From 282f8f6612e98153bdedf22791f4508560f3bfd6 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 11 Jun 2020 01:49:41 -0700 Subject: [PATCH] ams: delete exo1 --- exosphere/Makefile | 180 ----- exosphere/README.md | 6 - exosphere/linker.ld | 269 ------- exosphere/linker.specs | 4 - exosphere/lp0fw/Makefile | 154 ---- exosphere/lp0fw/linker.ld | 24 - exosphere/lp0fw/linker.specs | 7 - exosphere/lp0fw/src/car.c | 138 ---- exosphere/lp0fw/src/car.h | 110 --- exosphere/lp0fw/src/cluster.c | 163 ---- exosphere/lp0fw/src/cluster.h | 30 - exosphere/lp0fw/src/emc.c | 33 - exosphere/lp0fw/src/emc.h | 71 -- exosphere/lp0fw/src/flow.c | 31 - exosphere/lp0fw/src/flow.h | 35 - exosphere/lp0fw/src/fuse.c | 75 -- exosphere/lp0fw/src/fuse.h | 213 ----- exosphere/lp0fw/src/i2c.c | 76 -- exosphere/lp0fw/src/i2c.h | 48 -- exosphere/lp0fw/src/lp0.c | 98 --- exosphere/lp0fw/src/lp0.h | 35 - exosphere/lp0fw/src/mc.c | 40 - exosphere/lp0fw/src/mc.h | 622 --------------- exosphere/lp0fw/src/misc.c | 52 -- exosphere/lp0fw/src/misc.h | 39 - exosphere/lp0fw/src/pmc.h | 61 -- exosphere/lp0fw/src/se.c | 266 ------- exosphere/lp0fw/src/se.h | 179 ----- exosphere/lp0fw/src/secmon.c | 129 --- exosphere/lp0fw/src/secmon.h | 26 - exosphere/lp0fw/src/start.s | 65 -- exosphere/lp0fw/src/sysreg.h | 46 -- exosphere/lp0fw/src/timer.h | 34 - exosphere/lp0fw/src/utils.h | 39 - exosphere/rebootstub/Makefile | 154 ---- exosphere/rebootstub/linker.ld | 18 - exosphere/rebootstub/linker.specs | 7 - exosphere/rebootstub/src/i2c.c | 169 ---- exosphere/rebootstub/src/i2c.h | 51 -- exosphere/rebootstub/src/max77620.h | 360 --------- exosphere/rebootstub/src/shutdown.c | 30 - exosphere/rebootstub/src/start.s | 50 -- exosphere/rebootstub/src/timer.h | 33 - exosphere/rebootstub/src/utils.h | 38 - exosphere/sc7fw/Makefile | 154 ---- exosphere/sc7fw/linker.ld | 21 - exosphere/sc7fw/linker.specs | 7 - exosphere/sc7fw/src/emc.c | 73 -- exosphere/sc7fw/src/emc.h | 67 -- exosphere/sc7fw/src/i2c.c | 104 --- exosphere/sc7fw/src/i2c.h | 50 -- exosphere/sc7fw/src/pmc.h | 53 -- exosphere/sc7fw/src/sc7.c | 120 --- exosphere/sc7fw/src/sc7.h | 26 - exosphere/sc7fw/src/start.s | 40 - exosphere/sc7fw/src/timer.h | 33 - exosphere/sc7fw/src/utils.h | 38 - exosphere/src/actmon.c | 40 - exosphere/src/actmon.h | 41 - exosphere/src/arm.h | 40 - exosphere/src/arm.s | 316 -------- exosphere/src/bootconfig.c | 164 ---- exosphere/src/bootconfig.h | 94 --- exosphere/src/bootup.c | 381 --------- exosphere/src/bootup.h | 115 --- exosphere/src/bpmp.h | 44 -- exosphere/src/car.c | 87 -- exosphere/src/car.h | 58 -- exosphere/src/coldboot_init.c | 213 ----- exosphere/src/coldboot_main.c | 36 - exosphere/src/configitem.c | 308 -------- exosphere/src/configitem.h | 71 -- exosphere/src/cpu_context.c | 235 ------ exosphere/src/cpu_context.h | 83 -- exosphere/src/emummc_cfg.h | 67 -- exosphere/src/exceptions.s | 254 ------ exosphere/src/exocfg.c | 124 --- exosphere/src/exocfg.h | 79 -- exosphere/src/flow.h | 69 -- exosphere/src/fuse.c | 335 -------- exosphere/src/fuse.h | 234 ------ exosphere/src/gcm.c | 229 ------ exosphere/src/gcm.h | 37 - exosphere/src/i2c.c | 252 ------ exosphere/src/i2c.h | 113 --- exosphere/src/interrupt.c | 131 --- exosphere/src/interrupt.h | 80 -- exosphere/src/masterkey.c | 156 ---- exosphere/src/masterkey.h | 49 -- exosphere/src/mc.c | 162 ---- exosphere/src/mc.h | 631 --------------- exosphere/src/mc0.h | 32 - exosphere/src/mc1.h | 32 - exosphere/src/memory_map.h | 234 ------ exosphere/src/misc.h | 32 - exosphere/src/mmu.h | 193 ----- exosphere/src/my_libc.c | 1141 --------------------------- exosphere/src/package2.c | 637 --------------- exosphere/src/package2.h | 121 --- exosphere/src/panic_color.h | 39 - exosphere/src/pinmux.h | 214 ----- exosphere/src/pmc.h | 65 -- exosphere/src/preprocessor.h | 207 ----- exosphere/src/randomcache.c | 91 --- exosphere/src/randomcache.h | 29 - exosphere/src/rsa_common.c | 20 - exosphere/src/rsa_common.h | 36 - exosphere/src/sc7.c | 305 ------- exosphere/src/sc7.h | 28 - exosphere/src/se.c | 912 --------------------- exosphere/src/se.h | 231 ------ exosphere/src/sealedkeys.c | 91 --- exosphere/src/sealedkeys.h | 41 - exosphere/src/smc_ams.c | 290 ------- exosphere/src/smc_ams.h | 30 - exosphere/src/smc_api.c | 776 ------------------ exosphere/src/smc_api.h | 57 -- exosphere/src/smc_user.c | 1019 ------------------------ exosphere/src/smc_user.h | 47 -- exosphere/src/start.s | 300 ------- exosphere/src/synchronization.h | 139 ---- exosphere/src/sysctr0.h | 49 -- exosphere/src/sysreg.h | 49 -- exosphere/src/timers.c | 41 - exosphere/src/timers.h | 111 --- exosphere/src/titlekey.c | 180 ----- exosphere/src/titlekey.h | 33 - exosphere/src/uart.c | 135 ---- exosphere/src/uart.h | 178 ----- exosphere/src/userpage.c | 93 --- exosphere/src/userpage.h | 39 - exosphere/src/utils.c | 80 -- exosphere/src/utils.h | 134 ---- exosphere/src/warmboot_init.c | 221 ------ exosphere/src/warmboot_main.c | 108 --- 135 files changed, 19262 deletions(-) delete mode 100644 exosphere/Makefile delete mode 100644 exosphere/README.md delete mode 100644 exosphere/linker.ld delete mode 100644 exosphere/linker.specs delete mode 100644 exosphere/lp0fw/Makefile delete mode 100644 exosphere/lp0fw/linker.ld delete mode 100644 exosphere/lp0fw/linker.specs delete mode 100644 exosphere/lp0fw/src/car.c delete mode 100644 exosphere/lp0fw/src/car.h delete mode 100644 exosphere/lp0fw/src/cluster.c delete mode 100644 exosphere/lp0fw/src/cluster.h delete mode 100644 exosphere/lp0fw/src/emc.c delete mode 100644 exosphere/lp0fw/src/emc.h delete mode 100644 exosphere/lp0fw/src/flow.c delete mode 100644 exosphere/lp0fw/src/flow.h delete mode 100644 exosphere/lp0fw/src/fuse.c delete mode 100644 exosphere/lp0fw/src/fuse.h delete mode 100644 exosphere/lp0fw/src/i2c.c delete mode 100644 exosphere/lp0fw/src/i2c.h delete mode 100644 exosphere/lp0fw/src/lp0.c delete mode 100644 exosphere/lp0fw/src/lp0.h delete mode 100644 exosphere/lp0fw/src/mc.c delete mode 100644 exosphere/lp0fw/src/mc.h delete mode 100644 exosphere/lp0fw/src/misc.c delete mode 100644 exosphere/lp0fw/src/misc.h delete mode 100644 exosphere/lp0fw/src/pmc.h delete mode 100644 exosphere/lp0fw/src/se.c delete mode 100644 exosphere/lp0fw/src/se.h delete mode 100644 exosphere/lp0fw/src/secmon.c delete mode 100644 exosphere/lp0fw/src/secmon.h delete mode 100644 exosphere/lp0fw/src/start.s delete mode 100644 exosphere/lp0fw/src/sysreg.h delete mode 100644 exosphere/lp0fw/src/timer.h delete mode 100644 exosphere/lp0fw/src/utils.h delete mode 100644 exosphere/rebootstub/Makefile delete mode 100644 exosphere/rebootstub/linker.ld delete mode 100644 exosphere/rebootstub/linker.specs delete mode 100644 exosphere/rebootstub/src/i2c.c delete mode 100644 exosphere/rebootstub/src/i2c.h delete mode 100644 exosphere/rebootstub/src/max77620.h delete mode 100644 exosphere/rebootstub/src/shutdown.c delete mode 100644 exosphere/rebootstub/src/start.s delete mode 100644 exosphere/rebootstub/src/timer.h delete mode 100644 exosphere/rebootstub/src/utils.h delete mode 100644 exosphere/sc7fw/Makefile delete mode 100644 exosphere/sc7fw/linker.ld delete mode 100644 exosphere/sc7fw/linker.specs delete mode 100644 exosphere/sc7fw/src/emc.c delete mode 100644 exosphere/sc7fw/src/emc.h delete mode 100644 exosphere/sc7fw/src/i2c.c delete mode 100644 exosphere/sc7fw/src/i2c.h delete mode 100644 exosphere/sc7fw/src/pmc.h delete mode 100644 exosphere/sc7fw/src/sc7.c delete mode 100644 exosphere/sc7fw/src/sc7.h delete mode 100644 exosphere/sc7fw/src/start.s delete mode 100644 exosphere/sc7fw/src/timer.h delete mode 100644 exosphere/sc7fw/src/utils.h delete mode 100644 exosphere/src/actmon.c delete mode 100644 exosphere/src/actmon.h delete mode 100644 exosphere/src/arm.h delete mode 100644 exosphere/src/arm.s delete mode 100644 exosphere/src/bootconfig.c delete mode 100644 exosphere/src/bootconfig.h delete mode 100644 exosphere/src/bootup.c delete mode 100644 exosphere/src/bootup.h delete mode 100644 exosphere/src/bpmp.h delete mode 100644 exosphere/src/car.c delete mode 100644 exosphere/src/car.h delete mode 100644 exosphere/src/coldboot_init.c delete mode 100644 exosphere/src/coldboot_main.c delete mode 100644 exosphere/src/configitem.c delete mode 100644 exosphere/src/configitem.h delete mode 100644 exosphere/src/cpu_context.c delete mode 100644 exosphere/src/cpu_context.h delete mode 100644 exosphere/src/emummc_cfg.h delete mode 100644 exosphere/src/exceptions.s delete mode 100644 exosphere/src/exocfg.c delete mode 100644 exosphere/src/exocfg.h delete mode 100644 exosphere/src/flow.h delete mode 100644 exosphere/src/fuse.c delete mode 100644 exosphere/src/fuse.h delete mode 100644 exosphere/src/gcm.c delete mode 100644 exosphere/src/gcm.h delete mode 100644 exosphere/src/i2c.c delete mode 100644 exosphere/src/i2c.h delete mode 100644 exosphere/src/interrupt.c delete mode 100644 exosphere/src/interrupt.h delete mode 100644 exosphere/src/masterkey.c delete mode 100644 exosphere/src/masterkey.h delete mode 100644 exosphere/src/mc.c delete mode 100644 exosphere/src/mc.h delete mode 100644 exosphere/src/mc0.h delete mode 100644 exosphere/src/mc1.h delete mode 100644 exosphere/src/memory_map.h delete mode 100644 exosphere/src/misc.h delete mode 100644 exosphere/src/mmu.h delete mode 100644 exosphere/src/my_libc.c delete mode 100644 exosphere/src/package2.c delete mode 100644 exosphere/src/package2.h delete mode 100644 exosphere/src/panic_color.h delete mode 100644 exosphere/src/pinmux.h delete mode 100644 exosphere/src/pmc.h delete mode 100644 exosphere/src/preprocessor.h delete mode 100644 exosphere/src/randomcache.c delete mode 100644 exosphere/src/randomcache.h delete mode 100644 exosphere/src/rsa_common.c delete mode 100644 exosphere/src/rsa_common.h delete mode 100644 exosphere/src/sc7.c delete mode 100644 exosphere/src/sc7.h delete mode 100644 exosphere/src/se.c delete mode 100644 exosphere/src/se.h delete mode 100644 exosphere/src/sealedkeys.c delete mode 100644 exosphere/src/sealedkeys.h delete mode 100644 exosphere/src/smc_ams.c delete mode 100644 exosphere/src/smc_ams.h delete mode 100644 exosphere/src/smc_api.c delete mode 100644 exosphere/src/smc_api.h delete mode 100644 exosphere/src/smc_user.c delete mode 100644 exosphere/src/smc_user.h delete mode 100644 exosphere/src/start.s delete mode 100644 exosphere/src/synchronization.h delete mode 100644 exosphere/src/sysctr0.h delete mode 100644 exosphere/src/sysreg.h delete mode 100644 exosphere/src/timers.c delete mode 100644 exosphere/src/timers.h delete mode 100644 exosphere/src/titlekey.c delete mode 100644 exosphere/src/titlekey.h delete mode 100644 exosphere/src/uart.c delete mode 100644 exosphere/src/uart.h delete mode 100644 exosphere/src/userpage.c delete mode 100644 exosphere/src/userpage.h delete mode 100644 exosphere/src/utils.c delete mode 100644 exosphere/src/utils.h delete mode 100644 exosphere/src/warmboot_init.c delete mode 100644 exosphere/src/warmboot_main.c diff --git a/exosphere/Makefile b/exosphere/Makefile deleted file mode 100644 index 14a03900d..000000000 --- a/exosphere/Makefile +++ /dev/null @@ -1,180 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITPRO)/devkitA64/base_rules - -AMSBRANCH := $(shell git symbolic-ref --short HEAD) -AMSHASH = $(shell git rev-parse --short=16 HEAD) -AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) - -ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) - AMSREV := $(AMSREV)-dirty -endif - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := src src/dbg -DATA := data -INCLUDES := include ../libraries/libvapours/include - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv8-a -mtune=cortex-a57 -mgeneral-regs-only #<- important -DEFINES := -D__CCPLEX__ -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" -DATMOSPHERE_RELEASE_VERSION_HASH="0x$(AMSHASH)" -CFLAGS := \ - -g \ - -Os \ - -ffunction-sections \ - -fdata-sections \ - -fomit-frame-pointer \ - -fno-asynchronous-unwind-tables \ - -fno-unwind-tables \ - -std=gnu11 \ - -Werror \ - -Wall \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) - -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(TOPDIR)/linker.specs -nostartfiles -nostdlib -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ - $(TOPDIR)/lp0fw \ - $(TOPDIR)/sc7fw \ - $(TOPDIR)/rebootstub - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin lp0fw.bin rebootstub.bin - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -.PHONY: $(BUILD) build_sc7fw build_lp0fw build_rebootstub clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - -check_sc7fw: - @$(MAKE) -C sc7fw all - -check_lp0fw: - @$(MAKE) -C lp0fw all - -check_rebootstub: - @$(MAKE) -C rebootstub all - -$(BUILD): check_sc7fw check_lp0fw check_rebootstub - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @$(MAKE) -C $(TOPDIR)/sc7fw clean - @$(MAKE) -C $(TOPDIR)/lp0fw clean - @$(MAKE) -C $(TOPDIR)/rebootstub clean - @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf - - -#--------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -all : $(OUTPUT).bin - -$(OUTPUT).bin : $(OUTPUT).elf - $(OBJCOPY) -S -O binary $< $@ - @echo built ... $(notdir $@) - -$(OUTPUT).elf : $(OFILES) - -my_libc.o: CFLAGS += -fno-builtin - -%.elf: - @echo linking $(notdir $@) - $(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ - @$(NM) -CSn $@ > $(notdir $*.lst) - -$(OFILES_SRC) : $(HFILES_BIN) - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o %_bin.h: %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/exosphere/README.md b/exosphere/README.md deleted file mode 100644 index b4b8039cb..000000000 --- a/exosphere/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Exosphère -===== - -![License](https://img.shields.io/badge/License-GPLv2-blue.svg) - -Exosphère is a Secure Monitor implementation for the Nintendo Switch. diff --git a/exosphere/linker.ld b/exosphere/linker.ld deleted file mode 100644 index e1a694ea5..000000000 --- a/exosphere/linker.ld +++ /dev/null @@ -1,269 +0,0 @@ -OUTPUT_ARCH(aarch64) -ENTRY(__start_cold) - -MEMORY -{ - NULL : ORIGIN = 0, LENGTH = 4K - ccrt0 : ORIGIN = 0x040006000, LENGTH = 4K - glob : ORIGIN = 0x040020000, LENGTH = 128K - tzram : ORIGIN = 0x07C010000, LENGTH = 64K - /* - The warmboot crt0 is preceeded by the exception vector page and the L2 and L3 translation tables. - Normally the main code immediately follows the warmboot crt0, aligned to 256 bytes. - We can't ensure or replicate that behavior properly so we'll just give 2K to the warmboot crt0. - */ - warmboot_crt0 : ORIGIN = ORIGIN(tzram) + 12K, LENGTH = 2K - - /* 8K are the MMU L2 and L3 tables & 2K from the evt page */ - main : ORIGIN = 0x1F01E0000 + LENGTH(warmboot_crt0), LENGTH = LENGTH(tzram) - LENGTH(pk2ldr) - LENGTH(evt) - LENGTH(warmboot_crt0) - 10K - pk2ldr : ORIGIN = ORIGIN(main) - LENGTH(warmboot_crt0) + LENGTH(tzram), LENGTH = 8K - /* The first half of the page are exception entry stacks, the other half are the vectors themselves */ - evt : ORIGIN = ORIGIN(pk2ldr) + 40K + 2K, LENGTH = 2K -} - -SECTIONS -{ - PROVIDE(__start__ = 0x040006000); - . = __start__; - - .cold_crt0 : - { - . = ALIGN(64); - __cold_crt0_start__ = ABSOLUTE(.); - __glob_origin__ = ORIGIN(glob); - KEEP (*(.cold_crt0.text.start)) /* MUST be first */ - KEEP (*(.cold_crt0.text*)) - KEEP (coldboot_init.o(.text*)) - *(.cold_crt0.rodata*) - coldboot_init.o(.rodata*) - *(.cold_crt0.data*) - coldboot_init.o(.data*) - . = ALIGN(8); - *(.cold_crt0.bss*) - coldboot_init.o(.bss* COMMON) - . = ALIGN(64); - __cold_crt0_end__ = ABSOLUTE(.); - } >ccrt0 AT>glob - - .pk2ldr : - { - . = ALIGN(4096); - __pk2ldr_lma__ = LOADADDR(.pk2ldr); - __pk2ldr_start__ = ABSOLUTE(.); - KEEP (package2.o(.text*)) - package2.o(.rodata*) - package2.o(.data*) - . = ALIGN(8); - } >pk2ldr AT>glob - - .pk2ldr.bss : - { - . = ALIGN(8); - __pk2ldr_bss_start__ = ABSOLUTE(.); - package2.o(.bss* COMMON) - . = ALIGN(8); - __pk2ldr_end__ = ABSOLUTE(.); - } >pk2ldr AT>glob - - .vectors : - { - . = ALIGN(2048); - __vectors_lma__ = LOADADDR(.vectors); - __vectors_start__ = ABSOLUTE(.); - KEEP (*(.vectors*)) - . = ALIGN(8); - __vectors_end__ = ABSOLUTE(.); - } >evt AT>glob - - .warm_crt0 : - { - . = ALIGN(64); - __warmboot_crt0_lma__ = LOADADDR(.warm_crt0); - __warmboot_crt0_start__ = ABSOLUTE(.); - KEEP (*(.warm_crt0.text.start)) /* Should be first */ - KEEP (*(.warm_crt0.text*)) - KEEP (warmboot_init.o(.text*)) - *(.warm_crt0.rodata*) - warmboot_init.o(.rodata*) - *(.warm_crt0.data*) - warmboot_init.o(.data*) - . = ALIGN(8); - *(.warm_crt0.bss*) - warmboot_init.o(.bss*) - . = ALIGN(64); - __warmboot_crt0_end__ = ABSOLUTE(.); - } >warmboot_crt0 AT>glob - - .text : - { - . = ALIGN(256); - __main_lma__ = LOADADDR(.text); - __main_start__ = ABSOLUTE(.); - *(.text.unlikely .text.*_unlikely .text.unlikely.*) - *(.text.exit .text.exit.*) - *(.text.startup .text.startup.*) - *(.text.hot .text.hot.*) - *(.text .stub .text.* .gnu.linkonce.t.*) - . = ALIGN(8); - } >main AT>glob - - .init : - { - KEEP( *(.init) ) - . = ALIGN(8); - } >main AT>glob - - .plt : - { - *(.plt) - *(.iplt) - . = ALIGN(8); - } >main AT>glob - - - .fini : - { - KEEP( *(.fini) ) - . = ALIGN(8); - } >main AT>glob - - .rodata : - { - *(.rodata .rodata.* .gnu.linkonce.r.*) - SORT(CONSTRUCTORS) - . = ALIGN(8); - } >main AT>glob - - .got : { __got_start__ = ABSOLUTE(.); *(.got) *(.igot) } >main AT>glob - .got.plt : { *(.got.plt) *(.igot.plt) __got_end__ = ABSOLUTE(.);} >main AT>glob - - .preinit_array : - { - . = ALIGN(8); - PROVIDE (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE (__preinit_array_end = .); - . = ALIGN(8); - } >main AT>glob - - .init_array : - { - PROVIDE (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - PROVIDE (__init_array_end = .); - } >main AT>glob - - .fini_array : - { - . = ALIGN(8); - PROVIDE (__fini_array_start = .); - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE (__fini_array_end = .); - . = ALIGN(8); - } >main AT>glob - - .ctors : - { - . = ALIGN(8); - KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - . = ALIGN(8); - } >main AT>glob - - .dtors ALIGN(8) : - { - . = ALIGN(8); - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - . = ALIGN(8); - } >main AT>glob - - .data ALIGN(8) : - { - *(.data .data.* .gnu.linkonce.d.*) - CONSTRUCTORS - . = ALIGN(8); - } >main AT>glob - - - .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } >main AT>glob - .eh_frame : { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main AT>glob - .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } >main AT>glob - .gnu_extab : { *(.gnu_extab*) } >main AT>glob - .exception_ranges : { *(.exception_ranges .exception_ranges*) } >main AT>glob - - .dynamic : { *(.dynamic) } >main AT>glob - .interp : { *(.interp) } >main AT>glob - .note.gnu.build-id : { *(.note.gnu.build-id) } >main AT>glob - .hash : { *(.hash) } >main AT>glob - .gnu.hash : { *(.gnu.hash) } >main AT>glob - .gnu.version : { *(.gnu.version) } >main AT>glob - .gnu.version_d : { *(.gnu.version_d) } >main AT>glob - .gnu.version_r : { *(.gnu.version_r) } >main AT>glob - .dynsym : { *(.dynsym) } >main AT>glob - .dynstr : { *(.dynstr) } >main AT>glob - .rela.dyn : { *(.rela.*); __main_end__ = ABSOLUTE(.);} >main AT>glob - - .bss : - { - . = ALIGN(8); - __main_bss_start__ = ABSOLUTE(.); - __loaded_end_lma__ = LOADADDR(.bss); - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - . = ALIGN(8); - __main_end__ = ABSOLUTE(.); - } >main AT>glob - - __end__ = ABSOLUTE(.) ; - - . = ALIGN(0x1000); - __argdata__ = ABSOLUTE(.) ; - - /* ================== - ==== Metadata ==== - ================== */ - - /* Discard sections that difficult post-processing */ - /DISCARD/ : { *(.group .comment .note) } - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } -} \ No newline at end of file diff --git a/exosphere/linker.specs b/exosphere/linker.specs deleted file mode 100644 index fb0cb34bc..000000000 --- a/exosphere/linker.specs +++ /dev/null @@ -1,4 +0,0 @@ -%rename link old_link - -*link: -%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections diff --git a/exosphere/lp0fw/Makefile b/exosphere/lp0fw/Makefile deleted file mode 100644 index a1073d35e..000000000 --- a/exosphere/lp0fw/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITARM)/base_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := src -DATA := data -INCLUDES := include ../../libraries/libvapours/include - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork - -CFLAGS := \ - -g \ - -Os \ - -ffunction-sections \ - -fdata-sections \ - -fomit-frame-pointer \ - -fno-inline \ - -std=gnu11 \ - -Werror \ - -Wall \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) -D__BPMP__ - -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf - - -#--------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -all : $(OUTPUT).bin - -$(OUTPUT).bin : $(OUTPUT).elf - $(OBJCOPY) -S -O binary $< $@ - @echo built ... $(notdir $@) - -$(OUTPUT).elf : $(OFILES) - -%.elf: $(OFILES) - @echo linking $(notdir $@) - @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ - @$(NM) -CSn $@ > $(notdir $*.lst) - -$(OFILES_SRC) : $(HFILES_BIN) - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/exosphere/lp0fw/linker.ld b/exosphere/lp0fw/linker.ld deleted file mode 100644 index 165608360..000000000 --- a/exosphere/lp0fw/linker.ld +++ /dev/null @@ -1,24 +0,0 @@ -OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") -OUTPUT_ARCH(arm) - -ENTRY(_start) -SECTIONS -{ - . = 0x40010000; - - __start__ = ABSOLUTE(.); - - .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } - .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } - .bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; } - - . = ALIGN(4); - - __end__ = ABSOLUTE(.); - - __total_size__ = (__end__ - __start__); - __executable_size__ = (__end__ - _start); - - __stack_top__ = 0x40013000; - __stack_bottom__ = 0x40012000; -} \ No newline at end of file diff --git a/exosphere/lp0fw/linker.specs b/exosphere/lp0fw/linker.specs deleted file mode 100644 index 300990418..000000000 --- a/exosphere/lp0fw/linker.specs +++ /dev/null @@ -1,7 +0,0 @@ -%rename link old_link - -*link: -%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections - -*startfile: -crti%O%s crtbegin%O%s diff --git a/exosphere/lp0fw/src/car.c b/exosphere/lp0fw/src/car.c deleted file mode 100644 index 03bc687cd..000000000 --- a/exosphere/lp0fw/src/car.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 "utils.h" -#include "car.h" -#include "timer.h" -#include "pmc.h" -#include "emc.h" -#include "lp0.h" - -static inline uint32_t get_special_clk_reg(CarDevice dev) { - switch (dev) { - case CARDEVICE_UARTA: return 0x178; - case CARDEVICE_UARTB: return 0x17C; - case CARDEVICE_I2C1: return 0x124; - case CARDEVICE_I2C5: return 0x128; - case CARDEVICE_ACTMON: return 0x3E8; - case CARDEVICE_BPMP: return 0; - default: reboot(); - } -} - -static inline uint32_t get_special_clk_val(CarDevice dev) { - switch (dev) { - case CARDEVICE_UARTA: return 0; - case CARDEVICE_UARTB: return 0; - case CARDEVICE_I2C1: return (6 << 29); - case CARDEVICE_I2C5: return (6 << 29); - case CARDEVICE_ACTMON: return (6 << 29); - case CARDEVICE_BPMP: return 0; - default: reboot(); - } -} - -static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; -static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; - -static uint32_t g_clk_clr_reg_offsets[NUM_CAR_BANKS] = {0x324, 0x32C, 0x334, 0x444, 0x44C, 0x228, 0x2A0}; - -void car_configure_oscillators(void) { - /* Enable the crystal oscillator, setting drive strength to the saved value in PMC. */ - CLK_RST_CONTROLLER_OSC_CTRL_0 = (CLK_RST_CONTROLLER_OSC_CTRL_0 & 0xFFFFFC0E) | 1 | (((APBDEV_PMC_OSC_EDPD_OVER_0 >> 1) & 0x3F) << 4); - - /* Set CLK_M_DIVISOR to 1 (causes actual division by 2.) */ - CLK_RST_CONTROLLER_SPARE_REG0_0 = (1 << 2); - /* Reading the register after writing it is required to ensure value takes. */ - (void)(CLK_RST_CONTROLLER_SPARE_REG0_0); - - /* Set TIMERUS_USEC_CFG to cycle at 0x60 / 0x5 = 19.2 MHz. */ - /* Value is (dividend << 8) | (divisor). */ - TIMERUS_USEC_CFG_0 = 0x45F; -} - -void car_mbist_workaround(void) { - /* This code works around MBIST bug. */ - - /* Clear LVL2_CLK_GATE_OVR* registers. */ - CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 = 0; - CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 = 0; - CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 = 0; - CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 = 0; - CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 = 0; - - /* Clear bit patterns in CAR. */ - /* L: Reset all but RTC, TMR, GPIO, BPMP Cache (CACHE2). */ - MAKE_CAR_REG(g_clk_clr_reg_offsets[0]) = MAKE_CAR_REG(g_clk_reg_offsets[0]) & 0x7FFFFECF; - /* H: Reset all but MC, PMC, FUSE, EMC. */ - MAKE_CAR_REG(g_clk_clr_reg_offsets[1]) = MAKE_CAR_REG(g_clk_reg_offsets[1]) & 0xFDFFFF3E; - /* U: Reset all but CSITE, IRAM[A-D], BPMP Cache RAM (CRAM2). */ - MAKE_CAR_REG(g_clk_clr_reg_offsets[2]) = MAKE_CAR_REG(g_clk_reg_offsets[2]) & 0xFE0FFDFF; - /* V: Reset all but MSELECT, S/PDIF audio doubler, TZRAM, SE. */ - MAKE_CAR_REG(g_clk_clr_reg_offsets[3]) = MAKE_CAR_REG(g_clk_reg_offsets[3]) & 0x3FBFFFF7; - /* W: Reset all but PCIERX[0-5], ENTROPY. */ - MAKE_CAR_REG(g_clk_clr_reg_offsets[4]) = MAKE_CAR_REG(g_clk_reg_offsets[4]) & 0xFFDFFF03; - /* X: Reset all but ETC, MCLK, MCLK2, I2C6, EMC_DLL, GPU, DBGAPB, PLLG_REF, . */ - MAKE_CAR_REG(g_clk_clr_reg_offsets[5]) = MAKE_CAR_REG(g_clk_reg_offsets[5]) & 0xDCFFB87F; - /* Y: Reset all but MC_CDPA, MC_CCPA. */ - MAKE_CAR_REG(g_clk_clr_reg_offsets[6]) = MAKE_CAR_REG(g_clk_reg_offsets[6]) & 0xFFFFFCFF; - - /* Enable clock to MC1, if CH1 is enabled in EMC. */ - if (EMC_FBIO_CFG7_0 & 4) { /* CH1_ENABLE */ - CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 |= 0x40000000; /* SET_CLK_ENB_MC1 */ - } -} - -void clk_enable(CarDevice dev) { - uint32_t special_reg; - if ((special_reg = get_special_clk_reg(dev))) { - MAKE_CAR_REG(special_reg) = get_special_clk_val(dev); - } - MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); -} - -void clk_disable(CarDevice dev) { - MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); -} - -void rst_enable(CarDevice dev) { - MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); -} - -void rst_disable(CarDevice dev) { - MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); -} - -void clkrst_enable(CarDevice dev) { - clk_enable(dev); - rst_disable(dev); -} - -void clkrst_disable(CarDevice dev) { - rst_enable(dev); - clk_disable(dev); -} - -void clkrst_reboot(CarDevice dev) { - clkrst_disable(dev); - clkrst_enable(dev); -} - -void clkrst_enable_fuse_regs(bool enable) { - CLK_RST_CONTROLLER_MISC_CLK_ENB_0 = ((CLK_RST_CONTROLLER_MISC_CLK_ENB_0 & 0xEFFFFFFF) | ((enable & 1) << 28)); -} \ No newline at end of file diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h deleted file mode 100644 index 509672d1c..000000000 --- a/exosphere/lp0fw/src/car.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_CLOCK_AND_RESET_H -#define EXOSPHERE_WARMBOOT_BIN_CLOCK_AND_RESET_H - -#include - -#define CAR_BASE 0x60006000 - -#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) - -#define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048) -#define CLK_RST_CONTROLLER_OSC_CTRL_0 MAKE_CAR_REG(0x050) -#define CLK_RST_CONTROLLER_PLLX_BASE_0 MAKE_CAR_REG(0x0E0) -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) - -#define CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 MAKE_CAR_REG(0x36C) -#define CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 MAKE_CAR_REG(0x374) - -#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5_0 MAKE_CAR_REG(0x128) - -#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 MAKE_CAR_REG(0x62C) -#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 MAKE_CAR_REG(0x630) - -#define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0 MAKE_CAR_REG(0x388) -#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT_0 MAKE_CAR_REG(0x3B4) - -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 MAKE_CAR_REG(0x0F8) -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 MAKE_CAR_REG(0x0FC) -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 MAKE_CAR_REG(0x3A0) -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 MAKE_CAR_REG(0x554) - -#define CLK_RST_CONTROLLER_CCLKG_BURST_POLICY_0 MAKE_CAR_REG(0x368) -#define CLK_RST_CONTROLLER_CCLKP_BURST_POLICY_0 MAKE_CAR_REG(0x370) - -#define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) - -#define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C) - -#define CLK_RST_CONTROLLER_RST_DEV_H_SET_0 MAKE_CAR_REG(0x308) -#define CLK_RST_CONTROLLER_RST_DEV_U_SET_0 MAKE_CAR_REG(0x310) - -#define CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 MAKE_CAR_REG(0x30C) -#define CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 MAKE_CAR_REG(0x314) -#define CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 MAKE_CAR_REG(0x434) - -#define CLK_RST_CONTROLLER_CLK_ENB_L_SET_0 MAKE_CAR_REG(0x320) -#define CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 MAKE_CAR_REG(0x328) -#define CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 MAKE_CAR_REG(0x330) -#define CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 MAKE_CAR_REG(0x440) -#define CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 MAKE_CAR_REG(0x448) -#define CLK_RST_CONTROLLER_CLK_ENB_Y_SET_0 MAKE_CAR_REG(0x29C) - -#define CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 MAKE_CAR_REG(0x32C) -#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 MAKE_CAR_REG(0x44C) - -#define NUM_CAR_BANKS 7 - -typedef enum { - CARDEVICE_UARTA = ((0 << 5) | 0x6), - CARDEVICE_UARTB = ((0 << 5) | 0x7), - CARDEVICE_UARTC = ((1 << 5) | 0x17), - CARDEVICE_I2C1 = ((0 << 5) | 0xC), - CARDEVICE_I2C5 = ((1 << 5) | 0xF), - CARDEVICE_TZRAM = ((3 << 5) | 0x1E), - CARDEVICE_SE = ((3 << 5) | 0x1F), - CARDEVICE_HOST1X = ((0 << 5) | 0x1C), - CARDEVICE_TSEC = ((2 << 5) | 0x13), - CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E), - CARDEVICE_SOR0 = ((5 << 5) | 0x16), - CARDEVICE_SOR1 = ((5 << 5) | 0x17), - CARDEVICE_KFUSE = ((1 << 5) | 0x8), - CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B), - CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), - CARDEVICE_ACTMON = ((3 << 5) | 0x17), - CARDEVICE_BPMP = ((0 << 5) | 0x1) -} CarDevice; - -void car_configure_oscillators(void); -void car_mbist_workaround(void); - -void clk_enable(CarDevice dev); -void clk_disable(CarDevice dev); -void rst_enable(CarDevice dev); -void rst_disable(CarDevice dev); - -void clkrst_enable(CarDevice dev); -void clkrst_disable(CarDevice dev); -void clkrst_reboot(CarDevice dev); - -void clkrst_enable_fuse_regs(bool enable); - -#endif diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c deleted file mode 100644 index 71692f2cd..000000000 --- a/exosphere/lp0fw/src/cluster.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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 "utils.h" -#include "cluster.h" -#include "car.h" -#include "timer.h" -#include "pmc.h" -#include "misc.h" -#include "i2c.h" -#include "flow.h" -#include "sysreg.h" - -static void cluster_pmc_enable_partition(uint32_t mask, uint32_t toggle) { - /* Set toggle if unset. */ - if (!(APBDEV_PMC_PWRGATE_STATUS_0 & mask)) { - APBDEV_PMC_PWRGATE_TOGGLE_0 = toggle; - } - - /* Wait until toggle set. */ - while (!(APBDEV_PMC_PWRGATE_STATUS_0 & mask)) { } - - /* Remove clamping. */ - APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = mask; - while (APBDEV_PMC_CLAMP_STATUS_0 & mask) { } -} - -void cluster_initialize_cpu(void) { - /* Hold CoreSight in reset. */ - CLK_RST_CONTROLLER_RST_DEV_U_SET_0 = 0x200; - - /* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */ - CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0 &= 0xFFFFF000; - - /* Restore SB_AA64_RESET values from PMC scratch. */ - SB_AA64_RESET_LOW_0 = APBDEV_PMC_SECURE_SCRATCH34_0 | 1; - SB_AA64_RESET_HIGH_0 = APBDEV_PMC_SECURE_SCRATCH35_0; - - /* Set CDIV_ENB for CCLKG/CCLKP. */ - CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 = 0x80000000; - CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 = 0x80000000; - - /* Enable CoreSight clock, take CoreSight out of reset. */ - CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 = 0x200; - CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 = 0x200; - - /* Configure MSELECT to divide by 4, enable MSELECT clock. */ - CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT_0 = 6; /* (6/2) + 1 = 4. */ - CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 = 0x8; - - /* Wait 2 us, then take MSELECT out of reset. */ - timer_wait(2); - CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 = 0x8; - - /* Set MSELECT WRAP_TO_SLAVE_INCR[0-2], clear ERR_RESP_EN_SLAVE[1-2]. */ - MSELECT_CONFIG_0 = (MSELECT_CONFIG_0 & 0xFCFFFFFF) | 0x38000000; - - /* Clear PLLX_ENABLE. */ - CLK_RST_CONTROLLER_PLLX_BASE_0 &= 0xBFFFFFFF; - - /* Clear PMC scratch 190, disable PMC DPD then wait 10 us. */ - APBDEV_PMC_SCRATCH190_0 &= 0xFFFFFFFE; - APBDEV_PMC_DPD_SAMPLE_0 = 0; - timer_wait(10); - - /* Configure UART2 via GPIO controller 2 G. */ - MAKE_REG32(0x6000D108) |= 4; /* GPIO_CNF */ - MAKE_REG32(0x6000D118) |= 4; /* GPIO_OE */ - MAKE_REG32(0x6000D128) &= ~4; /* GPIO_OUT */ - - /* Set CL_DVFS RSVD0 + TRISTATE, read register to make it stick. */ - PINMUX_AUX_DVFS_PWM_0 = 0x11; - (void)PINMUX_AUX_DVFS_PWM_0; - - /* Configure I2C. */ - PINMUX_AUX_PWR_I2C_SCL_0 = 0x40; - PINMUX_AUX_PWR_I2C_SDA_0 = 0x40; - - /* Enable clock to CL_DVFS, and set its source/divider. */ - CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 = 0x08000000; - CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 = 0xE; - CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 = 0xE; - - /* Power on I2C5, wait 5 us, set source + take out of reset. */ - CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 = 0x8000; - CLK_RST_CONTROLLER_RST_DEV_H_SET_0 = 0x8000; - timer_wait(5); - CLK_RST_CONTROLLER_CLK_SOURCE_I2C5_0 = 0x4; - CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 = 0x8000; - - /* Enable the PMIC, wait 2ms. */ - i2c_enable_pmic(); - timer_wait(2000); - - /* Enable power to the CRAIL partition. */ - cluster_pmc_enable_partition(1, 0x100); - - /* Remove SW clamp to CRAIL. */ - APBDEV_PMC_SET_SW_CLAMP_0 = 0; - APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = 1; - while (APBDEV_PMC_CLAMP_STATUS_0 & 1) { } - - /* Nintendo manually counts down from 8. I am not sure why this happens. */ - { - volatile int32_t counter = 8; - while (counter >= 0) { - counter--; - } - } - - /* Power off I2C5. */ - CLK_RST_CONTROLLER_RST_DEV_H_SET_0 = 0x8000; - CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 = 0x8000; - - /* Disable clock to CL_DVFS */ - CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 = 0x08000000; - - /* Perform RAM repair if necessary. */ - flow_perform_ram_repair(); - - /* Enable power to the non-CPU partition. */ - cluster_pmc_enable_partition(0x8000, 0x10F); - - /* Enable clock to PLLP_OUT_CPU, wait 2 us. */ - CLK_RST_CONTROLLER_CLK_ENB_Y_SET_0 = 0x80000000; - timer_wait(2); - - /* Enable clock to CPU, CPUG, wait 10 us. */ - CLK_RST_CONTROLLER_CLK_ENB_L_SET_0 = 1; - CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 = 1; - timer_wait(10); - - /* Set CPU clock sources to PLLP_OUT_0 + state to RUN, wait 10 us. */ - CLK_RST_CONTROLLER_CCLKG_BURST_POLICY_0 = 0x20004444; - CLK_RST_CONTROLLER_CCLKP_BURST_POLICY_0 = 0x20004444; - timer_wait(10); - - /* Take non-CPU out of reset (write CLR_NONCPURESET). */ - CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = 0x20000000; -} - -void cluster_power_on_cpu(void) { - /* Enable power to CE0 partition. */ - cluster_pmc_enable_partition(0x4000, 0x10E); - - /* Clear CPU reset. */ - CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = 0x10001; -} \ No newline at end of file diff --git a/exosphere/lp0fw/src/cluster.h b/exosphere/lp0fw/src/cluster.h deleted file mode 100644 index e8db7cfbb..000000000 --- a/exosphere/lp0fw/src/cluster.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_CLUSTER_H -#define EXOSPHERE_WARMBOOT_BIN_CLUSTER_H - -#include - -#include "utils.h" - -#define MSELECT_CONFIG_0 MAKE_REG32(0x50060000) - -void cluster_initialize_cpu(void); -void cluster_power_on_cpu(void); - -#endif diff --git a/exosphere/lp0fw/src/emc.c b/exosphere/lp0fw/src/emc.c deleted file mode 100644 index 91888920d..000000000 --- a/exosphere/lp0fw/src/emc.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 "utils.h" -#include "lp0.h" -#include "emc.h" -#include "pmc.h" -#include "timer.h" - -void emc_configure_pmacro_training(void) { - /* Set DISABLE_CFG_BYTEN for all N. */ - EMC_PMACRO_CFG_PM_GLOBAL_0_0 = 0xFF0000; - - /* Set CHN_TRAINING_E_WRPTR for channel 0 + channel 1. */ - EMC_PMACRO_TRAINING_CTRL_0_0 = 8; - EMC_PMACRO_TRAINING_CTRL_1_0 = 8; - - /* Clear DISABLE_CFG_BYTEN for all N. */ - EMC_PMACRO_CFG_PM_GLOBAL_0_0 = 0x0; -} \ No newline at end of file diff --git a/exosphere/lp0fw/src/emc.h b/exosphere/lp0fw/src/emc.h deleted file mode 100644 index f8643e1ad..000000000 --- a/exosphere/lp0fw/src/emc.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_EMC_H -#define EXOSPHERE_WARMBOOT_BIN_EMC_H - -#include "utils.h" - -#define EMC_BASE (0x7001B000) - -#define EMC0_BASE (0x7001E000) -#define EMC1_BASE (0x7001F000) - - -#define MAKE_EMC_REG(ofs) (MAKE_REG32(EMC_BASE + ofs)) - -#define MAKE_EMC0_REG(ofs) (MAKE_REG32(EMC0_BASE + ofs)) -#define MAKE_EMC1_REG(ofs) (MAKE_REG32(EMC1_BASE + ofs)) - -#define EMC_CFG_0 MAKE_EMC_REG(0x00C) - -#define EMC_ADR_CFG_0 MAKE_EMC_REG(0x10) - -#define EMC_TIMING_CONTROL_0 MAKE_EMC_REG(0x028) - -#define EMC_SELF_REF_0 MAKE_EMC_REG(0x0E0) - -#define EMC_MRW_0 MAKE_EMC_REG(0x0E8) - -#define EMC_FBIO_CFG5_0 MAKE_EMC_REG(0x104) - -#define EMC_MRW3_0 MAKE_EMC_REG(0x138) - -#define EMC_AUTO_CAL_CONFIG_0 MAKE_EMC_REG(0x2A4) - -#define EMC_REQ_CTRL_0 MAKE_EMC_REG(0x2B0) - -#define EMC_EMC_STATUS_0 MAKE_EMC_REG(0x2B4) -#define EMC0_EMC_STATUS_0 MAKE_EMC0_REG(0x2B4) -#define EMC1_EMC_STATUS_0 MAKE_EMC1_REG(0x2B4) - -#define EMC_CFG_DIG_DLL_0 MAKE_EMC_REG(0x2BC) -#define EMC0_CFG_DIG_DLL_0 MAKE_EMC0_REG(0x2BC) -#define EMC1_CFG_DIG_DLL_0 MAKE_EMC1_REG(0x2BC) - -#define EMC_ZCAL_INTERVAL_0 MAKE_EMC_REG(0x2E0) - -#define EMC_PMC_SCRATCH3_0 MAKE_EMC_REG(0x448) - -#define EMC_FBIO_CFG7_0 MAKE_EMC_REG(0x584) - -#define EMC_PMACRO_CFG_PM_GLOBAL_0_0 MAKE_EMC_REG(0xC30) -#define EMC_PMACRO_TRAINING_CTRL_0_0 MAKE_EMC_REG(0xCF8) -#define EMC_PMACRO_TRAINING_CTRL_1_0 MAKE_EMC_REG(0xCFC) - -void emc_configure_pmacro_training(void); - -#endif diff --git a/exosphere/lp0fw/src/flow.c b/exosphere/lp0fw/src/flow.c deleted file mode 100644 index 9066ae9cb..000000000 --- a/exosphere/lp0fw/src/flow.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 "utils.h" -#include "flow.h" - -void flow_perform_ram_repair(void) { - /* Perform repair only if not active cluster. */ - if (!(FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 & 1)) { - /* Set REQ, to begin RAM repair. */ - FLOW_CTLR_RAM_REPAIR_0 = 1; - - /* Wait for STS to say RAM repair has completed. */ - while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)) { } - } -} \ No newline at end of file diff --git a/exosphere/lp0fw/src/flow.h b/exosphere/lp0fw/src/flow.h deleted file mode 100644 index bb27ad4c2..000000000 --- a/exosphere/lp0fw/src/flow.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_FLOW_CTLR_H -#define EXOSPHERE_WARMBOOT_BIN_FLOW_CTLR_H - -#include -#include - -#include "utils.h" - -#define FLOW_BASE (0x60007000) - -#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_BASE + ofs) - -#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) -#define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040) -#define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098) - -void flow_perform_ram_repair(void); - -#endif diff --git a/exosphere/lp0fw/src/fuse.c b/exosphere/lp0fw/src/fuse.c deleted file mode 100644 index 5ddf7e00d..000000000 --- a/exosphere/lp0fw/src/fuse.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 "utils.h" -#include "fuse.h" -#include "car.h" -#include "pmc.h" - -#define NUM_FUSE_BYPASS_ENTRIES 0 - -bool fuse_check_downgrade_status(void) { - /* We aren't going to implement anti-downgrade. */ - return false; -} - -void fuse_disable_programming(void) { - FUSE_REGS->FUSE_DISABLEREGPROGRAM = 1; -} - -static fuse_bypass_data_t g_fuse_bypass_entries[NUM_FUSE_BYPASS_ENTRIES] = { - /* No entries here. */ -}; - -void fuse_configure_fuse_bypass(void) { - /* Make all fuse registers visible. */ - clkrst_enable_fuse_regs(true); - - /* Configure bypass/override, only if programming is allowed. */ - if (!(FUSE_REGS->FUSE_DISABLEREGPROGRAM & 1)) { - /* Enable write access and flush status. */ - FUSE_REGS->FUSE_WRITE_ACCESS_SW = (FUSE_REGS->FUSE_WRITE_ACCESS_SW & ~0x1) | 0x10000; - - /* Enable fuse bypass config. */ - FUSE_REGS->FUSE_FUSEBYPASS = 1; - - /* Override fuses. */ - for (size_t i = 0; i < NUM_FUSE_BYPASS_ENTRIES; i++) { - MAKE_FUSE_REG(g_fuse_bypass_entries[i].offset) = g_fuse_bypass_entries[i].value; - } - - /* Disable fuse write access. */ - FUSE_REGS->FUSE_WRITE_ACCESS_SW |= 1; - - /* Enable fuse bypass config. */ - /* I think this is a bug, and Nintendo meant to write 0 here? */ - FUSE_REGS->FUSE_FUSEBYPASS = 1; - - /* This...clears the disable programming bit(?). */ - /* I have no idea why this happens. What? */ - /* This is probably also either a bug or does nothing. */ - /* Is this bit even clearable? */ - FUSE_REGS->FUSE_DISABLEREGPROGRAM &= 0xFFFFFFFE; - - /* Restore saved private key disable bit. */ - FUSE_REGS->FUSE_PRIVATEKEYDISABLE |= (APBDEV_PMC_SECURE_SCRATCH21_0 & 0x10); - - /* Lock private key disable secure scratch. */ - APBDEV_PMC_SEC_DISABLE2_0 |= 0x4000000; - } -} \ No newline at end of file diff --git a/exosphere/lp0fw/src/fuse.h b/exosphere/lp0fw/src/fuse.h deleted file mode 100644 index ae6d350e9..000000000 --- a/exosphere/lp0fw/src/fuse.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_FUSE_H -#define EXOSPHERE_WARMBOOT_BIN_FUSE_H - -#include -#include - -#include "utils.h" - -typedef struct { - uint32_t FUSE_FUSECTRL; - uint32_t FUSE_FUSEADDR; - uint32_t FUSE_FUSERDATA; - uint32_t FUSE_FUSEWDATA; - uint32_t FUSE_FUSETIME_RD1; - uint32_t FUSE_FUSETIME_RD2; - uint32_t FUSE_FUSETIME_PGM1; - uint32_t FUSE_FUSETIME_PGM2; - uint32_t FUSE_PRIV2INTFC_START; - uint32_t FUSE_FUSEBYPASS; - uint32_t FUSE_PRIVATEKEYDISABLE; - uint32_t FUSE_DISABLEREGPROGRAM; - uint32_t FUSE_WRITE_ACCESS_SW; - uint32_t FUSE_PWR_GOOD_SW; - uint32_t _0x38; - uint32_t FUSE_PRIV2RESHIFT; - uint32_t _0x40[0x3]; - uint32_t FUSE_FUSETIME_RD3; - uint32_t _0x50[0xC]; - uint32_t FUSE_PRIVATE_KEY0_NONZERO; - uint32_t FUSE_PRIVATE_KEY1_NONZERO; - uint32_t FUSE_PRIVATE_KEY2_NONZERO; - uint32_t FUSE_PRIVATE_KEY3_NONZERO; - uint32_t FUSE_PRIVATE_KEY4_NONZERO; - uint32_t _0x90[0x1C]; -} tegra_fuse_t; - -typedef struct { - uint32_t FUSE_PRODUCTION_MODE; - uint32_t FUSE_JTAG_SECUREID_VALID; - uint32_t FUSE_ODM_LOCK; - uint32_t FUSE_OPT_OPENGL_EN; - uint32_t FUSE_SKU_INFO; - uint32_t FUSE_CPU_SPEEDO_0_CALIB; - uint32_t FUSE_CPU_IDDQ_CALIB; - uint32_t FUSE_DAC_CRT_CALIB; - uint32_t FUSE_DAC_HDTV_CALIB; - uint32_t FUSE_DAC_SDTV_CALIB; - uint32_t FUSE_OPT_FT_REV; - uint32_t FUSE_CPU_SPEEDO_1_CALIB; - uint32_t FUSE_CPU_SPEEDO_2_CALIB; - uint32_t FUSE_SOC_SPEEDO_0_CALIB; - uint32_t FUSE_SOC_SPEEDO_1_CALIB; - uint32_t FUSE_SOC_SPEEDO_2_CALIB; - uint32_t FUSE_SOC_IDDQ_CALIB; - uint32_t FUSE_RESERVED_PRODUCTION_WP; - uint32_t FUSE_FA; - uint32_t FUSE_RESERVED_PRODUCTION; - uint32_t FUSE_HDMI_LANE0_CALIB; - uint32_t FUSE_HDMI_LANE1_CALIB; - uint32_t FUSE_HDMI_LANE2_CALIB; - uint32_t FUSE_HDMI_LANE3_CALIB; - uint32_t FUSE_ENCRYPTION_RATE; - uint32_t FUSE_PUBLIC_KEY[0x8]; - uint32_t FUSE_TSENSOR1_CALIB; - uint32_t FUSE_TSENSOR2_CALIB; - uint32_t FUSE_VSENSOR_CALIB; - uint32_t FUSE_OPT_CP_REV; - uint32_t FUSE_OPT_PFG; - uint32_t FUSE_TSENSOR0_CALIB; - uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE; - uint32_t FUSE_SECURITY_MODE; - uint32_t FUSE_PRIVATE_KEY[0x5]; - uint32_t FUSE_ARM_JTAG_DIS; - uint32_t FUSE_BOOT_DEVICE_INFO; - uint32_t FUSE_RESERVED_SW; - uint32_t FUSE_OPT_VP9_DISABLE; - uint32_t FUSE_RESERVED_ODM[0x8]; - uint32_t FUSE_OBS_DIS; - uint32_t FUSE_NOR_INFO; - uint32_t FUSE_USB_CALIB; - uint32_t FUSE_SKU_DIRECT_CONFIG; - uint32_t FUSE_KFUSE_PRIVKEY_CTRL; - uint32_t FUSE_PACKAGE_INFO; - uint32_t FUSE_OPT_VENDOR_CODE; - uint32_t FUSE_OPT_FAB_CODE; - uint32_t FUSE_OPT_LOT_CODE_0; - uint32_t FUSE_OPT_LOT_CODE_1; - uint32_t FUSE_OPT_WAFER_ID; - uint32_t FUSE_OPT_X_COORDINATE; - uint32_t FUSE_OPT_Y_COORDINATE; - uint32_t FUSE_OPT_SEC_DEBUG_EN; - uint32_t FUSE_OPT_OPS_RESERVED; - uint32_t FUSE_SATA_CALIB; - uint32_t FUSE_GPU_IDDQ_CALIB; - uint32_t FUSE_TSENSOR3_CALIB; - uint32_t FUSE_SKU_BOND_OUT_L; - uint32_t FUSE_SKU_BOND_OUT_H; - uint32_t FUSE_SKU_BOND_OUT_U; - uint32_t FUSE_SKU_BOND_OUT_V; - uint32_t FUSE_SKU_BOND_OUT_W; - uint32_t FUSE_OPT_SAMPLE_TYPE; - uint32_t FUSE_OPT_SUBREVISION; - uint32_t FUSE_OPT_SW_RESERVED_0; - uint32_t FUSE_OPT_SW_RESERVED_1; - uint32_t FUSE_TSENSOR4_CALIB; - uint32_t FUSE_TSENSOR5_CALIB; - uint32_t FUSE_TSENSOR6_CALIB; - uint32_t FUSE_TSENSOR7_CALIB; - uint32_t FUSE_OPT_PRIV_SEC_EN; - uint32_t FUSE_PKC_DISABLE; - uint32_t _0x16C; - uint32_t _0x170; - uint32_t _0x174; - uint32_t _0x178; - uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE; - uint32_t FUSE_TSENSOR_COMMON; - uint32_t FUSE_OPT_CP_BIN; - uint32_t FUSE_OPT_GPU_DISABLE; - uint32_t FUSE_OPT_FT_BIN; - uint32_t FUSE_OPT_DONE_MAP; - uint32_t _0x194; - uint32_t FUSE_APB2JTAG_DISABLE; - uint32_t FUSE_ODM_INFO; - uint32_t _0x1A0; - uint32_t _0x1A4; - uint32_t FUSE_ARM_CRYPT_DE_FEATURE; - uint32_t _0x1AC; - uint32_t _0x1B0; - uint32_t _0x1B4; - uint32_t _0x1B8; - uint32_t _0x1BC; - uint32_t FUSE_WOA_SKU_FLAG; - uint32_t FUSE_ECO_RESERVE_1; - uint32_t FUSE_GCPLEX_CONFIG_FUSE; - uint32_t FUSE_PRODUCTION_MONTH; - uint32_t FUSE_RAM_REPAIR_INDICATOR; - uint32_t FUSE_TSENSOR9_CALIB; - uint32_t _0x1D8; - uint32_t FUSE_VMIN_CALIBRATION; - uint32_t FUSE_AGING_SENSOR_CALIBRATION; - uint32_t FUSE_DEBUG_AUTHENTICATION; - uint32_t FUSE_SECURE_PROVISION_INDEX; - uint32_t FUSE_SECURE_PROVISION_INFO; - uint32_t FUSE_OPT_GPU_DISABLE_CP1; - uint32_t FUSE_SPARE_ENDIS; - uint32_t FUSE_ECO_RESERVE_0; - uint32_t _0x1FC; - uint32_t _0x200; - uint32_t FUSE_RESERVED_CALIB0; - uint32_t FUSE_RESERVED_CALIB1; - uint32_t FUSE_OPT_GPU_TPC0_DISABLE; - uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1; - uint32_t FUSE_OPT_CPU_DISABLE; - uint32_t FUSE_OPT_CPU_DISABLE_CP1; - uint32_t FUSE_TSENSOR10_CALIB; - uint32_t FUSE_TSENSOR10_CALIB_AUX; - uint32_t FUSE_OPT_RAM_SVOP_DP; - uint32_t FUSE_OPT_RAM_SVOP_PDP; - uint32_t FUSE_OPT_RAM_SVOP_REG; - uint32_t FUSE_OPT_RAM_SVOP_SP; - uint32_t FUSE_OPT_RAM_SVOP_SMPDP; - uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2; - uint32_t FUSE_OPT_GPU_TPC1_DISABLE; - uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1; - uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2; - uint32_t FUSE_OPT_CPU_DISABLE_CP2; - uint32_t FUSE_OPT_GPU_DISABLE_CP2; - uint32_t FUSE_USB_CALIB_EXT; - uint32_t FUSE_RESERVED_FIELD; - uint32_t FUSE_OPT_ECC_EN; - uint32_t _0x25C; - uint32_t _0x260; - uint32_t _0x264; - uint32_t _0x268; - uint32_t _0x26C; - uint32_t _0x270; - uint32_t _0x274; - uint32_t _0x278; - uint32_t FUSE_SPARE_REALIGNMENT_REG; - uint32_t FUSE_SPARE_BIT[0x20]; -} tegra_fuse_chip_t; - -#define FUSE_REGS ((volatile tegra_fuse_t *)(0x7000F800)) -#define FUSE_CHIP_REGS ((volatile tegra_fuse_chip_t *)(0x7000F900)) - -#define MAKE_FUSE_REG(n) MAKE_REG32(0x7000F800 + n) - -typedef struct { - uint32_t offset; - uint32_t value; -} fuse_bypass_data_t; - -bool fuse_check_downgrade_status(void); -void fuse_configure_fuse_bypass(void); -void fuse_disable_programming(void); - -#endif diff --git a/exosphere/lp0fw/src/i2c.c b/exosphere/lp0fw/src/i2c.c deleted file mode 100644 index 75d96df3b..000000000 --- a/exosphere/lp0fw/src/i2c.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 "i2c.h" -#include "timer.h" - -/* Prototypes for internal commands. */ -void i2c_set_test_master_config_load(void); -void i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes); -void i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b); - -/* Load hardware config for I2C5. */ -void i2c_set_test_master_config_load(void) { - /* Set MSTR_CONFIG_LOAD. */ - I2C_I2C_CONFIG_LOAD_0 = 0x1; - - while (I2C_I2C_CONFIG_LOAD_0 & 1) { - /* Wait forever until it's unset. */ - } -} - -/* Writes a value to an i2c device. */ -void i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) { - if (num_bytes > 4) { - return; - } - - /* Set device for 7-bit mode. */ - I2C_I2C_CMD_ADDR0_0 = device << 1; - - /* Load in data to write. */ - I2C_I2C_CMD_DATA1_0 = val; - - /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ - I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800; - - i2c_set_test_master_config_load(); - - /* Config |= SEND; */ - I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800 | 0x200; - - - while (I2C_I2C_STATUS_0 & 0x100) { - /* Wait until not busy. */ - } - - while (I2C_I2C_STATUS_0 & 0xF) { - /* Wait until write successful. */ - } -} - -/* Writes a byte val to reg for given device. */ -void i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) { - uint32_t val = (reg) | (b << 8); - /* Write 1 byte (reg) + 1 byte (value) */ - i2c_write(device, val, 2); -} - -/* Enable the PMIC. */ -void i2c_enable_pmic(void) { - /* Write 00 to Device 27 Reg 00. */ - i2c_send_byte_command(27, 0, 0x80); -} diff --git a/exosphere/lp0fw/src/i2c.h b/exosphere/lp0fw/src/i2c.h deleted file mode 100644 index 672bb2de6..000000000 --- a/exosphere/lp0fw/src/i2c.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_I2C_H -#define EXOSPHERE_WARMBOOT_BIN_I2C_H - -#include "utils.h" - -/* I2C_BASE = I2C5. */ -#define I2C_BASE (0x7000D000) - -#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs)) - -#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000) - -#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004) - -#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C) - -#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C) - -#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068) - -#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C) - -#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084) - -#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088) - - -#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C) - -void i2c_enable_pmic(void); - -#endif diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c deleted file mode 100644 index 5bd0b8a99..000000000 --- a/exosphere/lp0fw/src/lp0.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 "utils.h" -#include "lp0.h" -#include "mc.h" -#include "pmc.h" -#include "misc.h" -#include "fuse.h" -#include "car.h" -#include "emc.h" -#include "cluster.h" -#include "flow.h" -#include "timer.h" -#include "secmon.h" - -void reboot(void) { - /* Write MAIN_RST */ - APBDEV_PMC_CNTRL_0 = 0x10; - while (true) { - /* Wait for reboot. */ - } -} - -void lp0_entry_main(warmboot_metadata_t *meta) { - const uint32_t target_firmware = meta->target_firmware; - /* Before doing anything else, ensure some sanity. */ - if (meta->magic != WARMBOOT_MAGIC || target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX) { - reboot(); - } - - /* [4.0.0+] First thing warmboot does is disable BPMP access to memory. */ - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - disable_bpmp_access_to_dram(); - } - - /* Configure debugging depending on FUSE_PRODUCTION_MODE */ - misc_configure_device_dbg_settings(); - - /* Check for downgrade. */ - /* NOTE: We implemented this as "return false" */ - if (fuse_check_downgrade_status()) { - reboot(); - } - - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { - /* Nintendo's firmware checks APBDEV_PMC_SECURE_SCRATCH32_0 against a per-warmboot binary value here. */ - /* We won't bother with that. */ - if (false /* APBDEV_PMC_SECURE_SCRATCH32_0 == WARMBOOT_MAGIC_NUMBER */) { - reboot(); - } - } - - /* TODO: Check that we're running at the correct physical address. */ - - /* Setup fuses, disable bypass. */ - fuse_configure_fuse_bypass(); - - /* Configure oscillators/timing in CAR. */ - car_configure_oscillators(); - - /* Restore RAM configuration. */ - misc_restore_ram_svop(); - emc_configure_pmacro_training(); - - /* Setup clock output for all devices, working around mbist bug. */ - car_mbist_workaround(); - - /* Initialize the CPU cluster. */ - cluster_initialize_cpu(); - - secmon_restore_to_tzram(target_firmware); - - /* Power on the CPU cluster. */ - cluster_power_on_cpu(); - - /* Nintendo clears most of warmboot.bin out of IRAM here. We're not gonna bother. */ - /* memset( ... ); */ - - const uint32_t halt_val = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) ? 0x40000000 : 0x50000000; - while (true) { - /* Halt the BPMP. */ - FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val; - } -} diff --git a/exosphere/lp0fw/src/lp0.h b/exosphere/lp0fw/src/lp0.h deleted file mode 100644 index ca5679649..000000000 --- a/exosphere/lp0fw/src/lp0.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_LP0_H -#define EXOSPHERE_WARMBOOT_BIN_LP0_H - -#include "utils.h" - -/* WBT0 */ -#define WARMBOOT_MAGIC 0x30544257 - -typedef struct { - uint32_t magic; - uint32_t target_firmware; - uint32_t padding[2]; -} warmboot_metadata_t; - -void lp0_entry_main(warmboot_metadata_t *meta); - -void __attribute__((noreturn)) reboot(void); - -#endif diff --git a/exosphere/lp0fw/src/mc.c b/exosphere/lp0fw/src/mc.c deleted file mode 100644 index 522b1f475..000000000 --- a/exosphere/lp0fw/src/mc.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 "mc.h" -#include "utils.h" - -void disable_bpmp_access_to_dram(void) { - /* Modify carveout 4 to prevent BPMP access to dram (TZ will fix it). */ - volatile security_carveout_t *carveout = (volatile security_carveout_t *)(MC_BASE + 0xC08 + 0x50 * (4 - CARVEOUT_ID_MIN)); - carveout->paddr_low = 0; - carveout->paddr_high = 0; - carveout->size_big_pages = 1; /* 128 KiB */ - carveout->client_access_0 = 0; - carveout->client_access_1 = 0; - carveout->client_access_2 = 0; - carveout->client_access_3 = 0; - carveout->client_access_4 = 0; - carveout->client_force_internal_access_0 = BIT(CSR_AVPCARM7R); - carveout->client_force_internal_access_1 = BIT(CSW_AVPCARM7W); - carveout->client_force_internal_access_2 = 0; - carveout->client_force_internal_access_3 = 0; - carveout->client_force_internal_access_4 = 0; - /* Set config to LOCKED, TZ-SECURE, untranslated addresses only. */ - carveout->config = 0x8F; -} diff --git a/exosphere/lp0fw/src/mc.h b/exosphere/lp0fw/src/mc.h deleted file mode 100644 index 5e73730ce..000000000 --- a/exosphere/lp0fw/src/mc.h +++ /dev/null @@ -1,622 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_MC_H -#define EXOSPHERE_WARMBOOT_BIN_MC_H - -#include - -#define MC_BASE_PHYS 0x70019000 - -#define MC_BASE (MC_BASE_PHYS) -#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) - -#define MC_INTSTATUS 0x0 -#define MC_INTMASK 0x4 -#define MC_ERR_STATUS 0x8 -#define MC_ERR_ADR 0xc -#define MC_SMMU_CONFIG 0x10 -#define MC_SMMU_TLB_CONFIG 0x14 -#define MC_SMMU_PTC_CONFIG 0x18 -#define MC_SMMU_PTB_ASID 0x1c -#define MC_SMMU_PTB_DATA 0x20 -#define MC_SMMU_TLB_FLUSH 0x30 -#define MC_SMMU_PTC_FLUSH 0x34 -#define MC_SMMU_ASID_SECURITY 0x38 -#define MC_SMMU_ASID_SECURITY_1 0x3c -#define MC_SMMU_ASID_SECURITY_2 0x9e0 -#define MC_SMMU_ASID_SECURITY_3 0x9e4 -#define MC_SMMU_ASID_SECURITY_4 0x9e8 -#define MC_SMMU_ASID_SECURITY_5 0x9ec -#define MC_SMMU_ASID_SECURITY_6 0x9f0 -#define MC_SMMU_ASID_SECURITY_7 0x9f4 -#define MC_SMMU_AFI_ASID 0x238 -#define MC_SMMU_AVPC_ASID 0x23c -#define MC_SMMU_PPCS1_ASID 0x298 -#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 -#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c -#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 -#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 -#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 -#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 -#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 -#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 -#define MC_PCFIFO_CLIENT_CONFIG3 0xddc -#define MC_PCFIFO_CLIENT_CONFIG4 0xde0 -#define MC_EMEM_CFG 0x50 -#define MC_EMEM_ADR_CFG 0x54 -#define MC_EMEM_ADR_CFG_DEV0 0x58 -#define MC_EMEM_ADR_CFG_DEV1 0x5c -#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60 -#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64 -#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68 -#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c -#define MC_SECURITY_CFG0 0x70 -#define MC_SECURITY_CFG1 0x74 -#define MC_SECURITY_CFG3 0x9bc -#define MC_SECURITY_RSV 0x7c -#define MC_EMEM_ARB_CFG 0x90 -#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 -#define MC_EMEM_ARB_TIMING_RCD 0x98 -#define MC_EMEM_ARB_TIMING_RP 0x9c -#define MC_EMEM_ARB_TIMING_RC 0xa0 -#define MC_EMEM_ARB_TIMING_RAS 0xa4 -#define MC_EMEM_ARB_TIMING_FAW 0xa8 -#define MC_EMEM_ARB_TIMING_RRD 0xac -#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 -#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 -#define MC_EMEM_ARB_TIMING_R2R 0xb8 -#define MC_EMEM_ARB_TIMING_W2W 0xbc -#define MC_EMEM_ARB_TIMING_R2W 0xc0 -#define MC_EMEM_ARB_TIMING_W2R 0xc4 -#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0 -#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4 -#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0 -#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4 -#define MC_EMEM_ARB_DA_TURNS 0xd0 -#define MC_EMEM_ARB_DA_COVERS 0xd4 -#define MC_EMEM_ARB_MISC0 0xd8 -#define MC_EMEM_ARB_MISC1 0xdc -#define MC_EMEM_ARB_MISC2 0xc8 -#define MC_EMEM_ARB_RING1_THROTTLE 0xe0 -#define MC_EMEM_ARB_RING3_THROTTLE 0xe4 -#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0 -#define MC_EMEM_ARB_OVERRIDE 0xe8 -#define MC_EMEM_ARB_RSV 0xec -#define MC_CLKEN_OVERRIDE 0xf4 -#define MC_TIMING_CONTROL_DBG 0xf8 -#define MC_TIMING_CONTROL 0xfc -#define MC_STAT_CONTROL 0x100 -#define MC_STAT_STATUS 0x104 -#define MC_STAT_EMC_CLOCK_LIMIT 0x108 -#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c -#define MC_STAT_EMC_CLOCKS 0x110 -#define MC_STAT_EMC_CLOCKS_MSBS 0x114 -#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118 -#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158 -#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c -#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c -#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20 -#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24 -#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198 -#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8 -#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c -#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac -#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28 -#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c -#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0 -#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0 -#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120 -#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c -#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c -#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c -#define MC_STAT_EMC_SET0_COUNT 0x138 -#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c -#define MC_STAT_EMC_SET1_COUNT 0x178 -#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c -#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140 -#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144 -#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180 -#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184 -#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148 -#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c -#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188 -#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c -#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150 -#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190 -#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8 -#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc -#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8 -#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc -#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0 -#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0 -#define MC_CLIENT_HOTRESET_CTRL 0x200 -#define MC_CLIENT_HOTRESET_CTRL_1 0x970 -#define MC_CLIENT_HOTRESET_STATUS 0x204 -#define MC_CLIENT_HOTRESET_STATUS_1 0x974 -#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208 -#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c -#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210 -#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214 -#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94 -#define MC_EMEM_ARB_HYSTERESIS_0 0x218 -#define MC_EMEM_ARB_HYSTERESIS_1 0x21c -#define MC_EMEM_ARB_HYSTERESIS_2 0x220 -#define MC_EMEM_ARB_HYSTERESIS_3 0x224 -#define MC_EMEM_ARB_HYSTERESIS_4 0xb84 -#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0 -#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4 -#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8 -#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc -#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0 -#define MC_EMEM_ARB_DHYST_CTRL 0xbcc -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec -#define MC_RESERVED_RSV 0x3fc -#define MC_DISB_EXTRA_SNAP_LEVELS 0x408 -#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4 -#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0 -#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18 -#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08 -#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10 -#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c -#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40 -#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414 -#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc -#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c -#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14 -#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0 -#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac -#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c -#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48 -#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8 -#define MC_USBX_EXTRA_SNAP_LEVELS 0x404 -#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8 -#define MC_SD_EXTRA_SNAP_LEVELS 0xa04 -#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c -#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8 -#define MC_GK_EXTRA_SNAP_LEVELS 0xa00 -#define MC_VE2_EXTRA_SNAP_LEVELS 0x410 -#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44 -#define MC_VIDEO_PROTECT_BOM 0x648 -#define MC_VIDEO_PROTECT_SIZE_MB 0x64c -#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978 -#define MC_VIDEO_PROTECT_REG_CTRL 0x650 -#define MC_ERR_VPR_STATUS 0x654 -#define MC_ERR_VPR_ADR 0x658 -#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418 -#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590 -#define MC_IRAM_BOM 0x65c -#define MC_IRAM_TOM 0x660 -#define MC_IRAM_ADR_HI 0x980 -#define MC_IRAM_REG_CTRL 0x964 -#define MC_EMEM_CFG_ACCESS_CTRL 0x664 -#define MC_TZ_SECURITY_CTRL 0x668 -#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c -#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4 -#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc -#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8 -#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80 -#define MC_SEC_CARVEOUT_BOM 0x670 -#define MC_SEC_CARVEOUT_SIZE_MB 0x674 -#define MC_SEC_CARVEOUT_ADR_HI 0x9d4 -#define MC_SEC_CARVEOUT_REG_CTRL 0x678 -#define MC_ERR_SEC_STATUS 0x67c -#define MC_ERR_SEC_ADR 0x680 -#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684 -#define MC_STUTTER_CONTROL 0x688 -#define MC_RESERVED_RSV_1 0x958 -#define MC_DVFS_PIPE_SELECT 0x95c -#define MC_AHB_PTSA_MIN 0x4e0 -#define MC_AUD_PTSA_MIN 0x54c -#define MC_MLL_MPCORER_PTSA_RATE 0x44c -#define MC_RING2_PTSA_RATE 0x440 -#define MC_USBD_PTSA_RATE 0x530 -#define MC_USBX_PTSA_MIN 0x528 -#define MC_USBD_PTSA_MIN 0x534 -#define MC_APB_PTSA_MAX 0x4f0 -#define MC_JPG_PTSA_RATE 0x584 -#define MC_DIS_PTSA_MIN 0x420 -#define MC_AVP_PTSA_MAX 0x4fc -#define MC_AVP_PTSA_RATE 0x4f4 -#define MC_RING1_PTSA_MIN 0x480 -#define MC_DIS_PTSA_MAX 0x424 -#define MC_SD_PTSA_MAX 0x4d8 -#define MC_MSE_PTSA_RATE 0x4c4 -#define MC_VICPC_PTSA_MIN 0x558 -#define MC_PCX_PTSA_MAX 0x4b4 -#define MC_ISP_PTSA_RATE 0x4a0 -#define MC_A9AVPPC_PTSA_MIN 0x48c -#define MC_RING2_PTSA_MAX 0x448 -#define MC_AUD_PTSA_RATE 0x548 -#define MC_HOST_PTSA_MIN 0x51c -#define MC_MLL_MPCORER_PTSA_MAX 0x454 -#define MC_SD_PTSA_MIN 0x4d4 -#define MC_RING1_PTSA_RATE 0x47c -#define MC_JPG_PTSA_MIN 0x588 -#define MC_HDAPC_PTSA_MIN 0x62c -#define MC_AVP_PTSA_MIN 0x4f8 -#define MC_JPG_PTSA_MAX 0x58c -#define MC_VE_PTSA_MAX 0x43c -#define MC_DFD_PTSA_MAX 0x63c -#define MC_VICPC_PTSA_RATE 0x554 -#define MC_GK_PTSA_MAX 0x544 -#define MC_VICPC_PTSA_MAX 0x55c -#define MC_SDM_PTSA_MAX 0x624 -#define MC_SAX_PTSA_RATE 0x4b8 -#define MC_PCX_PTSA_MIN 0x4b0 -#define MC_APB_PTSA_MIN 0x4ec -#define MC_GK2_PTSA_MIN 0x614 -#define MC_PCX_PTSA_RATE 0x4ac -#define MC_RING1_PTSA_MAX 0x484 -#define MC_HDAPC_PTSA_RATE 0x628 -#define MC_MLL_MPCORER_PTSA_MIN 0x450 -#define MC_GK2_PTSA_MAX 0x618 -#define MC_AUD_PTSA_MAX 0x550 -#define MC_GK2_PTSA_RATE 0x610 -#define MC_ISP_PTSA_MAX 0x4a8 -#define MC_DISB_PTSA_RATE 0x428 -#define MC_VE2_PTSA_MAX 0x49c -#define MC_DFD_PTSA_MIN 0x638 -#define MC_FTOP_PTSA_RATE 0x50c -#define MC_A9AVPPC_PTSA_RATE 0x488 -#define MC_VE2_PTSA_MIN 0x498 -#define MC_USBX_PTSA_MAX 0x52c -#define MC_DIS_PTSA_RATE 0x41c -#define MC_USBD_PTSA_MAX 0x538 -#define MC_A9AVPPC_PTSA_MAX 0x490 -#define MC_USBX_PTSA_RATE 0x524 -#define MC_FTOP_PTSA_MAX 0x514 -#define MC_HDAPC_PTSA_MAX 0x630 -#define MC_SD_PTSA_RATE 0x4d0 -#define MC_DFD_PTSA_RATE 0x634 -#define MC_FTOP_PTSA_MIN 0x510 -#define MC_SDM_PTSA_RATE 0x61c -#define MC_AHB_PTSA_RATE 0x4dc -#define MC_SMMU_SMMU_PTSA_MAX 0x460 -#define MC_RING2_PTSA_MIN 0x444 -#define MC_SDM_PTSA_MIN 0x620 -#define MC_APB_PTSA_RATE 0x4e8 -#define MC_MSE_PTSA_MIN 0x4c8 -#define MC_HOST_PTSA_RATE 0x518 -#define MC_VE_PTSA_RATE 0x434 -#define MC_AHB_PTSA_MAX 0x4e4 -#define MC_SAX_PTSA_MIN 0x4bc -#define MC_SMMU_SMMU_PTSA_MIN 0x45c -#define MC_ISP_PTSA_MIN 0x4a4 -#define MC_HOST_PTSA_MAX 0x520 -#define MC_SAX_PTSA_MAX 0x4c0 -#define MC_VE_PTSA_MIN 0x438 -#define MC_GK_PTSA_MIN 0x540 -#define MC_MSE_PTSA_MAX 0x4cc -#define MC_DISB_PTSA_MAX 0x430 -#define MC_DISB_PTSA_MIN 0x42c -#define MC_SMMU_SMMU_PTSA_RATE 0x458 -#define MC_VE2_PTSA_RATE 0x494 -#define MC_GK_PTSA_RATE 0x53c -#define MC_PTSA_GRANT_DECREMENT 0x960 -#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4 -#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0 -#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380 -#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384 -#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc -#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8 -#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370 -#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0 -#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374 -#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 -#define MC_LATENCY_ALLOWANCE_VIC_0 0x394 -#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 -#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8 -#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc -#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390 -#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694 -#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 -#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c -#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 -#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0 -#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698 -#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec -#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0 -#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4 -#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8 -#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 -#define MC_LATENCY_ALLOWANCE_HC_1 0x314 -#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0 -#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4 -#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c -#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec -#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320 -#define MC_LATENCY_ALLOWANCE_VI2_0 0x398 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4 -#define MC_LATENCY_ALLOWANCE_SATA_0 0x350 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690 -#define MC_LATENCY_ALLOWANCE_HC_0 0x310 -#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8 -#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac -#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4 -#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388 -#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328 -#define MC_LATENCY_ALLOWANCE_HDA_0 0x318 -#define MC_MIN_LENGTH_APE_0 0xb34 -#define MC_MIN_LENGTH_DCB_2 0x8a8 -#define MC_MIN_LENGTH_A9AVP_0 0x950 -#define MC_MIN_LENGTH_TSEC_0 0x93c -#define MC_MIN_LENGTH_DC_1 0x898 -#define MC_MIN_LENGTH_AXIAP_0 0x94c -#define MC_MIN_LENGTH_ISP2B_0 0x930 -#define MC_MIN_LENGTH_VI2_0 0x944 -#define MC_MIN_LENGTH_DCB_0 0x8a0 -#define MC_MIN_LENGTH_DCB_1 0x8a4 -#define MC_MIN_LENGTH_PPCS_1 0x8f4 -#define MC_MIN_LENGTH_NVJPG_0 0xb3c -#define MC_MIN_LENGTH_HDA_0 0x8c4 -#define MC_MIN_LENGTH_NVENC_0 0x8d4 -#define MC_MIN_LENGTH_SDMMC_0 0xb18 -#define MC_MIN_LENGTH_ISP2B_1 0x934 -#define MC_MIN_LENGTH_HC_1 0x8c0 -#define MC_MIN_LENGTH_DC_3 0xb20 -#define MC_MIN_LENGTH_AVPC_0 0x890 -#define MC_MIN_LENGTH_VIC_0 0x940 -#define MC_MIN_LENGTH_ISP2_0 0x91c -#define MC_MIN_LENGTH_HC_0 0x8bc -#define MC_MIN_LENGTH_SE_0 0xb38 -#define MC_MIN_LENGTH_NVDEC_0 0xb30 -#define MC_MIN_LENGTH_SATA_0 0x8fc -#define MC_MIN_LENGTH_DC_0 0x894 -#define MC_MIN_LENGTH_XUSB_1 0x92c -#define MC_MIN_LENGTH_DC_2 0x89c -#define MC_MIN_LENGTH_SDMMCAA_0 0xb14 -#define MC_MIN_LENGTH_GPU_0 0xb04 -#define MC_MIN_LENGTH_ETR_0 0xb44 -#define MC_MIN_LENGTH_AFI_0 0x88c -#define MC_MIN_LENGTH_PPCS_0 0x8f0 -#define MC_MIN_LENGTH_ISP2_1 0x920 -#define MC_MIN_LENGTH_XUSB_0 0x928 -#define MC_MIN_LENGTH_MPCORE_0 0x8cc -#define MC_MIN_LENGTH_TSECB_0 0xb48 -#define MC_MIN_LENGTH_SDMMCA_0 0xb10 -#define MC_MIN_LENGTH_GPU2_0 0xb40 -#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c -#define MC_MIN_LENGTH_PTC_0 0x8f8 -#define MC_EMEM_ARB_OVERRIDE_1 0x968 -#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984 -#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988 -#define MC_EMEM_ARB_STATS_0 0x990 -#define MC_EMEM_ARB_STATS_1 0x994 -#define MC_MTS_CARVEOUT_BOM 0x9a0 -#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4 -#define MC_MTS_CARVEOUT_ADR_HI 0x9a8 -#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac -#define MC_ERR_MTS_STATUS 0x9b0 -#define MC_ERR_MTS_ADR 0x9b4 -#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 -#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74 -#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8 -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10 -#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04 -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c -#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4 -#define MC_SECURITY_CARVEOUT2_CFG0 0xc58 -#define MC_SECURITY_CARVEOUT1_CFG0 0xc08 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84 -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68 -#define MC_SECURITY_CARVEOUT3_BOM 0xcac -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70 -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60 -#define MC_SECURITY_CARVEOUT3_CFG0 0xca8 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88 -#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64 -#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50 -#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14 -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14 -#define MC_SECURITY_CARVEOUT1_BOM 0xc0c -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58 -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4 -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78 -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18 -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c -#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8 -#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60 -#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80 -#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54 -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4 -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc -#define MC_SECURITY_CARVEOUT4_BOM 0xcfc -#define MC_SECURITY_CARVEOUT5_CFG0 0xd48 -#define MC_SECURITY_CARVEOUT2_BOM 0xc5c -#define MC_SECURITY_CARVEOUT5_BOM 0xd4c -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24 -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0 -#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10 -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08 -#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 -#define MC_DA_CONFIG0 0x9dc - -/* Virtual aliases */ -#define VIRT_MC_SECURITY_CFG3 MAKE_MC_REG(MC_SECURITY_CFG3) - -/* Memory Controller clients */ -#define CLIENT_ACCESS_NUM_CLIENTS 32 -typedef enum { - /* _ACCESS0 */ - CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - - /* _ACCESS1 */ - CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - - /* _ACCESS2 */ - CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - - /* _ACCESS3 */ - CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - - /* _ACCESS4 */ - CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) -} McClient; - -/* Memory Controller carveouts */ -#define CARVEOUT_ID_MIN 1 -#define CARVEOUT_ID_MAX 5 -typedef struct { - uint32_t config; - uint32_t paddr_low; - uint32_t paddr_high; - uint32_t size_big_pages; - uint32_t client_access_0; - uint32_t client_access_1; - uint32_t client_access_2; - uint32_t client_access_3; - uint32_t client_access_4; - uint32_t client_force_internal_access_0; - uint32_t client_force_internal_access_1; - uint32_t client_force_internal_access_2; - uint32_t client_force_internal_access_3; - uint32_t client_force_internal_access_4; - uint8_t padding[0x18]; -} security_carveout_t; - -void disable_bpmp_access_to_dram(void); - -#endif \ No newline at end of file diff --git a/exosphere/lp0fw/src/misc.c b/exosphere/lp0fw/src/misc.c deleted file mode 100644 index bab594d48..000000000 --- a/exosphere/lp0fw/src/misc.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 "utils.h" -#include "misc.h" -#include "fuse.h" -#include "sysreg.h" -#include "pmc.h" - -void misc_configure_device_dbg_settings(void) { - /* Set APB_MISC_PP_CONFIG_CTL_TBE (enables RTCK daisy-chaining). */ - APB_MISC_PP_CONFIG_CTL_0 = 0x80; - - /* Configure JTAG and debug bits. */ - if (FUSE_CHIP_REGS->FUSE_SECURITY_MODE == 1) { - uint32_t secure_boot_val = 0b0100; /* Set NIDEN for aarch64. */ - uint32_t pp_config_ctl_val = 0x40; /* Set APB_MISC_PP_CONFIG_CTL_JTAG. */ - if (APBDEV_PMC_STICKY_BITS_0 & 0x40) { - pp_config_ctl_val = 0x0; - } else { - secure_boot_val = 0b1101; /* Set SPNIDEN, NIDEN, DBGEN for aarch64. */ - } - SB_PFCFG_0 = (SB_PFCFG_0 & ~0b1111) | secure_boot_val; /* Configure debug bits. */ - APB_MISC_PP_CONFIG_CTL_0 |= pp_config_ctl_val; /* Configure JTAG. */ - } - - /* Set HDA_LPBK_DIS if FUSE_SECURITY_MODE is set (disables HDA codec loopback). */ - APBDEV_PMC_STICKY_BITS_0 |= FUSE_CHIP_REGS->FUSE_SECURITY_MODE; - - /* Set E_INPUT in PINMUX_AUX_GPIO_PA6_0 (needed by the XUSB and SATA controllers). */ - PINMUX_AUX_GPIO_PA6_0 |= 0x40; -} - -void misc_restore_ram_svop(void) { - /* This sets CFG2TMC_RAM_SVOP_PDP to 0x2. */ - APB_MISC_GP_ASDBGREG_0 = (APB_MISC_GP_ASDBGREG_0 & 0xFCFFFFFF) | 0x02000000; -} \ No newline at end of file diff --git a/exosphere/lp0fw/src/misc.h b/exosphere/lp0fw/src/misc.h deleted file mode 100644 index ccb17a773..000000000 --- a/exosphere/lp0fw/src/misc.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_MISC_H -#define EXOSPHERE_WARMBOOT_BIN_MISC_H - -#include - -#include "utils.h" - -#define MISC_BASE (0x70000000) - -#define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n) - -#define APB_MISC_PP_CONFIG_CTL_0 MAKE_MISC_REG(0x024) -#define APB_MISC_GP_ASDBGREG_0 MAKE_MISC_REG(0x810) - -#define PINMUX_AUX_PWR_I2C_SCL_0 MAKE_MISC_REG(0x30DC) -#define PINMUX_AUX_PWR_I2C_SDA_0 MAKE_MISC_REG(0x30E0) -#define PINMUX_AUX_DVFS_PWM_0 MAKE_MISC_REG(0x3184) -#define PINMUX_AUX_GPIO_PA6_0 MAKE_MISC_REG(0x3244) - -void misc_configure_device_dbg_settings(void); -void misc_restore_ram_svop(void); - -#endif diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h deleted file mode 100644 index a872c6073..000000000 --- a/exosphere/lp0fw/src/pmc.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_PMC_H -#define EXOSPHERE_WARMBOOT_BIN_PMC_H - -#include "utils.h" - -#define PMC_BASE (0x7000E400) - -#define MAKE_PMC_REG(ofs) (MAKE_REG32(PMC_BASE + ofs)) - -#define APBDEV_PMC_CNTRL_0 MAKE_PMC_REG(0x000) -#define APBDEV_PMC_DPD_SAMPLE_0 MAKE_PMC_REG(0x020) -#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x024) -#define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C) -#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x030) -#define APBDEV_PMC_REMOVE_CLAMPING_CMD_0 MAKE_PMC_REG(0x034) -#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038) -#define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080) -#define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084) -#define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) -#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) -#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) -#define APBDEV_PMC_STICKY_BITS_0 MAKE_PMC_REG(0x2C0) -#define APBDEV_PMC_SEC_DISABLE2_0 MAKE_PMC_REG(0x2C4) -#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) -#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334) -#define APBDEV_PMC_SECURE_SCRATCH24_0 MAKE_PMC_REG(0x340) -#define APBDEV_PMC_SECURE_SCRATCH25_0 MAKE_PMC_REG(0x344) -#define APBDEV_PMC_SECURE_SCRATCH26_0 MAKE_PMC_REG(0x348) -#define APBDEV_PMC_SECURE_SCRATCH27_0 MAKE_PMC_REG(0x34C) -#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360) -#define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_PMC_REG(0x368) -#define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_PMC_REG(0x36C) -#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_PMC_REG(0xB18) -#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_PMC_REG(0xB1C) -#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_PMC_REG(0xB20) -#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_PMC_REG(0xB24) -#define APBDEV_PMC_FUSE_CTRL MAKE_PMC_REG(0x450) -#define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) -#define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460) -#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464) -#define APBDEV_PMC_IO_DPD4_STATUS_0 MAKE_PMC_REG(0x468) -#define APBDEV_PMC_SET_SW_CLAMP_0 MAKE_PMC_REG(0x47C) -#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4) - -#endif diff --git a/exosphere/lp0fw/src/se.c b/exosphere/lp0fw/src/se.c deleted file mode 100644 index 2deccbdbc..000000000 --- a/exosphere/lp0fw/src/se.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * 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 "utils.h" -#include "lp0.h" -#include "se.h" - -static void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size); - -/* Initialize a SE linked list. */ -static void __attribute__((__noinline__)) ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { - ll->num_entries = 0; /* 1 Entry. */ - - if (buffer != NULL) { - ll->addr_info.address = (uint32_t) buffer; - ll->addr_info.size = (uint32_t) size; - } else { - ll->addr_info.address = 0; - ll->addr_info.size = 0; - } -} - -void se_check_error_status_reg(void) { - if (se_get_regs()->SE_ERR_STATUS) { - reboot(); - } -} - -void se_check_for_error(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) { - reboot(); - } -} - -void se_verify_flags_cleared(void) { - if (se_get_regs()->SE_STATUS & 3) { - reboot(); - } -} - -void clear_aes_keyslot(unsigned int keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - reboot(); - } - - /* Zero out the whole keyslot and IV. */ - for (unsigned int i = 0; i < 0x10; i++) { - se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i; - se->SE_CRYPTO_KEYTABLE_DATA = 0; - } -} - -void clear_rsa_keyslot(unsigned int keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_RSA_MAX) { - reboot(); - } - - /* Zero out the whole keyslot. */ - for (unsigned int i = 0; i < 0x40; i++) { - /* Select Keyslot Modulus[i] */ - se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; - se->SE_RSA_KEYTABLE_DATA = 0; - } - for (unsigned int i = 0; i < 0x40; i++) { - /* Select Keyslot Expontent[i] */ - se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - se->SE_RSA_KEYTABLE_DATA = 0; - } -} - -void clear_aes_keyslot_iv(unsigned int keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - reboot(); - } - - for (size_t i = 0; i < (0x10 >> 2); i++) { - se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - se->SE_CRYPTO_KEYTABLE_DATA = 0; - } -} - -void decrypt_data_into_keyslot_256(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { - reboot(); - } - - se->SE_CONFIG = (0x202 << 16) | (ALG_AES_DEC | DST_KEYTAB); - se->SE_CRYPTO_CONFIG = keyslot_src << 24; - se->SE_CRYPTO_LAST_BLOCK = 0; - se->SE_CRYPTO_KEYTABLE_DST = keyslot_dst << 8; - - trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); -} - -void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); - se_ll_t in_ll; - se_ll_t out_ll; - - ll_init(&in_ll, (void *)src, src_size); - ll_init(&out_ll, dst, dst_size); - - /* Set the LLs. */ - se->SE_IN_LL_ADDR = (uint32_t)(&in_ll); - se->SE_OUT_LL_ADDR = (uint32_t) (&out_ll); - - /* Set registers for operation. */ - se->SE_ERR_STATUS = se->SE_ERR_STATUS; - se->SE_INT_STATUS = se->SE_INT_STATUS; - se->SE_OPERATION = op; - - while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ } - se_check_for_error(); -} - -/* Secure AES Functionality. */ -void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { - uint8_t block[0x10] = {0}; - - if (src_size > sizeof(block) || dst_size > sizeof(block)) { - reboot(); - } - - /* Load src data into block. */ - if (src_size != 0) { - memcpy(block, src, src_size); - } - - /* Trigger AES operation. */ - se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0; - trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); - - /* Copy output data into dst. */ - if (dst_size != 0) { - memcpy(dst, block, dst_size); - } -} - -void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { - reboot(); - } - - /* Set configuration high (256-bit vs 128-bit) based on parameter. */ - se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); - se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100; - se_perform_aes_block_operation(dst, 0x10, src, 0x10); -} - -void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { - reboot(); - } - - se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY); - se->SE_CRYPTO_CONFIG = keyslot << 24; - se_perform_aes_block_operation(dst, 0x10, src, 0x10); -} - -void shift_left_xor_rb(uint8_t *key) { - uint8_t prev_high_bit = 0; - for (unsigned int i = 0; i < 0x10; i++) { - uint8_t cur_byte = key[0xF - i]; - key[0xF - i] = (cur_byte << 1) | (prev_high_bit); - prev_high_bit = cur_byte >> 7; - } - if (prev_high_bit) { - key[0xF] ^= 0x87; - } -} - -void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - reboot(); - } - - /* Generate the derived key, to be XOR'd with final output block. */ - uint8_t ALIGN(16) derived_key[0x10] = {0}; - se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high); - shift_left_xor_rb(derived_key); - if (data_size & 0xF) { - shift_left_xor_rb(derived_key); - } - - se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); - se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145); - clear_aes_keyslot_iv(keyslot); - - unsigned int num_blocks = (data_size + 0xF) >> 4; - /* Handle aligned blocks. */ - if (num_blocks > 1) { - se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2; - trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); - se->SE_CRYPTO_CONFIG |= 0x80; - } - - /* Create final block. */ - uint8_t ALIGN(16) last_block[0x10] = {0}; - if (data_size & 0xF) { - memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF); - last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */ - } else if (data_size >= 0x10) { - memcpy(last_block, data + data_size - 0x10, 0x10); - } - - for (unsigned int i = 0; i < 0x10; i++) { - last_block[i] ^= derived_key[i]; - } - - /* Perform last operation. */ - se->SE_CRYPTO_LAST_BLOCK = 0; - trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); - - /* Copy output CMAC. */ - for (unsigned int i = 0; i < (cmac_size >> 2); i++) { - ((uint32_t *)cmac)[i] = ((volatile uint32_t *)se->SE_HASH_RESULT)[i]; - } -} - -void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { - se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202); -} - -void se_aes_256_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { - reboot(); - } - - se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY) | (0x202 << 16); - se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x66; - clear_aes_keyslot_iv(keyslot); - se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1; - trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); -} \ No newline at end of file diff --git a/exosphere/lp0fw/src/se.h b/exosphere/lp0fw/src/se.h deleted file mode 100644 index 5e0083e36..000000000 --- a/exosphere/lp0fw/src/se.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_SE_H -#define EXOSPHERE_WARMBOOT_BIN_SE_H - -#define SE_BASE 0x70012000 -#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n) - -#define KEYSLOT_SWITCH_LP0TZRAMKEK 0x2 -#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x3 -#define KEYSLOT_SWITCH_SRKGENKEY 0x8 -#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8 -#define KEYSLOT_SWITCH_TEMPKEY 0x9 -#define KEYSLOT_SWITCH_SESSIONKEY 0xA -#define KEYSLOT_SWITCH_RNGKEY 0xB -#define KEYSLOT_SWITCH_MASTERKEY 0xC -#define KEYSLOT_SWITCH_DEVICEKEY 0xD - -/* This keyslot was added in 4.0.0. */ -#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD -#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE -#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF - -/* This keyslot was added in 5.0.0. */ -#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA - -#define KEYSLOT_AES_MAX 0x10 -#define KEYSLOT_RSA_MAX 0x2 - -#define KEYSIZE_AES_MAX 0x20 -#define KEYSIZE_RSA_MAX 0x100 - -#define ALG_SHIFT (12) -#define ALG_DEC_SHIFT (8) -#define ALG_NOP (0 << ALG_SHIFT) -#define ALG_AES_ENC (1 << ALG_SHIFT) -#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP) -#define ALG_RNG (2 << ALG_SHIFT) -#define ALG_SHA (3 << ALG_SHIFT) -#define ALG_RSA (4 << ALG_SHIFT) - -#define DST_SHIFT (2) -#define DST_MEMORY (0 << DST_SHIFT) -#define DST_HASHREG (1 << DST_SHIFT) -#define DST_KEYTAB (2 << DST_SHIFT) -#define DST_SRK (3 << DST_SHIFT) -#define DST_RSAREG (4 << DST_SHIFT) - -#define ENCMODE_SHIFT (24) -#define DECMODE_SHIFT (16) -#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT) - -#define HASH_DISABLE (0x0) -#define HASH_ENABLE (0x1) - -#define OP_ABORT 0 -#define OP_START 1 -#define OP_RESTART 2 -#define OP_CTX_SAVE 3 -#define OP_RESTART_IN 4 - -#define CTX_SAVE_SRC_SHIFT 29 -#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT) - -#define CTX_SAVE_KEY_LOW_BITS 0 -#define CTX_SAVE_KEY_HIGH_BITS 1 -#define CTX_SAVE_KEY_ORIGINAL_IV 2 -#define CTX_SAVE_KEY_UPDATED_IV 3 - -#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24 -#define CTX_SAVE_KEY_INDEX_SHIFT 8 -#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16 -#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12 - -#define RSA_2048_BYTES 0x100 - -typedef struct { - uint32_t SE_SE_SECURITY; - uint32_t SE_TZRAM_SECURITY; - uint32_t SE_OPERATION; - uint32_t SE_INT_ENABLE; - uint32_t SE_INT_STATUS; - uint32_t SE_CONFIG; - uint32_t SE_IN_LL_ADDR; - uint32_t SE_IN_CUR_BYTE_ADDR; - uint32_t SE_IN_CUR_LL_ID; - uint32_t SE_OUT_LL_ADDR; - uint32_t SE_OUT_CUR_BYTE_ADDR; - uint32_t SE_OUT_CUR_LL_ID; - uint32_t SE_HASH_RESULT[0x10]; - uint32_t SE_CTX_SAVE_CONFIG; - uint32_t _0x74[0x63]; - uint32_t SE_SHA_CONFIG; - uint32_t SE_SHA_MSG_LENGTH[0x4]; - uint32_t SE_SHA_MSG_LEFT[0x4]; - uint32_t _0x224[0x17]; - uint32_t SE_CRYPTO_SECURITY_PERKEY; - uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10]; - uint32_t _0x2C4[0x10]; - uint32_t SE_CRYPTO_CONFIG; - uint32_t SE_CRYPTO_LINEAR_CTR[0x4]; - uint32_t SE_CRYPTO_LAST_BLOCK; - uint32_t SE_CRYPTO_KEYTABLE_ADDR; - uint32_t SE_CRYPTO_KEYTABLE_DATA; - uint32_t _0x324[0x3]; - uint32_t SE_CRYPTO_KEYTABLE_DST; - uint32_t _0x334[0x3]; - uint32_t SE_RNG_CONFIG; - uint32_t SE_RNG_SRC_CONFIG; - uint32_t SE_RNG_RESEED_INTERVAL; - uint32_t _0x34C[0x2D]; - uint32_t SE_RSA_CONFIG; - uint32_t SE_RSA_KEY_SIZE; - uint32_t SE_RSA_EXP_SIZE; - uint32_t SE_RSA_SECURITY_PERKEY; - uint32_t SE_RSA_KEYTABLE_ACCESS[0x2]; - uint32_t _0x418[0x2]; - uint32_t SE_RSA_KEYTABLE_ADDR; - uint32_t SE_RSA_KEYTABLE_DATA; - uint32_t SE_RSA_OUTPUT[0x40]; - uint32_t _0x528[0xB6]; - uint32_t SE_STATUS; - uint32_t SE_ERR_STATUS; - uint32_t SE_MISC; - uint32_t SE_SPARE; - uint32_t SE_ENTROPY_DEBUG_COUNTER; - uint32_t _0x814; - uint32_t _0x818; - uint32_t _0x81C; - uint32_t _0x820[0x5F8]; -} tegra_se_t; - -typedef struct { - uint32_t address; - uint32_t size; -} se_addr_info_t; - -typedef struct { - uint32_t num_entries; /* Set to total entries - 1 */ - se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ -} se_ll_t; - -static inline volatile tegra_se_t *se_get_regs(void) { - return (volatile tegra_se_t *)SE_BASE; -} - -void se_check_error_status_reg(void); -void se_check_for_error(void); - -void se_verify_flags_cleared(void); - -void clear_aes_keyslot(unsigned int keyslot); -void clear_rsa_keyslot(unsigned int keyslot); -void clear_aes_keyslot_iv(unsigned int keyslot); - -void decrypt_data_into_keyslot_256(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size); - -void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); -void se_aes_256_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); - -#endif diff --git a/exosphere/lp0fw/src/secmon.c b/exosphere/lp0fw/src/secmon.c deleted file mode 100644 index 01a6ff539..000000000 --- a/exosphere/lp0fw/src/secmon.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 "utils.h" -#include "lp0.h" -#include "secmon.h" -#include "se.h" -#include "fuse.h" -#include "pmc.h" - -/* "private" functions. */ -static bool secmon_should_clear_aes_keyslot(unsigned int keyslot); -static void secmon_clear_unused_keyslots(void); -static void secmon_decrypt_saved_image(void *dst, const void *src, size_t size); - -void secmon_restore_to_tzram(const uint32_t target_firmware) { - /* Newer warmboot binaries clear the untouched keyslots for safety. */ - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - secmon_clear_unused_keyslots(); - } - - /* Decrypt Secure Monitor from DRAM into TZRAM. */ - void *tzram_src = (void *)(0x80010000); - void *tzram_dst = (void *)(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ? 0x7C012000 : 0x7C010000); - const size_t tzram_size = 0xE000; - secmon_decrypt_saved_image(tzram_dst, tzram_src, tzram_size); - - /* Nintendo clears DRAM, but I'm not sure why, given they lock out BPMP access to DRAM. */ - for (size_t i = 0; i < tzram_size/sizeof(uint32_t); i++) { - ((volatile uint32_t *)tzram_src)[i] = 0; - } - - /* Make security engine require secure busmaster. */ - se_get_regs()->SE_TZRAM_SECURITY = 0; - - /* TODO: se_verify_keys_unreadable(); */ - - /* TODO: pmc_lockout_wb_scratch_registers(); */ - - /* Disable fuse programming. */ - fuse_disable_programming(); -} - -void secmon_decrypt_saved_image(void *dst, const void *src, size_t size) { - /* Derive the key used for context save. */ - { - const uint32_t key_source[4] = { APBDEV_PMC_SECURE_SCRATCH24_0, APBDEV_PMC_SECURE_SCRATCH25_0, APBDEV_PMC_SECURE_SCRATCH26_0, APBDEV_PMC_SECURE_SCRATCH27_0 }; - - clear_aes_keyslot(KEYSLOT_SWITCH_LP0TZRAMKEY); - decrypt_data_into_keyslot_256(KEYSLOT_SWITCH_LP0TZRAMKEY, KEYSLOT_SWITCH_LP0TZRAMKEK, key_source, sizeof(key_source)); - - clear_aes_keyslot(KEYSLOT_SWITCH_LP0TZRAMKEK); - APBDEV_PMC_SECURE_SCRATCH24_0 = 0; - APBDEV_PMC_SECURE_SCRATCH25_0 = 0; - APBDEV_PMC_SECURE_SCRATCH26_0 = 0; - APBDEV_PMC_SECURE_SCRATCH27_0 = 0; - } - - /* First, AES-256-CBC decrypt the image into TZRAM. */ - se_aes_256_cbc_decrypt(KEYSLOT_SWITCH_LP0TZRAMKEY, dst, size, src, size); - - /* Next, calculate CMAC. */ - uint32_t tzram_cmac[4] = {0, 0, 0, 0}; - se_compute_aes_256_cmac(KEYSLOT_SWITCH_LP0TZRAMKEY, tzram_cmac, sizeof(tzram_cmac), dst, size); - - /* Validate the MAC against saved one in PMC scratch. */ - if (tzram_cmac[0] != APBDEV_PMC_SECURE_SCRATCH112_0 || - tzram_cmac[1] != APBDEV_PMC_SECURE_SCRATCH113_0 || - tzram_cmac[2] != APBDEV_PMC_SECURE_SCRATCH114_0 || - tzram_cmac[3] != APBDEV_PMC_SECURE_SCRATCH115_0) { - reboot(); - } - - /* Clear the PMC scratch registers that hold the CMAC. */ - APBDEV_PMC_SECURE_SCRATCH112_0 = 0; - APBDEV_PMC_SECURE_SCRATCH113_0 = 0; - APBDEV_PMC_SECURE_SCRATCH114_0 = 0; - APBDEV_PMC_SECURE_SCRATCH115_0 = 0; - - /* Clear keyslot now that we're done with it. */ - clear_aes_keyslot(KEYSLOT_SWITCH_LP0TZRAMKEY); -} - -bool secmon_should_clear_aes_keyslot(unsigned int keyslot) { - /* We'll just compare keyslot against a hardcoded list of keys. */ - static const uint8_t saved_keyslots[6] = { - KEYSLOT_SWITCH_LP0TZRAMKEK, - KEYSLOT_SWITCH_SESSIONKEY, - KEYSLOT_SWITCH_RNGKEY, - KEYSLOT_SWITCH_MASTERKEY, - KEYSLOT_SWITCH_DEVICEKEY, - KEYSLOT_SWITCH_4XOLDDEVICEKEY - }; - - for (unsigned int i = 0; i < sizeof(saved_keyslots)/sizeof(saved_keyslots[0]); i++) { - if (keyslot == saved_keyslots[i]) { - return false; - } - } - return true; -} - -void secmon_clear_unused_keyslots(void) { - /* Clear unused keyslots. */ - for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - if (secmon_should_clear_aes_keyslot(i)) { - clear_aes_keyslot(i); - } - clear_aes_keyslot_iv(i); - } - for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) { - clear_rsa_keyslot(i); - } -} diff --git a/exosphere/lp0fw/src/secmon.h b/exosphere/lp0fw/src/secmon.h deleted file mode 100644 index 2577f3855..000000000 --- a/exosphere/lp0fw/src/secmon.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_SECMON_H -#define EXOSPHERE_WARMBOOT_BIN_SECMON_H - -#include - -#include "utils.h" - -void secmon_restore_to_tzram(const uint32_t target_firmware); - -#endif diff --git a/exosphere/lp0fw/src/start.s b/exosphere/lp0fw/src/start.s deleted file mode 100644 index 5a458e123..000000000 --- a/exosphere/lp0fw/src/start.s +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 . - */ - -.section .text.start - -/* Warmboot header. */ -/* Binary size */ -.word __total_size__ -.rept 3 -.word 0x00000000 -.endr -/* RSA modulus */ -.rept 0x40 -.word 0xFFFFFFFF -.endr -/* Padding */ -.rept 4 -.word 0x00000000 -.endr -/* RSA signature */ -.rept 0x40 -.word 0xFFFFFFFF -.endr -/* Padding */ -.rept 4 -.word 0x00000000 -.endr -/* Relocation meta */ -.word __total_size__ -.word _start -.word _start -.word __executable_size__ - -.global _start -_start: - b crt0 - -.global _metadata -_metadata: - .ascii "WBT0" /* Magic number */ - .word 0x00000000 /* Target firmware. */ - .word 0x00000000 /* Reserved */ - .word 0x00000000 /* Reserved */ - -.global crt0 -.type crt0, %function -crt0: - @ setup to call lp0_entry_main - ldr sp, =__stack_top__ - ldr lr, =reboot - ldr r0, =_metadata - b lp0_entry_main diff --git a/exosphere/lp0fw/src/sysreg.h b/exosphere/lp0fw/src/sysreg.h deleted file mode 100644 index 10af8357b..000000000 --- a/exosphere/lp0fw/src/sysreg.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_SYSREG_H -#define EXOSPHERE_WARMBOOT_BIN_SYSREG_H - -#include - - -#define SYSREG_BASE (0x6000C000) - -#define SB_BASE (SYSREG_BASE + 0x200) - -#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n) -#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n) - -#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004) - -#define SB_CSR_0 MAKE_SB_REG(0x00) -#define SB_PIROM_START_0 MAKE_SB_REG(0x04) -#define SB_PFCFG_0 MAKE_SB_REG(0x08) -#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C) -#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10) -#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14) -#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18) -#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C) -#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20) -#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24) -#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28) -#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30) -#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34) - -#endif diff --git a/exosphere/lp0fw/src/timer.h b/exosphere/lp0fw/src/timer.h deleted file mode 100644 index ec2d3dfe6..000000000 --- a/exosphere/lp0fw/src/timer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_TIMER_H -#define EXOSPHERE_WARMBOOT_BIN_TIMER_H - -#include "utils.h" - -#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010) -#define TIMERUS_USEC_CFG_0 MAKE_REG32(0x60005014) - -static inline void timer_wait(uint32_t microseconds) { - const uint32_t old_time = TIMERUS_CNTR_1US_0; - while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { - /* Spin-lock. */ - } -} - -void spinlock_wait(uint32_t count); - -#endif diff --git a/exosphere/lp0fw/src/utils.h b/exosphere/lp0fw/src/utils.h deleted file mode 100644 index 88fd917c8..000000000 --- a/exosphere/lp0fw/src/utils.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_WARMBOOT_BIN_UTILS_H -#define EXOSPHERE_WARMBOOT_BIN_UTILS_H - -#include -#include -#include -#include - -#define BIT(n) (1u << (n)) -#define BITL(n) (1ull << (n)) -#define MASK(n) (BIT(n) - 1) -#define MASKL(n) (BITL(n) - 1) -#define MASK2(a,b) (MASK(a) & ~MASK(b)) -#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) - -#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) - -#define ALIGN(m) __attribute__((aligned(m))) -#define PACKED __attribute__((packed)) - -#define ALINLINE __attribute__((always_inline)) - -#endif diff --git a/exosphere/rebootstub/Makefile b/exosphere/rebootstub/Makefile deleted file mode 100644 index ff265beef..000000000 --- a/exosphere/rebootstub/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITARM)/base_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := src -DATA := data -INCLUDES := include - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork - -CFLAGS := \ - -g \ - -Os \ - -ffunction-sections \ - -fdata-sections \ - -fomit-frame-pointer \ - -fno-inline \ - -std=gnu11 \ - -Werror \ - -Wall \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) -D__BPMP__ - -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf - - -#--------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -all : $(OUTPUT).bin - -$(OUTPUT).bin : $(OUTPUT).elf - $(OBJCOPY) -S -O binary $< $@ - @echo built ... $(notdir $@) - -$(OUTPUT).elf : $(OFILES) - -%.elf: $(OFILES) - @echo linking $(notdir $@) - @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ - @$(NM) -CSn $@ > $(notdir $*.lst) - -$(OFILES_SRC) : $(HFILES_BIN) - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/exosphere/rebootstub/linker.ld b/exosphere/rebootstub/linker.ld deleted file mode 100644 index d2e018d4d..000000000 --- a/exosphere/rebootstub/linker.ld +++ /dev/null @@ -1,18 +0,0 @@ -OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") -OUTPUT_ARCH(arm) - -ENTRY(_start) -SECTIONS -{ - . = 0x4003F000; - - __start__ = ABSOLUTE(.); - - .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } - .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } - .bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; } - - . = ALIGN(4); - - __end__ = ABSOLUTE(.); -} \ No newline at end of file diff --git a/exosphere/rebootstub/linker.specs b/exosphere/rebootstub/linker.specs deleted file mode 100644 index 300990418..000000000 --- a/exosphere/rebootstub/linker.specs +++ /dev/null @@ -1,7 +0,0 @@ -%rename link old_link - -*link: -%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections - -*startfile: -crti%O%s crtbegin%O%s diff --git a/exosphere/rebootstub/src/i2c.c b/exosphere/rebootstub/src/i2c.c deleted file mode 100644 index fc380962b..000000000 --- a/exosphere/rebootstub/src/i2c.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 "max77620.h" -#include "i2c.h" -#include "timer.h" - -/* Prototypes for internal commands. */ -void i2c_load_config(void); -int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes); -int i2c_read(unsigned int device, void *dst, unsigned num_bytes); -int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes); -int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b); - -/* Load hardware config for I2C4. */ -void i2c_load_config(void) { - /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ - I2C_I2C_CONFIG_LOAD_0 = 0x25; - - /* Wait a bit for master config to be loaded. */ - for (unsigned int i = 0; i < 20; i++) { - timer_wait(1); - if (!(I2C_I2C_CONFIG_LOAD_0 & 1)) { - break; - } - } -} - -/* Initialize I2C4. */ -void i2c_init(void) { - /* Setup divisor, and clear the bus. */ - I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; - I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; - - /* Load hardware configuration. */ - i2c_load_config(); - - /* Wait a while until BUS_CLEAR_DONE is set. */ - for (unsigned int i = 0; i < 10; i++) { - timer_wait(20000); - if (I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { - break; - } - } - - /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ - I2C_I2C_BUS_CLEAR_STATUS_0; - - /* Read and set the Interrupt Status. */ - uint32_t int_status = I2C_INTERRUPT_STATUS_REGISTER_0; - I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; -} - -/* Writes a value to an i2c device. */ -int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) { - if (num_bytes > 4) { - return 0; - } - - /* Set device for 7-bit mode. */ - I2C_I2C_CMD_ADDR0_0 = device << 1; - - /* Load in data to write. */ - I2C_I2C_CMD_DATA1_0 = val; - - /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ - I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800; - - i2c_load_config(); - - /* Config |= SEND; */ - I2C_I2C_CNFG_0 |= 0x200; - - - while (I2C_I2C_STATUS_0 & 0x100) { - /* Wait until not busy. */ - } - - /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ - return (I2C_I2C_STATUS_0 & 0xF) == 0; -} - -/* Reads a value from an i2c device. */ -int i2c_read(unsigned device, void *dst, unsigned num_bytes) { - if (num_bytes > 4) { - return 0; - } - - /* Set device for 7-bit read mode. */ - I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1; - - /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ - I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2840; - - i2c_load_config(); - - /* Config |= SEND; */ - I2C_I2C_CNFG_0 |= 0x200; - - - while (I2C_I2C_STATUS_0 & 0x100) { - /* Wait until not busy. */ - } - - /* Ensure success. */ - if ((I2C_I2C_STATUS_0 & 0xF) != 0) { - return 0; - } - - uint32_t val = I2C_I2C_CMD_DATA1_0; - for (size_t i = 0; i < num_bytes; i++) { - ((uint8_t *)dst)[i] = ((uint8_t *)&val)[i]; - } - return 1; -} - -/* Queries the value of a register. */ -int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes) { - /* Limit output size to 32-bits. */ - if (num_bytes > 4) { - return 0; - } - - /* Write single byte register ID to device. */ - if (!i2c_write(device, r, 1)) { - return 0; - } - - return i2c_read(device, dst, num_bytes); - -} - -/* Writes a byte val to reg for given device. */ -int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) { - uint32_t val = (reg) | (b << 8); - /* Write 1 byte (reg) + 1 byte (value) */ - return i2c_write(device, val, 2); -} - -void i2c_stop_rtc_alarm(void) { - i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x10); - - uint8_t val = 0; - for (int i = 0; i < 14; i++) { - if (i2c_query(MAX77620_RTC_I2C_ADDR, 0x0E + i, &val, 1)) { - val &= 0x7F; - i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, 0x0E + i, val); - } - } - - i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x01); -} - -void i2c_send_shutdown_cmd(void) { - i2c_send_byte_command(MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); -} diff --git a/exosphere/rebootstub/src/i2c.h b/exosphere/rebootstub/src/i2c.h deleted file mode 100644 index 480ff41b8..000000000 --- a/exosphere/rebootstub/src/i2c.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_REBOOTSTUB_I2C_H -#define EXOSPHERE_REBOOTSTUB_I2C_H - -#include "utils.h" - -/* I2C_BASE = I2C4. */ -#define I2C_BASE (0x7000D000) - -#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs)) - -#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000) - -#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004) - -#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C) - -#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C) - -#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068) - -#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C) - -#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084) - -#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088) - - -#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C) - -void i2c_init(void); - -void i2c_stop_rtc_alarm(void); -void i2c_send_shutdown_cmd(void); - -#endif diff --git a/exosphere/rebootstub/src/max77620.h b/exosphere/rebootstub/src/max77620.h deleted file mode 100644 index 6cbaaa94e..000000000 --- a/exosphere/rebootstub/src/max77620.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Defining registers address and its bit definitions of MAX77620 and MAX20024 - * - * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. - * 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. - */ - -#ifndef _MFD_MAX77620_H_ -#define _MFD_MAX77620_H_ - -#define MAX77620_I2C_ADDR 0x3C -#define MAX77620_RTC_I2C_ADDR 0x68 - -/* RTC Registers */ -#define MAX77620_REG_RTCINT 0x00 -#define MAX77620_REG_RTCINTM 0x01 -#define MAX77620_REG_RTCCNTLM 0x02 -#define MAX77620_REG_RTCCNTL 0x03 -#define MAX77620_REG_RTCUPDATE0 0x04 -#define MAX77620_REG_RTCUPDATE1 0x05 -#define MAX77620_REG_RTCSMPL 0x06 -#define MAX77620_REG_RTCSEC 0x07 -#define MAX77620_REG_RTCMIN 0x08 -#define MAX77620_REG_RTCHOUR 0x09 -#define MAX77620_REG_RTCDOW 0x0A -#define MAX77620_REG_RTCMONTH 0x0B -#define MAX77620_REG_RTCYEAR 0x0C -#define MAX77620_REG_RTCDOM 0x0D -#define MAX77620_REG_RTCSECA1 0x0E -#define MAX77620_REG_RTCMINA1 0x0F -#define MAX77620_REG_RTCHOURA1 0x10 -#define MAX77620_REG_RTCDOWA1 0x11 -#define MAX77620_REG_RTCMONTHA1 0x12 -#define MAX77620_REG_RTCYEARA1 0x13 -#define MAX77620_REG_RTCDOMA1 0x14 -#define MAX77620_REG_RTCSECA2 0x15 -#define MAX77620_REG_RTCMINA2 0x16 -#define MAX77620_REG_RTCHOURA2 0x17 -#define MAX77620_REG_RTCDOWA2 0x18 -#define MAX77620_REG_RTCMONTHA2 0x19 -#define MAX77620_REG_RTCYEARA2 0x1A -#define MAX77620_REG_RTCDOMA2 0x1B - -/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ -#define MAX77620_REG_CNFGGLBL1 0x00 -#define MAX77620_REG_CNFGGLBL2 0x01 -#define MAX77620_REG_CNFGGLBL3 0x02 -#define MAX77620_REG_CNFG1_32K 0x03 -#define MAX77620_REG_CNFGBBC 0x04 -#define MAX77620_REG_IRQTOP 0x05 -#define MAX77620_REG_INTLBT 0x06 -#define MAX77620_REG_IRQSD 0x07 -#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 -#define MAX77620_REG_IRQ_LVL2_L8 0x09 -#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A -#define MAX77620_REG_ONOFFIRQ 0x0B -#define MAX77620_REG_NVERC 0x0C -#define MAX77620_REG_IRQTOPM 0x0D -#define MAX77620_REG_INTENLBT 0x0E -#define MAX77620_REG_IRQMASKSD 0x0F -#define MAX77620_REG_IRQ_MSK_L0_7 0x10 -#define MAX77620_REG_IRQ_MSK_L8 0x11 -#define MAX77620_REG_ONOFFIRQM 0x12 -#define MAX77620_REG_STATLBT 0x13 -#define MAX77620_REG_STATSD 0x14 -#define MAX77620_REG_ONOFFSTAT 0x15 - -/* SD and LDO Registers */ -#define MAX77620_REG_SD0 0x16 -#define MAX77620_REG_SD1 0x17 -#define MAX77620_REG_SD2 0x18 -#define MAX77620_REG_SD3 0x19 -#define MAX77620_REG_SD4 0x1A -#define MAX77620_REG_DVSSD0 0x1B -#define MAX77620_REG_DVSSD1 0x1C -#define MAX77620_REG_SD0_CFG 0x1D -#define MAX77620_REG_SD1_CFG 0x1E -#define MAX77620_REG_SD2_CFG 0x1F -#define MAX77620_REG_SD3_CFG 0x20 -#define MAX77620_REG_SD4_CFG 0x21 -#define MAX77620_REG_SD_CFG2 0x22 -#define MAX77620_REG_LDO0_CFG 0x23 -#define MAX77620_REG_LDO0_CFG2 0x24 -#define MAX77620_REG_LDO1_CFG 0x25 -#define MAX77620_REG_LDO1_CFG2 0x26 -#define MAX77620_REG_LDO2_CFG 0x27 -#define MAX77620_REG_LDO2_CFG2 0x28 -#define MAX77620_REG_LDO3_CFG 0x29 -#define MAX77620_REG_LDO3_CFG2 0x2A -#define MAX77620_REG_LDO4_CFG 0x2B -#define MAX77620_REG_LDO4_CFG2 0x2C -#define MAX77620_REG_LDO5_CFG 0x2D -#define MAX77620_REG_LDO5_CFG2 0x2E -#define MAX77620_REG_LDO6_CFG 0x2F -#define MAX77620_REG_LDO6_CFG2 0x30 -#define MAX77620_REG_LDO7_CFG 0x31 -#define MAX77620_REG_LDO7_CFG2 0x32 -#define MAX77620_REG_LDO8_CFG 0x33 -#define MAX77620_REG_LDO8_CFG2 0x34 -#define MAX77620_REG_LDO_CFG3 0x35 - -#define MAX77620_LDO_SLEW_RATE_MASK 0x1 - -/* LDO Configuration 3 */ -#define MAX77620_TRACK4_MASK (1 << 5) -#define MAX77620_TRACK4_SHIFT 5 - -/* Voltage */ -#define MAX77620_SDX_VOLT_MASK 0xFF -#define MAX77620_SD0_VOLT_MASK 0x3F -#define MAX77620_SD1_VOLT_MASK 0x7F -#define MAX77620_LDO_VOLT_MASK 0x3F - -#define MAX77620_REG_GPIO0 0x36 -#define MAX77620_REG_GPIO1 0x37 -#define MAX77620_REG_GPIO2 0x38 -#define MAX77620_REG_GPIO3 0x39 -#define MAX77620_REG_GPIO4 0x3A -#define MAX77620_REG_GPIO5 0x3B -#define MAX77620_REG_GPIO6 0x3C -#define MAX77620_REG_GPIO7 0x3D -#define MAX77620_REG_PUE_GPIO 0x3E -#define MAX77620_REG_PDE_GPIO 0x3F -#define MAX77620_REG_AME_GPIO 0x40 -#define MAX77620_REG_ONOFFCNFG1 0x41 -#define MAX77620_REG_ONOFFCNFG2 0x42 - -/* FPS Registers */ -#define MAX77620_REG_FPS_CFG0 0x43 -#define MAX77620_REG_FPS_CFG1 0x44 -#define MAX77620_REG_FPS_CFG2 0x45 -#define MAX77620_REG_FPS_LDO0 0x46 -#define MAX77620_REG_FPS_LDO1 0x47 -#define MAX77620_REG_FPS_LDO2 0x48 -#define MAX77620_REG_FPS_LDO3 0x49 -#define MAX77620_REG_FPS_LDO4 0x4A -#define MAX77620_REG_FPS_LDO5 0x4B -#define MAX77620_REG_FPS_LDO6 0x4C -#define MAX77620_REG_FPS_LDO7 0x4D -#define MAX77620_REG_FPS_LDO8 0x4E -#define MAX77620_REG_FPS_SD0 0x4F -#define MAX77620_REG_FPS_SD1 0x50 -#define MAX77620_REG_FPS_SD2 0x51 -#define MAX77620_REG_FPS_SD3 0x52 -#define MAX77620_REG_FPS_SD4 0x53 -#define MAX77620_REG_FPS_NONE 0 - -#define MAX77620_FPS_SRC_MASK 0xC0 -#define MAX77620_FPS_SRC_SHIFT 6 -#define MAX77620_FPS_PU_PERIOD_MASK 0x38 -#define MAX77620_FPS_PU_PERIOD_SHIFT 3 -#define MAX77620_FPS_PD_PERIOD_MASK 0x07 -#define MAX77620_FPS_PD_PERIOD_SHIFT 0 -#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 -#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 -#define MAX77620_FPS_EN_SRC_MASK 0x06 -#define MAX77620_FPS_EN_SRC_SHIFT 1 -#define MAX77620_FPS_ENFPS_SW_MASK 0x01 -#define MAX77620_FPS_ENFPS_SW 0x01 - -/* Minimum and maximum FPS period time (in microseconds) are - * different for MAX77620 and Max20024. - */ -#define MAX77620_FPS_PERIOD_MIN_US 40 -#define MAX20024_FPS_PERIOD_MIN_US 20 - -#define MAX77620_FPS_PERIOD_MAX_US 2560 -#define MAX20024_FPS_PERIOD_MAX_US 5120 - -#define MAX77620_REG_FPS_GPIO1 0x54 -#define MAX77620_REG_FPS_GPIO2 0x55 -#define MAX77620_REG_FPS_GPIO3 0x56 -#define MAX77620_REG_FPS_RSO 0x57 -#define MAX77620_REG_CID0 0x58 -#define MAX77620_REG_CID1 0x59 -#define MAX77620_REG_CID2 0x5A -#define MAX77620_REG_CID3 0x5B -#define MAX77620_REG_CID4 0x5C -#define MAX77620_REG_CID5 0x5D - -#define MAX77620_REG_DVSSD4 0x5E -#define MAX20024_REG_MAX_ADD 0x70 - -#define MAX77620_CID_DIDM_MASK 0xF0 -#define MAX77620_CID_DIDM_SHIFT 4 - -/* CNCG2SD */ -#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) -#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) - -/* Device Identification Metal */ -#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) -/* Device Indentification OTP */ -#define MAX77620_CID5_DIDO(n) ((n) & 0xF) - -/* SD CNFG1 */ -#define MAX77620_SD_SR_MASK 0xC0 -#define MAX77620_SD_SR_SHIFT 6 -#define MAX77620_SD_POWER_MODE_MASK 0x30 -#define MAX77620_SD_POWER_MODE_SHIFT 4 -#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) -#define MAX77620_SD_CFG1_ADE_DISABLE 0 -#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) -#define MAX77620_SD_FPWM_MASK 0x04 -#define MAX77620_SD_FPWM_SHIFT 2 -#define MAX77620_SD_FSRADE_MASK 0x01 -#define MAX77620_SD_FSRADE_SHIFT 0 -#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) -#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 -#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) -#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) -#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) -#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 -#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) - -/* LDO_CNFG2 */ -#define MAX77620_LDO_POWER_MODE_MASK 0xC0 -#define MAX77620_LDO_POWER_MODE_SHIFT 6 -#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) -#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) -#define MAX77620_LDO_CFG2_ADE_DISABLE 0 -#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) -#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) -#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) -#define MAX77620_LDO_CFG2_SS_SLOW 0 - -#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) -#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) -#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) -#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) -#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) -#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) -#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) - -#define MAX77620_IRQ_LBM_MASK (1 << 3) -#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) -#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) - -#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 -#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 -#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 -#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) -#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) -#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) -#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) -#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) -#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) -#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) -#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) - -#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) -#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) -#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) -#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) -#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) -#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) -#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) -#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) - -#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) - -#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) -#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 -#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 -#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) -#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) -#define MAX20024_ONOFFCNFG1_CLRSE 0x18 - -#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) -#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) -#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) -#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) -#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) - -#define MAX77620_GLBLM_MASK (1 << 0) - -#define MAX77620_WDTC_MASK 0x3 -#define MAX77620_WDTOFFC (1 << 4) -#define MAX77620_WDTSLPC (1 << 3) -#define MAX77620_WDTEN (1 << 2) - -#define MAX77620_TWD_MASK 0x3 -#define MAX77620_TWD_2s 0x0 -#define MAX77620_TWD_16s 0x1 -#define MAX77620_TWD_64s 0x2 -#define MAX77620_TWD_128s 0x3 - -#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) -#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) -#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) -#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4) -#define MAX77620_CNFGGLBL1_LBDAC 0x0E -#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1) -#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) - -/* CNFG BBC registers */ -#define MAX77620_CNFGBBC_ENABLE (1 << 0) -#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 -#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 -#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 -#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 -#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) -#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 -#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 - -#define MAX77620_FPS_COUNT 3 - -/* Interrupts */ -enum { - MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ - MAX77620_IRQ_TOP_SD, /* SD power fail */ - MAX77620_IRQ_TOP_LDO, /* LDO power fail */ - MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ - MAX77620_IRQ_TOP_RTC, /* RTC */ - MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ - MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ - MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ -}; - -/* GPIOs */ -enum { - MAX77620_GPIO0, - MAX77620_GPIO1, - MAX77620_GPIO2, - MAX77620_GPIO3, - MAX77620_GPIO4, - MAX77620_GPIO5, - MAX77620_GPIO6, - MAX77620_GPIO7, - MAX77620_GPIO_NR, -}; - -/* FPS Source */ -enum max77620_fps_src { - MAX77620_FPS_SRC_0, - MAX77620_FPS_SRC_1, - MAX77620_FPS_SRC_2, - MAX77620_FPS_SRC_NONE, - MAX77620_FPS_SRC_DEF, -}; - -enum max77620_chip_id { - MAX77620, - MAX20024, -}; - -#endif /* _MFD_MAX77620_H_ */ diff --git a/exosphere/rebootstub/src/shutdown.c b/exosphere/rebootstub/src/shutdown.c deleted file mode 100644 index 49353eadb..000000000 --- a/exosphere/rebootstub/src/shutdown.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 "utils.h" -#include "i2c.h" -#include "timer.h" - -void do_shutdown(void) { - /* Initialize i2c. */ - i2c_init(); - - /* Stop alarm, shutdown. */ - i2c_stop_rtc_alarm(); - i2c_send_shutdown_cmd(); - - while (true) { } -} \ No newline at end of file diff --git a/exosphere/rebootstub/src/start.s b/exosphere/rebootstub/src/start.s deleted file mode 100644 index e32319534..000000000 --- a/exosphere/rebootstub/src/start.s +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 . - */ - -.section .text.start -.align 4 -.global _start -_start: - ldr r0, reboot_type - cmp r0, #0x0 - beq do_shutdown - b jump_to_reboot_payload -reboot_type: -.word 0x00000001 - -.global jump_to_reboot_payload -.type jump_to_reboot_payload, %function -jump_to_reboot_payload: - @ clear all registers - ldr r0, =0x52425430 @ RBT0 - mov r1, #0x0 - mov r2, #0x0 - mov r3, #0x0 - mov r4, #0x0 - mov r5, #0x0 - mov r6, #0x0 - mov r7, #0x0 - mov r8, #0x0 - mov r9, #0x0 - mov r10, #0x0 - mov r11, #0x0 - mov r12, #0x0 - mov lr, #0x0 - ldr sp, =0x40010000 - ldr pc, =0x40010000 - - - diff --git a/exosphere/rebootstub/src/timer.h b/exosphere/rebootstub/src/timer.h deleted file mode 100644 index 334bff1a8..000000000 --- a/exosphere/rebootstub/src/timer.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_REBOOTSTUB_TIMER_H -#define EXOSPHERE_REBOOTSTUB_TIMER_H - -#include "utils.h" - -#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010) - -static inline void timer_wait(uint32_t microseconds) { - uint32_t old_time = TIMERUS_CNTR_1US_0; - while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { - /* Spin-lock. */ - } -} - -void spinlock_wait(uint32_t count); - -#endif diff --git a/exosphere/rebootstub/src/utils.h b/exosphere/rebootstub/src/utils.h deleted file mode 100644 index eae0a6d7a..000000000 --- a/exosphere/rebootstub/src/utils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_REBOOTSTUB_UTILS_H -#define EXOSPHERE_REBOOTSTUB_UTILS_H - -#include -#include -#include - -#define BIT(n) (1u << (n)) -#define BITL(n) (1ull << (n)) -#define MASK(n) (BIT(n) - 1) -#define MASKL(n) (BITL(n) - 1) -#define MASK2(a,b) (MASK(a) & ~MASK(b)) -#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) - -#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) - -#define ALIGN(m) __attribute__((aligned(m))) -#define PACKED __attribute__((packed)) - -#define ALINLINE __attribute__((always_inline)) - -#endif diff --git a/exosphere/sc7fw/Makefile b/exosphere/sc7fw/Makefile deleted file mode 100644 index ff265beef..000000000 --- a/exosphere/sc7fw/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITARM)/base_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := src -DATA := data -INCLUDES := include - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork - -CFLAGS := \ - -g \ - -Os \ - -ffunction-sections \ - -fdata-sections \ - -fomit-frame-pointer \ - -fno-inline \ - -std=gnu11 \ - -Werror \ - -Wall \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) -D__BPMP__ - -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf - - -#--------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -all : $(OUTPUT).bin - -$(OUTPUT).bin : $(OUTPUT).elf - $(OBJCOPY) -S -O binary $< $@ - @echo built ... $(notdir $@) - -$(OUTPUT).elf : $(OFILES) - -%.elf: $(OFILES) - @echo linking $(notdir $@) - @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ - @$(NM) -CSn $@ > $(notdir $*.lst) - -$(OFILES_SRC) : $(HFILES_BIN) - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/exosphere/sc7fw/linker.ld b/exosphere/sc7fw/linker.ld deleted file mode 100644 index fd4272593..000000000 --- a/exosphere/sc7fw/linker.ld +++ /dev/null @@ -1,21 +0,0 @@ -OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") -OUTPUT_ARCH(arm) - -ENTRY(_start) -SECTIONS -{ - . = 0x40003000; - - __start__ = ABSOLUTE(.); - - .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } - .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } - .bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; } - - . = ALIGN(4); - - __end__ = ABSOLUTE(.); - - __stack_top__ = 0x40005000; - __stack_bottom__ = 0x40004000; -} \ No newline at end of file diff --git a/exosphere/sc7fw/linker.specs b/exosphere/sc7fw/linker.specs deleted file mode 100644 index 300990418..000000000 --- a/exosphere/sc7fw/linker.specs +++ /dev/null @@ -1,7 +0,0 @@ -%rename link old_link - -*link: -%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections - -*startfile: -crti%O%s crtbegin%O%s diff --git a/exosphere/sc7fw/src/emc.c b/exosphere/sc7fw/src/emc.c deleted file mode 100644 index fa92a5f46..000000000 --- a/exosphere/sc7fw/src/emc.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 "utils.h" -#include "sc7.h" -#include "emc.h" -#include "pmc.h" -#include "timer.h" - -static void emc_trigger_timing_update(void) { - EMC_TIMING_CONTROL_0 = 1; - while (EMC_EMC_STATUS_0 & 0x800000) { - /* Wait until TIMING_UPDATE_STALLED is unset. */ - } -} - -/* Puts DRAM into self refresh mode. */ -void emc_put_dram_in_self_refresh_mode(void) { - /* Verify CH1_ENABLE [PMC]. */ - if (!(EMC_FBIO_CFG7_0 & 4)) { - reboot(); - } - - /* Clear config. */ - EMC_CFG_0 = 0; - emc_trigger_timing_update(); - timer_wait(5); - - /* Set calibration intervals. */ - EMC_ZCAL_INTERVAL_0 = 0; - EMC_AUTO_CAL_CONFIG_0 = 0x600; /* AUTO_CAL_MEASURE_STALL | AUTO_CAL_UPDATE_STALL */ - - /* If EMC0 mirror is set, clear digital DLL. */ - if (EMC0_CFG_DIG_DLL_0 & 1) { - EMC_CFG_DIG_DLL_0 &= 0xFFFFFFFE; - emc_trigger_timing_update(); - while (EMC0_CFG_DIG_DLL_0 & 1) { /* Wait for EMC0 to clear. */ } - while (EMC1_CFG_DIG_DLL_0 & 1) { /* Wait for EMC1 to clear. */ } - } else { - emc_trigger_timing_update(); - } - - /* Stall all transactions to DRAM. */ - EMC_REQ_CTRL_0 = 3; /* STALL_ALL_WRITES | STALL_ALL_READS. */ - while (!(EMC0_EMC_STATUS_0 & 4)) { /* Wait for NO_OUTSTANDING_TRANSACTIONS for EMC0. */ } - while (!(EMC1_EMC_STATUS_0 & 4)) { /* Wait for NO_OUTSTANDING_TRANSACTIONS for EMC1. */ } - - /* Enable Self-Refresh Mode. */ - EMC_SELF_REF_0 |= 1; - - - /* Wait until we see the right devices in self refresh mode. */ - uint32_t num_populated_devices = 1; - if (EMC_ADR_CFG_0) { - num_populated_devices = 3; - } - - while (((EMC0_EMC_STATUS_0 >> 8) & 3) != num_populated_devices) { /* Wait for EMC0 DRAM_IN_SELF_REFRESH to be correct. */ } - while (((EMC1_EMC_STATUS_0 >> 8) & 3) != num_populated_devices) { /* Wait for EMC1 DRAM_IN_SELF_REFRESH to be correct. */ } -} diff --git a/exosphere/sc7fw/src/emc.h b/exosphere/sc7fw/src/emc.h deleted file mode 100644 index cc9845221..000000000 --- a/exosphere/sc7fw/src/emc.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BPMPFW_EMC_H -#define EXOSPHERE_BPMPFW_EMC_H - -#include "utils.h" - -#define EMC_BASE (0x7001B000) - -#define EMC0_BASE (0x7001E000) -#define EMC1_BASE (0x7001F000) - - -#define MAKE_EMC_REG(ofs) (MAKE_REG32(EMC_BASE + ofs)) - -#define MAKE_EMC0_REG(ofs) (MAKE_REG32(EMC0_BASE + ofs)) -#define MAKE_EMC1_REG(ofs) (MAKE_REG32(EMC1_BASE + ofs)) - -#define EMC_CFG_0 MAKE_EMC_REG(0x00C) - -#define EMC_ADR_CFG_0 MAKE_EMC_REG(0x10) - -#define EMC_TIMING_CONTROL_0 MAKE_EMC_REG(0x028) - -#define EMC_SELF_REF_0 MAKE_EMC_REG(0x0E0) - -#define EMC_MRW_0 MAKE_EMC_REG(0x0E8) - -#define EMC_FBIO_CFG5_0 MAKE_EMC_REG(0x104) - -#define EMC_MRW3_0 MAKE_EMC_REG(0x138) - -#define EMC_AUTO_CAL_CONFIG_0 MAKE_EMC_REG(0x2A4) - -#define EMC_REQ_CTRL_0 MAKE_EMC_REG(0x2B0) - -#define EMC_EMC_STATUS_0 MAKE_EMC_REG(0x2B4) -#define EMC0_EMC_STATUS_0 MAKE_EMC0_REG(0x2B4) -#define EMC1_EMC_STATUS_0 MAKE_EMC1_REG(0x2B4) - -#define EMC_CFG_DIG_DLL_0 MAKE_EMC_REG(0x2BC) -#define EMC0_CFG_DIG_DLL_0 MAKE_EMC0_REG(0x2BC) -#define EMC1_CFG_DIG_DLL_0 MAKE_EMC1_REG(0x2BC) - -#define EMC_ZCAL_INTERVAL_0 MAKE_EMC_REG(0x2E0) - -#define EMC_PMC_SCRATCH3_0 MAKE_EMC_REG(0x448) - -#define EMC_FBIO_CFG7_0 MAKE_EMC_REG(0x584) - -void emc_put_dram_in_self_refresh_mode(void); - -#endif diff --git a/exosphere/sc7fw/src/i2c.c b/exosphere/sc7fw/src/i2c.c deleted file mode 100644 index a938936a0..000000000 --- a/exosphere/sc7fw/src/i2c.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 "i2c.h" -#include "timer.h" - -/* Prototypes for internal commands. */ -void i2c_load_config(void); -int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes); -int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b); - -/* Load hardware config for I2C4. */ -void i2c_load_config(void) { - /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ - I2C_I2C_CONFIG_LOAD_0 = 0x25; - - /* Wait a bit for master config to be loaded. */ - for (unsigned int i = 0; i < 20; i++) { - timer_wait(1); - if (!(I2C_I2C_CONFIG_LOAD_0 & 1)) { - break; - } - } -} - -/* Initialize I2C4. */ -void i2c_init(void) { - /* Setup divisor, and clear the bus. */ - I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; - I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; - - /* Load hardware configuration. */ - i2c_load_config(); - - /* Wait a while until BUS_CLEAR_DONE is set. */ - for (unsigned int i = 0; i < 10; i++) { - timer_wait(20000); - if (I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { - break; - } - } - - /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ - I2C_I2C_BUS_CLEAR_STATUS_0; - - /* Read and set the Interrupt Status. */ - uint32_t int_status = I2C_INTERRUPT_STATUS_REGISTER_0; - I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; -} - -/* Writes a value to an i2c device. */ -int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) { - if (num_bytes > 4) { - return 0; - } - - /* Set device for 7-bit mode. */ - I2C_I2C_CMD_ADDR0_0 = device << 1; - - /* Load in data to write. */ - I2C_I2C_CMD_DATA1_0 = val; - - /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ - I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800; - - i2c_load_config(); - - /* Config |= SEND; */ - I2C_I2C_CNFG_0 |= 0x200; - - - while (I2C_I2C_STATUS_0 & 0x100) { - /* Wait until not busy. */ - } - - /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ - return (I2C_I2C_STATUS_0 & 0xF) == 0; -} - -/* Writes a byte val to reg for given device. */ -int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) { - uint32_t val = (reg) | (b << 8); - /* Write 1 byte (reg) + 1 byte (value) */ - return i2c_write(device, val, 2); -} - -/* Actually reset device 27. This might turn off the screen? */ -int i2c_send_reset_cmd(void) { - /* Write 00 to Device 27 Reg 00. */ - return i2c_send_byte_command(27, 0, 0); -} diff --git a/exosphere/sc7fw/src/i2c.h b/exosphere/sc7fw/src/i2c.h deleted file mode 100644 index 608069255..000000000 --- a/exosphere/sc7fw/src/i2c.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BPMPFW_I2C_H -#define EXOSPHERE_BPMPFW_I2C_H - -#include "utils.h" - -/* I2C_BASE = I2C4. */ -#define I2C_BASE (0x7000D000) - -#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs)) - -#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000) - -#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004) - -#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C) - -#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C) - -#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068) - -#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C) - -#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084) - -#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088) - - -#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C) - -void i2c_init(void); - -int i2c_send_reset_cmd(void); - -#endif diff --git a/exosphere/sc7fw/src/pmc.h b/exosphere/sc7fw/src/pmc.h deleted file mode 100644 index 21224fa69..000000000 --- a/exosphere/sc7fw/src/pmc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BPMPFW_PMC_H -#define EXOSPHERE_BPMPFW_PMC_H - -#include "utils.h" - -#define PMC_BASE (0x7000E400) - -#define MAKE_PMC_REG(ofs) (MAKE_REG32(PMC_BASE + ofs)) - -#define APBDEV_PMC_CNTRL_0 MAKE_PMC_REG(0x000) - -#define APBDEV_PMC_DPD_SAMPLE_0 MAKE_PMC_REG(0x020) - -#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x024) - -#define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C) - -#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038) - -#define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080) -#define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084) -#define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) - - -#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) - -#define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) -#define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460) - -#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464) -#define APBDEV_PMC_IO_DPD4_STATUS_0 MAKE_PMC_REG(0x468) - -#define APBDEV_PMC_SET_SW_CLAMP_0 MAKE_PMC_REG(0x47C) - -#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4) - -#endif diff --git a/exosphere/sc7fw/src/sc7.c b/exosphere/sc7fw/src/sc7.c deleted file mode 100644 index 67cef4328..000000000 --- a/exosphere/sc7fw/src/sc7.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 "utils.h" -#include "sc7.h" -#include "i2c.h" -#include "pmc.h" -#include "emc.h" -#include "timer.h" - -#define CACHE_CTRL MAKE_REG32(0x50040000) - -#define PRI_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004038) -#define SEC_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004138) -#define TRI_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004238) -#define QUAD_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004338) -#define PENTA_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004438) -#define HEXA_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004538) - -void reboot(void) { - /* Write MAIN_RST */ - APBDEV_PMC_CNTRL_0 = 0x10; - while (true) { - /* Wait for reboot. */ - } -} - - -static void set_pmc_dpd_io_pads(void) { - /* Read val from EMC_PMC scratch, configure accordingly. */ - uint32_t emc_pmc_val = EMC_PMC_SCRATCH3_0; - APBDEV_PMC_DDR_CNTRL_0 = emc_pmc_val & 0x7FFFF; - if (emc_pmc_val & 0x40000000) { - APBDEV_PMC_WEAK_BIAS_0 = 0x7FFF0000; - } - /* Request to put pads in Deep Power Down. */ - APBDEV_PMC_IO_DPD3_REQ_0 = 0x8FFFFFFF; - while (APBDEV_PMC_IO_DPD3_STATUS_0 != 0xFFFFFFF) { /* Wait a while. */ } - spinlock_wait(32); - APBDEV_PMC_IO_DPD4_REQ_0 = 0x8FFFFFFF; - while (APBDEV_PMC_IO_DPD4_STATUS_0 != 0xFFF1FFF) { /* Wait a while. */ } - spinlock_wait(32); -} - -void sc7_entry_main(void) { - /* Disable the BPMP Cache. */ - CACHE_CTRL |= 0xC00; - - /* Wait until the CPU Rail is turned off. */ - while (APBDEV_PMC_PWRGATE_STATUS_0 & 1) { /* Wait for TrustZone to finish. */ } - - /* Clamp the CPU Rail. */ - APBDEV_PMC_SET_SW_CLAMP_0 |= 0x1; - while (!(APBDEV_PMC_CLAMP_STATUS_0 & 1)) { /* Wait for CPU Rail to be clamped. */ } - - /* Waste some time. */ - spinlock_wait(10); - - /* Reset device 27 over I2C, then wait a while. */ - i2c_init(); - i2c_send_reset_cmd(); - timer_wait(700); - - /* Clear Interrupt Enable for BPMP in all ICTLRs. */ - PRI_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; - SEC_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; - TRI_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; - QUAD_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; - PENTA_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; - HEXA_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; - - /* Write EMC's DRAM op into PMC scratch. */ - if ((EMC_FBIO_CFG5_0 & 3) != 1) { - /* If DRAM_TYPE != LPDDR4, something's gone wrong. Reboot. */ - reboot(); - } - /* Write MRW3_OP into scratch. */ - APBDEV_PMC_SCRATCH18_0 = (APBDEV_PMC_SCRATCH18_0 & 0xFFFFFF3F) | (EMC_MRW3_0 & 0xC0); - uint32_t mrw3_op = ((EMC_MRW3_0 & 0xC0) << 8) | (EMC_MRW3_0 & 0xC0); - APBDEV_PMC_SCRATCH12_0 = (APBDEV_PMC_SCRATCH12_0 & 0xFFFF3F3F) | mrw3_op; - APBDEV_PMC_SCRATCH13_0 = (APBDEV_PMC_SCRATCH13_0 & 0xFFFF3F3F) | mrw3_op; - - /* Ready DRAM for deep sleep. */ - emc_put_dram_in_self_refresh_mode(); - - /* Setup LPDDR MRW based on device config. */ - EMC_MRW_0 = 0x88110000; - if (EMC_ADR_CFG_0 & 1) { - EMC_MRW_0 = 0x48110000; - } - - /* Put IO pads in Deep Power Down. */ - set_pmc_dpd_io_pads(); - - /* Enable pad sampling during deep sleep. */ - APBDEV_PMC_DPD_SAMPLE_0 |= 1; - - /* Waste some more time. */ - spinlock_wait(0x128); - - /* Enter deep sleep. */ - APBDEV_PMC_DPD_ENABLE_0 |= 1; - - while (true) { /* Wait until we're asleep. */ } -} - - diff --git a/exosphere/sc7fw/src/sc7.h b/exosphere/sc7fw/src/sc7.h deleted file mode 100644 index 03544c453..000000000 --- a/exosphere/sc7fw/src/sc7.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BPMPFW_SC7_H -#define EXOSPHERE_BPMPFW_SC7_H - -#include "utils.h" - -void sc7_entry_main(void); - -void reboot(void); - -#endif diff --git a/exosphere/sc7fw/src/start.s b/exosphere/sc7fw/src/start.s deleted file mode 100644 index f4f639daf..000000000 --- a/exosphere/sc7fw/src/start.s +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 . - */ - -.section .text.start -.align 4 -.global _start -_start: - b crt0 -.global _reboot - b reboot - -.global crt0 -.type crt0, %function -crt0: - @ setup to call sc7_entry_main - msr cpsr_cxsf, #0xD3 - ldr sp, =__stack_top__ - ldr lr, =reboot - b sc7_entry_main - - -.global spinlock_wait -.type spinlock_wait, %function -spinlock_wait: - subs r0, r0, #1 - bgt spinlock_wait - bx lr diff --git a/exosphere/sc7fw/src/timer.h b/exosphere/sc7fw/src/timer.h deleted file mode 100644 index 023bd443e..000000000 --- a/exosphere/sc7fw/src/timer.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BPMPFW_TIMER_H -#define EXOSPHERE_BPMPFW_TIMER_H - -#include "utils.h" - -#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010) - -static inline void timer_wait(uint32_t microseconds) { - uint32_t old_time = TIMERUS_CNTR_1US_0; - while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { - /* Spin-lock. */ - } -} - -void spinlock_wait(uint32_t count); - -#endif diff --git a/exosphere/sc7fw/src/utils.h b/exosphere/sc7fw/src/utils.h deleted file mode 100644 index 8e96a937d..000000000 --- a/exosphere/sc7fw/src/utils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BPMPFW_UTILS_H -#define EXOSPHERE_BPMPFW_UTILS_H - -#include -#include -#include - -#define BIT(n) (1u << (n)) -#define BITL(n) (1ull << (n)) -#define MASK(n) (BIT(n) - 1) -#define MASKL(n) (BITL(n) - 1) -#define MASK2(a,b) (MASK(a) & ~MASK(b)) -#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) - -#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) - -#define ALIGN(m) __attribute__((aligned(m))) -#define PACKED __attribute__((packed)) - -#define ALINLINE __attribute__((always_inline)) - -#endif diff --git a/exosphere/src/actmon.c b/exosphere/src/actmon.c deleted file mode 100644 index f638453fd..000000000 --- a/exosphere/src/actmon.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 "utils.h" -#include "actmon.h" - -static void (*g_actmon_callback)(void) = NULL; - -void actmon_set_callback(void (*callback)(void)) { - g_actmon_callback = callback; -} - -void actmon_on_bpmp_wakeup(void) { - /* This gets set as the actmon interrupt handler on 4.x. */ - panic(0xF0A00036); -} - -void actmon_interrupt_handler(void) { - ACTMON_COP_CTRL_0 = 0; - ACTMON_COP_INTR_STATUS_0 = ACTMON_COP_INTR_STATUS_0; - if (g_actmon_callback != NULL) { - g_actmon_callback(); - g_actmon_callback = NULL; - } -} \ No newline at end of file diff --git a/exosphere/src/actmon.h b/exosphere/src/actmon.h deleted file mode 100644 index 37038e465..000000000 --- a/exosphere/src/actmon.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_ACTIVITY_MONITOR_H -#define EXOSPHERE_ACTIVITY_MONITOR_H - -#include "sysreg.h" - -/* Exosphere Driver for the Tegra X1 Activity Monitor. */ - -/* NOTE: ACTMON registers lie in the SYSREG region! */ -#define ACTMON_BASE (SYSREG_BASE + 0x800) - -#define MAKE_ACTMON_REG(n) MAKE_REG32(ACTMON_BASE + n) - -#define ACTMON_GLB_STATUS_0 MAKE_ACTMON_REG(0x000) -#define ACTMON_GLB_PERIOD_CTRL_0 MAKE_ACTMON_REG(0x004) -#define ACTMON_COP_CTRL_0 MAKE_ACTMON_REG(0x0C0) -#define ACTMON_COP_UPPER_WMARK_0 MAKE_ACTMON_REG(0x0C4) -#define ACTMON_COP_INTR_STATUS_0 MAKE_ACTMON_REG(0x0E4) - -void actmon_interrupt_handler(void); - -void actmon_on_bpmp_wakeup(void); - -void actmon_set_callback(void (*callback)(void)); - -#endif diff --git a/exosphere/src/arm.h b/exosphere/src/arm.h deleted file mode 100644 index 565d93acc..000000000 --- a/exosphere/src/arm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_ARM_H -#define EXOSPHERE_ARM_H - -#include - -void tlb_invalidate_all(void); -void tlb_invalidate_all_inner_shareable(void); - -void tlb_invalidate_page(const volatile void *page); -void tlb_invalidate_page_inner_shareable(const void *page); - -void flush_dcache_all(void); -void invalidate_dcache_all(void); - -void flush_dcache_range(const void *start, const void *end); -void invalidate_dcache_range(const void *start, const void *end); - -void invalidate_icache_all_inner_shareable(void); -void invalidate_icache_all(void); - -void finalize_powerdown(void); -void call_with_stack_pointer(uintptr_t stack_pointer, void (*function)(void)); - -#endif diff --git a/exosphere/src/arm.s b/exosphere/src/arm.s deleted file mode 100644 index dd943d1b5..000000000 --- a/exosphere/src/arm.s +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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 . - */ - -#define cpuactlr_el1 s3_1_c15_c2_0 -#define cpuectlr_el1 s3_1_c15_c2_1 - -.section .text.tlb_invalidate_all, "ax", %progbits -.type tlb_invalidate_all, %function -.global tlb_invalidate_all -tlb_invalidate_all: - dsb sy - tlbi alle3 - dsb sy - isb - ret - -.section .text.tlb_invalidate_all_inner_shareable, "ax", %progbits -.type tlb_invalidate_all_inner_shareable, %function -.global tlb_invalidate_all_inner_shareable -tlb_invalidate_all_inner_shareable: - dsb ish - tlbi alle3is - dsb ish - isb - ret - -.section .text.tlb_invalidate_page, "ax", %progbits -.type tlb_invalidate_page, %function -.global tlb_invalidate_page -tlb_invalidate_page: - lsr x8, x0, #12 - dsb sy - tlbi vale3, x8 - dsb sy - isb - ret - -.section .text.tlb_invalidate_page_inner_shareable, "ax", %progbits -.type tlb_invalidate_page_inner_shareable, %function -.global tlb_invalidate_page_inner_shareable -tlb_invalidate_page_inner_shareable: - lsr x8, x0, #12 - dsb ish - tlbi vale3is, x8 - dsb ish - isb - ret - -/* The following functions are taken/adapted from https://github.com/u-boot/u-boot/blob/master/arch/arm/cpu/armv8/cache.S */ - -/* - * (C) Copyright 2013 - * David Feng - * - * This file is based on sample code from ARMv8 ARM. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * void __asm_dcache_level(level) - * - * flush or invalidate one level cache. - * - * x0: cache level - * x1: 0 clean & invalidate, 1 invalidate only - * x2~x9: clobbered - */ -.section .warm_crt0.text.__asm_dcache_level, "ax", %progbits -.type __asm_dcache_level, %function -__asm_dcache_level: - lsl x12, x0, #1 - msr csselr_el1, x12 /* select cache level */ - isb /* sync change of cssidr_el1 */ - mrs x6, ccsidr_el1 /* read the new cssidr_el1 */ - and x2, x6, #7 /* x2 <- log2(cache line size)-4 */ - add x2, x2, #4 /* x2 <- log2(cache line size) */ - mov x3, #0x3ff - and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */ - clz w5, w3 /* bit position of #ways */ - mov x4, #0x7fff - and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */ - /* x12 <- cache level << 1 */ - /* x2 <- line length offset */ - /* x3 <- number of cache ways - 1 */ - /* x4 <- number of cache sets - 1 */ - /* x5 <- bit position of #ways */ - -loop_set: - mov x6, x3 /* x6 <- working copy of #ways */ -loop_way: - lsl x7, x6, x5 - orr x9, x12, x7 /* map way and level to cisw value */ - lsl x7, x4, x2 - orr x9, x9, x7 /* map set number to cisw value */ - tbz w1, #0, 1f - dc isw, x9 - b 2f -1: dc cisw, x9 /* clean & invalidate by set/way */ -2: subs x6, x6, #1 /* decrement the way */ - b.ge loop_way - subs x4, x4, #1 /* decrement the set */ - b.ge loop_set - - ret - -/* - * void __asm_flush_dcache_all(int invalidate_only) - * - * x0: 0 clean & invalidate, 1 invalidate only - * - * flush or invalidate all data cache by SET/WAY. - */ -.section .warm_crt0.text.__asm_dcache_all, "ax", %progbits -.type __asm_dcache_all, %function -__asm_dcache_all: - mov x1, x0 - dsb sy - mrs x10, clidr_el1 /* read clidr_el1 */ - lsr x11, x10, #24 - and x11, x11, #0x7 /* x11 <- loc */ - cbz x11, finished /* if loc is 0, exit */ - mov x15, lr - mov x0, #0 /* start flush at cache level 0 */ - /* x0 <- cache level */ - /* x10 <- clidr_el1 */ - /* x11 <- loc */ - /* x15 <- return address */ - -loop_level: - lsl x12, x0, #1 - add x12, x12, x0 /* x0 <- tripled cache level */ - lsr x12, x10, x12 - and x12, x12, #7 /* x12 <- cache type */ - cmp x12, #2 - b.lt skip /* skip if no cache or icache */ - bl __asm_dcache_level /* x1 = 0 flush, 1 invalidate */ -skip: - add x0, x0, #1 /* increment cache level */ - cmp x11, x0 - b.gt loop_level - - mov x0, #0 - msr csselr_el1, x0 /* restore csselr_el1 */ - dsb sy - isb - mov lr, x15 - -finished: - ret - -.section .warm_crt0.text.flush_dcache_all, "ax", %progbits -.type flush_dcache_all, %function -.global flush_dcache_all -flush_dcache_all: - mov x0, #0 - b __asm_dcache_all - -.section .warm_crt0.text.invalidate_dcache_all, "ax", %progbits -.type invalidate_dcache_all, %function -.global invalidate_dcache_all -invalidate_dcache_all: - mov x0, #1 - b __asm_dcache_all - -/* - * void __asm_flush_dcache_range(start, end) (renamed -> flush_dcache_range) - * - * clean & invalidate data cache in the range - * - * x0: start address - * x1: end address - */ -.section .warm_crt0.text.flush_dcache_range, "ax", %progbits -.type flush_dcache_range, %function -.global flush_dcache_range -flush_dcache_range: - mrs x3, ctr_el0 - lsr x3, x3, #16 - and x3, x3, #0xf - mov x2, #4 - lsl x2, x2, x3 /* cache line size */ - - /* x2 <- minimal cache line size in cache system */ - sub x3, x2, #1 - bic x0, x0, x3 -1: dc civac, x0 /* clean & invalidate data or unified cache */ - add x0, x0, x2 - cmp x0, x1 - b.lo 1b - dsb sy - ret - -/* - * void __asm_invalidate_dcache_range(start, end) (-> invalidate_dcache_range) - * - * invalidate data cache in the range - * - * x0: start address - * x1: end address - */ -.section .warm_crt0.text.invalidate_dcache_range, "ax", %progbits -.type invalidate_dcache_range, %function -.global invalidate_dcache_range -invalidate_dcache_range: - mrs x3, ctr_el0 - ubfm x3, x3, #16, #19 - mov x2, #4 - lsl x2, x2, x3 /* cache line size */ - - /* x2 <- minimal cache line size in cache system */ - sub x3, x2, #1 - bic x0, x0, x3 -1: dc ivac, x0 /* invalidate data or unified cache */ - add x0, x0, x2 - cmp x0, x1 - b.lo 1b - dsb sy - ret - -/* - * void __asm_invalidate_icache_all(void) (-> invalidate_icache_inner_shareable) - * - * invalidate all icache entries. - */ -.section .warm_crt0.text.invalidate_icache_all_inner_shareable, "ax", %progbits -.type invalidate_icache_all_inner_shareable, %function -.global invalidate_icache_all_inner_shareable -invalidate_icache_all_inner_shareable: - dsb ish - isb - ic ialluis - dsb ish - isb - ret - -.section .warm_crt0.text.invalidate_icache_all, "ax", %progbits -.type invalidate_icache_all, %function -.global invalidate_icache_all -invalidate_icache_all: - dsb ish - isb - ic iallu - dsb ish - isb - ret - -/* Final steps before power down. */ -.section .text.finalize_powerdown, "ax", %progbits -.type finalize_powerdown, %function -.global finalize_powerdown -finalize_powerdown: - /* - Make all data access to Normal memory from EL0/EL1 + all Normal Memory accesses to EL0/1 stage 1 translation tables - non-cacheable for all levels, unified cache. - */ - mrs x0, sctlr_el1 - bic x0, x0, #(1 << 2) - msr sctlr_el1, x0 - isb - - /* Same as above, for EL3. */ - mrs x0, sctlr_el3 - bic x0, x0, #(1 << 2) - msr sctlr_el3, x0 - isb - - /* Disable table walk descriptor access prefetch, disable instruction prefetch, disable data prefetch. */ - mrs x0, cpuectlr_el1 - orr x0, x0, #(1 << 38) - bic x0, x0, #(3 << 35) - bic x0, x0, #(3 << 32) - msr cpuectlr_el1, x0 - isb - dsb sy - bl flush_dcache_all - - /* Disable receiving instruction cache/tbl maintenance operations. */ - mrs x0, cpuectlr_el1 - bic x0, x0, #(1 << 6) - msr cpuectlr_el1, x0 - - /* Prepare GICC */ - bl intr_prepare_gicc_for_sleep - - /* Set OS double lock */ - mrs x0, osdlr_el1 - orr x0, x0, #1 - msr osdlr_el1, x0 - - isb - dsb sy -wait_for_power_off: - wfi - b wait_for_power_off - -/* Call a function with desired stack pointer. */ -.section .text.call_with_stack_pointer, "ax", %progbits -.type call_with_stack_pointer, %function -.global call_with_stack_pointer -call_with_stack_pointer: - mov sp, x0 - br x1 diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c deleted file mode 100644 index 5d3896f9e..000000000 --- a/exosphere/src/bootconfig.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 -#include - -#include "utils.h" -#include "se.h" -#include "configitem.h" -#include "fuse.h" -#include "bootconfig.h" - -static boot_reason_t g_boot_reason = {0}; -static uint64_t g_package2_hash_for_recovery[4] = {0}; - -bool bootconfig_matches_hardware_info(void) { - uint32_t hardware_info[4]; - fuse_get_hardware_info(hardware_info); - return memcmp(LOADED_BOOTCONFIG->signed_config.hardware_info, hardware_info, sizeof(hardware_info)) == 0; -} - -void bootconfig_load_and_verify(const bootconfig_t *bootconfig) { - static const uint8_t bootconfig_modulus[RSA_2048_BYTES] = { - 0xB5, 0x96, 0x87, 0x31, 0x39, 0xAA, 0xBB, 0x3C, 0x28, 0xF3, 0xF0, 0x65, 0xF1, 0x50, 0x70, 0x64, - 0xE6, 0x6C, 0x97, 0x50, 0xCD, 0xA6, 0xEE, 0xEA, 0xC3, 0x8F, 0xE6, 0xB5, 0x81, 0x54, 0x65, 0x33, - 0x1B, 0x88, 0x4B, 0xCE, 0x9F, 0x53, 0xDF, 0xE4, 0xF6, 0xAD, 0xC3, 0x78, 0xD7, 0x3C, 0xD1, 0xDB, - 0x27, 0x21, 0xA0, 0x24, 0x30, 0x2D, 0x98, 0x41, 0xA8, 0xDF, 0x50, 0x7D, 0xAB, 0xCE, 0x00, 0xD9, - 0xCB, 0xAC, 0x8F, 0x37, 0xF5, 0x53, 0xE4, 0x97, 0x1F, 0x13, 0x3C, 0x19, 0xFF, 0x05, 0xA7, 0x3B, - 0xF6, 0xF4, 0x01, 0xDE, 0xF0, 0xC3, 0x77, 0x7B, 0x83, 0xBA, 0xAF, 0x99, 0x30, 0x94, 0x87, 0x25, - 0x4E, 0x54, 0x42, 0x3F, 0xAC, 0x27, 0xF9, 0xCC, 0x87, 0xDD, 0xAE, 0xF2, 0x54, 0xF3, 0x97, 0x49, - 0xF4, 0xB0, 0xF8, 0x6D, 0xDA, 0x60, 0xE0, 0xFD, 0x57, 0xAE, 0x55, 0xA9, 0x76, 0xEA, 0x80, 0x24, - 0xA0, 0x04, 0x7D, 0xBE, 0xD1, 0x81, 0xD3, 0x0C, 0x95, 0xCF, 0xB7, 0xE0, 0x2D, 0x21, 0x21, 0xFF, - 0x97, 0x1E, 0xB3, 0xD7, 0x9F, 0xBB, 0x33, 0x0C, 0x23, 0xC5, 0x88, 0x4A, 0x33, 0xB9, 0xC9, 0x4E, - 0x1E, 0x65, 0x51, 0x45, 0xDE, 0xF9, 0x64, 0x7C, 0xF0, 0xBF, 0x11, 0xB4, 0x93, 0x8D, 0x5D, 0xC6, - 0xAB, 0x37, 0x9E, 0xE9, 0x39, 0xC1, 0xC8, 0xDB, 0xB9, 0xFE, 0x45, 0xCE, 0x7B, 0xDD, 0x72, 0xD9, - 0x6F, 0x68, 0x13, 0xC0, 0x4B, 0xBA, 0x00, 0xF4, 0x1E, 0x89, 0x71, 0x91, 0x26, 0xA6, 0x46, 0x12, - 0xDF, 0x29, 0x6B, 0xC2, 0x5A, 0x53, 0xAF, 0xB9, 0x5B, 0xFD, 0x13, 0x9F, 0xD1, 0x8A, 0x7C, 0xB5, - 0x04, 0xFD, 0x69, 0xEA, 0x23, 0xB4, 0x6D, 0x16, 0x21, 0x98, 0x54, 0xB4, 0xDF, 0xE6, 0xAB, 0x93, - 0x36, 0xB6, 0xD2, 0x43, 0xCF, 0x2B, 0x98, 0x1D, 0x45, 0xC9, 0xBB, 0x20, 0x42, 0xB1, 0x9D, 0x1D - }; - memcpy(LOADED_BOOTCONFIG, bootconfig, sizeof(bootconfig_t)); - /* TODO: Should these restrictions be loosened for Exosphere? */ - if (configitem_is_retail() - || se_rsa2048_pss_verify(LOADED_BOOTCONFIG->signature, RSA_2048_BYTES, bootconfig_modulus, RSA_2048_BYTES, &LOADED_BOOTCONFIG->signed_config, sizeof(LOADED_BOOTCONFIG->signed_config)) != 0 - || !bootconfig_matches_hardware_info()) { - /* Clear signed config. */ - memset(&LOADED_BOOTCONFIG->signed_config, 0, sizeof(LOADED_BOOTCONFIG->signed_config)); - } -} - -void bootconfig_clear(void){ - memset(LOADED_BOOTCONFIG, 0, sizeof(bootconfig_t)); -} - -/* Actual configuration getters. */ -bool bootconfig_is_package2_plaintext(void) { - return (LOADED_BOOTCONFIG->signed_config.package2_config & 1) != 0; -} - -bool bootconfig_is_package2_unsigned(void) { - return (LOADED_BOOTCONFIG->signed_config.package2_config & 2) != 0; -} - -void bootconfig_set_package2_plaintext_and_unsigned(void) { - LOADED_BOOTCONFIG->signed_config.package2_config |= 3; -} - -bool bootconfig_disable_program_verification(void) { - return LOADED_BOOTCONFIG->signed_config.disable_program_verification != 0; -} - -bool bootconfig_is_debug_mode(void) { - return (LOADED_BOOTCONFIG->unsigned_config.data[0x10] & 2) != 0; -} - -bool bootconfig_take_extabt_serror_to_el3(void) { - return (LOADED_BOOTCONFIG->unsigned_config.data[0x10] & 6) != 6; -} - -uint64_t bootconfig_get_value_for_sysctr0(void) { - if (LOADED_BOOTCONFIG->unsigned_config.data[0x24] & 1) { - return *(volatile uint64_t *)(&(LOADED_BOOTCONFIG->unsigned_config.data[0x30])); - } else { - return 0ULL; - } -} - -uint64_t bootconfig_get_memory_arrangement(void) { - /* TODO: This function has changed pretty significantly since we implemented it. */ - /* Not relevant for retail, but we'll probably want this to be accurate sooner or later. */ - if (bootconfig_is_debug_mode()) { - if (fuse_get_dram_id() == 4) { - if (LOADED_BOOTCONFIG->unsigned_config.data[0x23]) { - return (uint64_t)(LOADED_BOOTCONFIG->unsigned_config.data[0x23]); - } else { - return 0x11ull; - } - } else { - if (LOADED_BOOTCONFIG->unsigned_config.data[0x23]) { - if ((LOADED_BOOTCONFIG->unsigned_config.data[0x23] & 0x30) == 0) { - return (uint64_t)(LOADED_BOOTCONFIG->unsigned_config.data[0x23]); - } else { - return 1ull; - } - } else { - return 1ull; - } - } - } else { - return 1ull; - } -} - -uint64_t bootconfig_get_kernel_configuration(void) { - if (bootconfig_is_debug_mode()) { - uint64_t high_val = 0; - if (fuse_get_dram_id() == 4) { - if (LOADED_BOOTCONFIG->unsigned_config.data[0x23]) { - high_val = ((uint64_t)(LOADED_BOOTCONFIG->unsigned_config.data[0x23]) >> 4) & 0x3; - } else { - high_val = 0x1; - } - } - return (high_val << 16) | (((uint64_t)(LOADED_BOOTCONFIG->unsigned_config.data[0x21])) << 8) | ((uint64_t)(LOADED_BOOTCONFIG->unsigned_config.data[0x11])); - } else { - return 0ull; - } -} - -void bootconfig_load_boot_reason(volatile boot_reason_t *boot_reason) { - g_boot_reason = *boot_reason; -} - -void bootconfig_set_package2_hash_for_recovery(const void *package2, size_t package2_size) { - se_calculate_sha256(g_package2_hash_for_recovery, package2, package2_size); -} - -void bootconfig_get_package2_hash_for_recovery(uint64_t *out_hash) { - for (unsigned int i = 0; i < 4; i++) { - out_hash[i] = g_package2_hash_for_recovery[i]; - } -} - -bool bootconfig_is_recovery_boot(void) { - return ((g_boot_reason.bootloader_attribute & 0x01) != 0); -} - -uint64_t bootconfig_get_boot_reason(void) { - return ((uint64_t)g_boot_reason.boot_reason_state << 24) | (g_boot_reason.boot_reason_value & 0xFFFFFF); -} diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h deleted file mode 100644 index 7452a0dfb..000000000 --- a/exosphere/src/bootconfig.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BOOTCONFIG_H -#define EXOSPHERE_BOOTCONFIG_H - -#include -#include -#include "memory_map.h" - -/* This is kind of ConfigItem, but it's stored in BootConfig, so... */ -typedef enum { - KERNELCONFIGFLAG_INITIALIZE_MEMORY_TO_PATTERN = (1 << 0), - KERNELCONFIGFLAG_ENABLE_USER_EXCEPTION_HANDLERS = (1 << 1), - KERNELCONFIGFLAG_ENABLE_USER_PMU_ACCESS = (1 << 2), - KERNELCONFIGFLAG_CALL_SMC_PANIC_ON_KERNEL_ERROR = (1 << 8), -} KernelConfigFlag; - -/* This provides management for Switch BootConfig. */ - -#define LOADED_BOOTCONFIG (get_loaded_bootconfig()) - -typedef struct { - uint8_t data[0x200]; -} bootconfig_unsigned_config_t; - -typedef struct { - uint8_t _0x0[8]; - uint8_t package2_config; - uint8_t _0x9[7]; - uint8_t hardware_info[0x10]; - uint8_t disable_program_verification; - uint8_t _0x21[0xDF]; -} bootconfig_signed_config_t; - -typedef struct { - bootconfig_unsigned_config_t unsigned_config; - uint8_t signature[0x100]; - bootconfig_signed_config_t signed_config; -} bootconfig_t; - -static inline bootconfig_t *get_loaded_bootconfig(void) { - /* this is also get_exception_entry_stack_address(2) */ - return (bootconfig_t *)(TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x180); -} - -typedef struct { - uint32_t bootloader_version; - uint32_t bootloader_start_block; - uint32_t bootloader_start_page; - uint32_t bootloader_attribute; - uint32_t boot_reason_value; - uint32_t boot_reason_state; -} boot_reason_t; - -void bootconfig_load_and_verify(const bootconfig_t *bootconfig); -void bootconfig_clear(void); - -void bootconfig_load_boot_reason(volatile boot_reason_t *boot_reason); - -void bootconfig_set_package2_hash_for_recovery(const void *package2, size_t package2_size); -void bootconfig_get_package2_hash_for_recovery(uint64_t *out_hash); - -/* Actual configuration getters. */ -bool bootconfig_is_package2_plaintext(void); -bool bootconfig_is_package2_unsigned(void); -void bootconfig_set_package2_plaintext_and_unsigned(void); -bool bootconfig_disable_program_verification(void); -bool bootconfig_is_debug_mode(void); - -bool bootconfig_take_extabt_serror_to_el3(void); - -uint64_t bootconfig_get_value_for_sysctr0(void); - -uint64_t bootconfig_get_memory_arrangement(void); -uint64_t bootconfig_get_kernel_configuration(void); - -bool bootconfig_is_recovery_boot(void); -uint64_t bootconfig_get_boot_reason(void); - -#endif diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c deleted file mode 100644 index 47916e315..000000000 --- a/exosphere/src/bootup.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "bootup.h" - -#include "fuse.h" -#include "bpmp.h" -#include "flow.h" -#include "pmc.h" -#include "mc.h" -#include "car.h" -#include "se.h" -#include "masterkey.h" -#include "configitem.h" -#include "timers.h" -#include "misc.h" -#include "uart.h" -#include "bpmp.h" -#include "sysreg.h" -#include "interrupt.h" -#include "cpu_context.h" -#include "actmon.h" -#include "sysctr0.h" -#include "exocfg.h" - -#include "mmu.h" -#include "arm.h" -#include "memory_map.h" -#include "synchronization.h" - -static bool g_has_booted_up = false; - -void setup_dram_magic_numbers(void) { - /* These DRAM writes test and set values for the GPU UCODE carveout. */ - unsigned int target_fw = exosphere_get_target_firmware(); - (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; /* Access test value. */ - flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); - if (ATMOSPHERE_TARGET_FIRMWARE_6_0_0 <= target_fw) { - (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; /* SKU code. */ - (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; - (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; /* Tegra210 code. */ - flush_dcache_range((void *)0x8005FF00, (void *)0x8005FF0C); - } - __dsb_sy(); -} - -void bootup_misc_mmio(void) { - /* Initialize Fuse registers. */ - fuse_init(); - - /* Verify Security Engine sanity. */ - se_set_in_context_save_mode(false); - /* TODO: se_verify_keys_unreadable(); */ - se_validate_stored_vector(); - - for (unsigned int i = 0; i < KEYSLOT_SWITCH_SESSIONKEY; i++) { - clear_aes_keyslot(i); - } - - for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) { - clear_rsa_keyslot(i); - } - se_initialize_rng(KEYSLOT_SWITCH_RNGKEY); - se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY); - se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY); - - if (!g_has_booted_up && (ATMOSPHERE_TARGET_FIRMWARE_6_0_0 > exosphere_get_target_firmware())) { - setup_dram_magic_numbers(); - } - - /* On 9.0.0+, Nintendo writes random values to context save scratch here, and locks the SRK scratch. */ - /* There's no real need for us to do this, so we won't. */ - - /* Mark TMR5, TMR6, TMR7, TMR8, WDT0, WDT1, WDT2 and WDT3 as secure. */ - SHARED_TIMER_SECURE_CFG_0 = 0xF1E0; - - FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 = 4; /* ACTIVE_CLUSTER_LOCK. */ - FLOW_CTLR_FLOW_DBG_QUAL_0 = 0x10000000; /* Enable FIQ2CCPLEX */ - - /* Disable Deep Power Down. */ - APBDEV_PMC_DPD_ENABLE_0 = 0; - - /* Setup MC carveouts. */ - MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; - MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; - MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; - MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; - MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; - MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = 0; - MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = 0; - MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = 1; - MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0; - MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; - MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0; - MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1; - MAKE_MC_REG(MC_SECURITY_CFG0) = 0; - MAKE_MC_REG(MC_SECURITY_CFG1) = 0; - MAKE_MC_REG(MC_SECURITY_CFG3) = 3; - configure_default_carveouts(); - - /* Mark registers secure world only. */ - if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_1_0_0) { - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SATA | APB_SSER0_LA; - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 = APB_SSER1_SPI1 | APB_SSER1_SPI2 | APB_SSER1_SPI3 | APB_SSER1_SPI5 | APB_SSER1_SPI6 | APB_SSER1_I2C4 | APB_SSER1_I2C6; - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = 1 << 4 | 1 << 5 | APB_SSER2_DDS; /* bits 4 and 5 are not labeled in 21.1.7.3 */ - } else { - /* Mark SATA_AUX, DTV, QSPI, SE, SATA, LA secure only. */ - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SE | APB_SSER0_SATA | APB_SSER0_LA; - - /* By default, mark SPI1, SPI2, SPI3, SPI5, SPI6, I2C6 secure only. */ - uint32_t sec_disable_1 = APB_SSER1_SPI1 | APB_SSER1_SPI2 | APB_SSER1_SPI3 | APB_SSER1_SPI5 | APB_SSER1_SPI6 | APB_SSER1_I2C6; - /* By default, mark SDMMC3, DDS, DP2 secure only. */ - uint32_t sec_disable_2 = APB_SSER2_SDMMC3 | APB_SSER2_DDS | APB_SSER2_DP2; - uint64_t hardware_type = configitem_get_hardware_type(); - if (hardware_type != 1) { - /* Also mark I2C4 secure only, */ - sec_disable_1 |= APB_SSER1_I2C4; - } - if (hardware_type != 0 && exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - /* Starting on 4.x on non-dev units, mark UARTB, UARTC, SPI4, I2C3 secure only. */ - sec_disable_1 |= APB_SSER1_UART_B | APB_SSER1_UART_C | APB_SSER1_SPI4 | APB_SSER1_I2C3; - /* Starting on 4.x on non-dev units, mark SDMMC1 secure only. */ - sec_disable_2 |= APB_SSER2_SDMMC1; - } - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 = sec_disable_1; - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = sec_disable_2; - } - - /* Reset Translation Enable registers. */ - MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_0) = 0xFFFFFFFF; - MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_1) = 0xFFFFFFFF; - MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_2) = 0xFFFFFFFF; - MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_3) = 0xFFFFFFFF; - MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF; - - /* Set SMMU ASID security registers. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0xE; - } else { - MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0x0; - } - MAKE_MC_REG(MC_SMMU_ASID_SECURITY_1) = 0; - MAKE_MC_REG(MC_SMMU_ASID_SECURITY_2) = 0; - MAKE_MC_REG(MC_SMMU_ASID_SECURITY_3) = 0; - MAKE_MC_REG(MC_SMMU_ASID_SECURITY_4) = 0; - MAKE_MC_REG(MC_SMMU_ASID_SECURITY_5) = 0; - MAKE_MC_REG(MC_SMMU_ASID_SECURITY_6) = 0; - MAKE_MC_REG(MC_SMMU_ASID_SECURITY_7) = 0; - - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0; - } - MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0; - MAKE_MC_REG(MC_SMMU_TLB_CONFIG) = 0x30000030; - MAKE_MC_REG(MC_SMMU_PTC_CONFIG) = 0x2800003F; - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - MAKE_MC_REG(MC_SMMU_PTC_FLUSH) = 0; - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - MAKE_MC_REG(MC_SMMU_TLB_FLUSH) = 0; - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - MAKE_MC_REG(MC_SMMU_CONFIG) = 1; /* Enable SMMU. */ - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - - /* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */ - uint32_t reset_vec; - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - reset_vec = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); - } else { - reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); - } - EVP_CPU_RESET_VECTOR_0 = 0; - SB_AA64_RESET_LOW_0 = reset_vec | 1; - SB_AA64_RESET_HIGH_0 = 0; - - /* Lock Non-Secure writes to Secure Boot RESET Vector. */ - SB_CSR_0 = 2; - - /* Setup PMC Secure Scratch RESET Vector for warmboot. */ - APBDEV_PMC_SECURE_SCRATCH34_0 = reset_vec; - APBDEV_PMC_SECURE_SCRATCH35_0 = 0; - APBDEV_PMC_SEC_DISABLE3_0 = 0x500000; - - /* Setup FIQs. */ - - /* And assign "se_operation_completed" to Interrupt 0x5A. */ - intr_set_priority(INTERRUPT_ID_SECURITY_ENGINE, 0); - intr_set_group(INTERRUPT_ID_SECURITY_ENGINE, 0); - intr_set_enabled(INTERRUPT_ID_SECURITY_ENGINE, 1); - intr_set_cpu_mask(INTERRUPT_ID_SECURITY_ENGINE, 8); - intr_set_edge_level(INTERRUPT_ID_SECURITY_ENGINE, 0); - - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - intr_set_priority(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); - intr_set_group(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); - intr_set_enabled(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 1); - intr_set_cpu_mask(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 8); - intr_set_edge_level(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); - } - - if (!g_has_booted_up) { - /* N doesn't do this, but we should for compatibility. */ - uart_config(UART_A); - clkrst_reboot(CARDEVICE_UARTA); - uart_init(UART_A, 115200); - - intr_register_handler(INTERRUPT_ID_SECURITY_ENGINE, se_operation_completed); - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - intr_register_handler(INTERRUPT_ID_ACTIVITY_MONITOR_4X, actmon_interrupt_handler); - } - for (unsigned int core = 1; core < NUM_CPU_CORES; core++) { - set_core_is_active(core, false); - } - g_has_booted_up = true; - } else if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - /* Disable AHB redirect. */ - MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; - MAKE_MC_REG(MC_IRAM_TOM) = 0; - MAKE_MC_REG(MC_IRAM_REG_CTRL) |= 1; - CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 &= 0xFFF7FFFF; - } -} - -void setup_4x_mmio(void) { - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - configure_gpu_ucode_carveout(); - } - - /* Disable AHB redirect. */ - MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; - MAKE_MC_REG(MC_IRAM_TOM) = 0; - MAKE_MC_REG(MC_IRAM_REG_CTRL) |= 1; - CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 &= 0xFFF7FFFF; - - /* TODO: What are these PMC scratch writes? */ - APBDEV_PMC_SECURE_SCRATCH51_0 = (APBDEV_PMC_SECURE_SCRATCH51_0 & 0xFFFF8000) | 0x4000; - APBDEV_PMC_SECURE_SCRATCH16_0 &= 0x3FFFFFFF; - APBDEV_PMC_SECURE_SCRATCH55_0 = (APBDEV_PMC_SECURE_SCRATCH55_0 & 0xFF000FFF) | 0x1000; - APBDEV_PMC_SECURE_SCRATCH74_0 = 0x40008000; - APBDEV_PMC_SECURE_SCRATCH75_0 = 0x40000; - APBDEV_PMC_SECURE_SCRATCH76_0 = 0x0; - APBDEV_PMC_SECURE_SCRATCH77_0 = 0x0; - APBDEV_PMC_SECURE_SCRATCH78_0 = 0x0; - APBDEV_PMC_SECURE_SCRATCH99_0 = 0x40008000; - APBDEV_PMC_SECURE_SCRATCH100_0 = 0x40000; - APBDEV_PMC_SECURE_SCRATCH101_0 = 0x0; - APBDEV_PMC_SECURE_SCRATCH102_0 = 0x0; - APBDEV_PMC_SECURE_SCRATCH103_0 = 0x0; - APBDEV_PMC_SECURE_SCRATCH39_0 = (APBDEV_PMC_SECURE_SCRATCH39_0 & 0xF8000000) | 0x88; - - /* TODO: Do we want to bother locking the secure scratch registers? */ - /* 4.x Jamais Vu mitigations. */ - /* Overwrite exception vectors. */ - BPMP_VECTOR_RESET = BPMP_MITIGATION_RESET_VAL; - BPMP_VECTOR_UNDEF = BPMP_MITIGATION_RESET_VAL; - BPMP_VECTOR_SWI = BPMP_MITIGATION_RESET_VAL; - BPMP_VECTOR_PREFETCH_ABORT = BPMP_MITIGATION_RESET_VAL; - BPMP_VECTOR_DATA_ABORT = BPMP_MITIGATION_RESET_VAL; - BPMP_VECTOR_UNK = BPMP_MITIGATION_RESET_VAL; - BPMP_VECTOR_IRQ = BPMP_MITIGATION_RESET_VAL; - BPMP_VECTOR_FIQ = BPMP_MITIGATION_RESET_VAL; - - /* Disable AHB arbitration for the BPMP. */ - AHB_ARBITRATION_DISABLE_0 |= 2; - - /* Set SMMU for BPMP/APB-DMA to point to TZRAM. */ - MAKE_MC_REG(MC_SMMU_PTB_ASID) = 1; - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0x70012; - MAKE_MC_REG(MC_SMMU_AVPC_ASID) = 0x80000001; - MAKE_MC_REG(MC_SMMU_PPCS1_ASID) = 0x80000001; - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - MAKE_MC_REG(MC_SMMU_PTC_FLUSH) = 0; - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - MAKE_MC_REG(MC_SMMU_TLB_FLUSH) = 0; - (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); - - /* Wait for the BPMP to halt. */ - while ((FLOW_CTLR_HALT_COP_EVENTS_0 >> 29) != 2) { - wait(1); - } - - /* If not in a debugging context, setup the activity monitor. */ - if ((get_debug_authentication_status() & 3) != 3) { - FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000; - clkrst_reboot(CARDEVICE_ACTMON); - /* Sample every microsecond. */ - ACTMON_GLB_PERIOD_CTRL_0 = 0x100; - /* Fire interrupt every wakeup. */ - ACTMON_COP_UPPER_WMARK_0 = 0; - /* Cause a panic() on BPMP wakeup. */ - actmon_set_callback(actmon_on_bpmp_wakeup); - /* Enable interrupt when above watermark, periodic sampling. */ - ACTMON_COP_CTRL_0 = 0xC0040000; - } -} - -void setup_current_core_state(void) { - uint64_t temp_reg; - - /* Setup system registers. */ - SET_SYSREG(spsr_el3, 0b1111 << 6 | 0b0101); /* use EL2h+DAIF set initially, may be overwritten later. Not in official code */ - - SET_SYSREG(actlr_el3, 0x73ull); - SET_SYSREG(actlr_el2, 0x73ull); - SET_SYSREG(hcr_el2, 0x80000000ull); - SET_SYSREG(dacr32_el2, 0xFFFFFFFFull); - SET_SYSREG(sctlr_el1, 0xC50838ull); - SET_SYSREG(sctlr_el2, 0x30C50838ull); - - __isb(); - - SET_SYSREG(cntfrq_el0, SYSCTR0_CNTFID0_0); - SET_SYSREG(cnthctl_el2, 3ull); - - __isb(); - - /* Setup Interrupts, flow. */ - flow_clear_csr0_and_events(get_core_id()); - intr_initialize_gic(); - intr_set_priority(INTERRUPT_ID_1C, 0); - intr_set_group(INTERRUPT_ID_1C, 0); - intr_set_enabled(INTERRUPT_ID_1C, 1); - - /* Restore current core context. */ - restore_current_core_context(); -} - -void identity_unmap_iram_cd_tzram(void) { - /* See also: configure_ttbls (in coldboot_init.c). */ - /*uintptr_t *mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - uintptr_t *mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE);*/ - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - - mmu_unmap_range(3, mmu_l3_tbl, IDENTITY_GET_MAPPING_ADDRESS(IDENTITY_MAPPING_IRAM_A_CCRT0), IDENTITY_GET_MAPPING_SIZE(IDENTITY_MAPPING_IRAM_A_CCRT0)); - mmu_unmap_range(3, mmu_l3_tbl, IDENTITY_GET_MAPPING_ADDRESS(IDENTITY_MAPPING_IRAM_CD), IDENTITY_GET_MAPPING_SIZE(IDENTITY_MAPPING_IRAM_CD)); - /*mmu_unmap_range(3, mmu_l3_tbl, IDENTITY_GET_MAPPING_ADDRESS(IDENTITY_MAPPING_TZRAM), IDENTITY_GET_MAPPING_SIZE(IDENTITY_MAPPING_TZRAM)); - - mmu_unmap(2, mmu_l2_tbl, 0x40000000); - mmu_unmap(2, mmu_l2_tbl, 0x7C000000); - - mmu_unmap(1, mmu_l1_tbl, 0x40000000);*/ - - tlb_invalidate_all_inner_shareable(); -} - -void secure_additional_devices(void) { - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 |= APB_SSER0_PMC; /* make PMC secure-only (2.x+) */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 |= APB_SSER1_MC0 | APB_SSER1_MC1 | APB_SSER1_MCB; /* make MC0, MC1, MCB secure-only (4.x+) */ - } - } -} - -void set_extabt_serror_taken_to_el3(bool taken_to_el3) { - uint64_t temp_scr_el3; - __asm__ __volatile__ ("mrs %0, scr_el3" : "=r"(temp_scr_el3) :: "memory"); - - temp_scr_el3 &= 0xFFFFFFF7; - temp_scr_el3 |= taken_to_el3 ? 8 : 0; - - __asm__ __volatile__ ("msr scr_el3, %0" :: "r"(temp_scr_el3) : "memory"); - __isb(); -} diff --git a/exosphere/src/bootup.h b/exosphere/src/bootup.h deleted file mode 100644 index ba8a20d20..000000000 --- a/exosphere/src/bootup.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BOOTUP_H -#define EXOSPHERE_BOOTUP_H - -#include - -/* 21.1.7 AP Control Registers */ -/* 21.1.7.1 APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 slaves */ -typedef enum { - APB_SSER0_MISC_REGS = 1 << 1, /* PP, SC1x pads and GP registers */ - APB_SSER0_SATA_AUX = 1 << 2, - APB_SSER0_PINMUX_AUX = 1 << 3, - APB_SSER0_APE = 1 << 4, - - APB_SSER0_DTV = 1 << 6, - - APB_SSER0_PWM = 1 << 8, /* PWFM */ - APB_SSER0_QSPI = 1 << 9, - APB_SSER0_CSITE = 1 << 10, /* Core Site */ - APB_SSER0_RTC = 1 << 11, - - APB_SSER0_PMC = 1 << 13, - APB_SSER0_SE = 1 << 14, /* Security Engine */ - APB_SSER0_FUSE = 1 << 15, - APB_SSER0_KFUSE = 1 << 16, - - APB_SSER0_UNUSED = 1 << 18, /* reserved, unused but listed as accessible */ - - APB_SSER0_SATA = 1 << 20, - APB_SSER0_HDA = 1 << 21, - APB_SSER0_LA = 1 << 22, - APB_SSER0_ATOMICS = 1 << 23, - APB_SSER0_CEC = 1 << 24, - - STM = 1 << 29 -} APB_SSER0; - -/* 21.1.7.2 APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 slaves */ -typedef enum { - APB_SSER1_MC0 = 1 << 4, - APB_SSER1_EMC0 = 1 << 5, - - APB_SSER1_MC1 = 1 << 8, - APB_SSER1_EMC1 = 1 << 9, - APB_SSER1_MCB = 1 << 10, - APB_SSER1_EMBC = 1 << 11, - APB_SSER1_UART_A = 1 << 12, - APB_SSER1_UART_B = 1 << 13, - APB_SSER1_UART_C = 1 << 14, - APB_SSER1_UART_D = 1 << 15, - - APB_SSER1_SPI1 = 1 << 20, - APB_SSER1_SPI2 = 1 << 21, - APB_SSER1_SPI3 = 1 << 22, - APB_SSER1_SPI4 = 1 << 23, - APB_SSER1_SPI5 = 1 << 24, - APB_SSER1_SPI6 = 1 << 25, - APB_SSER1_I2C1 = 1 << 26, - APB_SSER1_I2C2 = 1 << 27, - APB_SSER1_I2C3 = 1 << 28, - APB_SSER1_I2C4 = 1 << 29, - APB_SSER1_DVC = 1 << 30, - APB_SSER1_I2C5 = 1 << 30, - APB_SSER1_I2C6 = 1 << 31 /* this will show as negative because of the 32bit sign bit being set */ -} APB_SSER1; - -/* 21.1.7.3 APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 slaves */ -typedef enum { - APB_SSER2_SDMMC1 = 1 << 0, - APB_SSER2_SDMMC2 = 1 << 1, - APB_SSER2_SDMMC3 = 1 << 2, - APB_SSER2_SDMMC4 = 1 << 3, - - APB_SSER2_MIPIBIF = 1 << 7, /* reserved */ - APB_SSER2_DDS = 1 << 8, - APB_SSER2_DP2 = 1 << 9, - APB_SSER2_SOC_THERM = 1 << 10, - APB_SSER2_APB2JTAG = 1 << 11, - APB_SSER2_XUSB_HOST = 1 << 12, - APB_SSER2_XUSB_DEV = 1 << 13, - APB_SSER2_XUSB_PADCTL = 1 << 14, - APB_SSER2_MIPI_CAL = 1 << 15, - APB_SSER2_DVFS = 1 << 16 -} APB_SSER2; - -void bootup_misc_mmio(void); - -void setup_4x_mmio(void); - -void setup_dram_magic_numbers(void); - -void setup_current_core_state(void); - -void identity_unmap_iram_cd_tzram(void); - -void secure_additional_devices(void); - -void set_extabt_serror_taken_to_el3(bool taken_to_el3); - -#endif diff --git a/exosphere/src/bpmp.h b/exosphere/src/bpmp.h deleted file mode 100644 index 5222c8a18..000000000 --- a/exosphere/src/bpmp.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_BPMP_H -#define EXOSPHERE_BPMP_H - -#include -#include "memory_map.h" - -/* Exosphere register definitions for the Tegra X1 BPMP vectors. */ - -static inline uintptr_t get_bpmp_vector_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_EXCEPTION_VECTORS); -} - -#define BPMP_VECTOR_BASE (get_bpmp_vector_base()) - -#define EVP_CPU_RESET_VECTOR_0 MAKE_REG32(BPMP_VECTOR_BASE + 0x100) - -#define BPMP_VECTOR_RESET MAKE_REG32(BPMP_VECTOR_BASE + 0x200) -#define BPMP_VECTOR_UNDEF MAKE_REG32(BPMP_VECTOR_BASE + 0x204) -#define BPMP_VECTOR_SWI MAKE_REG32(BPMP_VECTOR_BASE + 0x208) -#define BPMP_VECTOR_PREFETCH_ABORT MAKE_REG32(BPMP_VECTOR_BASE + 0x20C) -#define BPMP_VECTOR_DATA_ABORT MAKE_REG32(BPMP_VECTOR_BASE + 0x210) -#define BPMP_VECTOR_UNK MAKE_REG32(BPMP_VECTOR_BASE + 0x214) -#define BPMP_VECTOR_IRQ MAKE_REG32(BPMP_VECTOR_BASE + 0x218) -#define BPMP_VECTOR_FIQ MAKE_REG32(BPMP_VECTOR_BASE + 0x21C) - -#define BPMP_MITIGATION_RESET_VAL 0x7D000000 - -#endif diff --git a/exosphere/src/car.c b/exosphere/src/car.c deleted file mode 100644 index bc4bb47b0..000000000 --- a/exosphere/src/car.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 "utils.h" -#include "car.h" -#include "timers.h" - -static inline uint32_t get_special_clk_reg(CarDevice dev) { - switch (dev) { - case CARDEVICE_UARTA: return 0x178; - case CARDEVICE_UARTB: return 0x17C; - case CARDEVICE_I2C1: return 0x124; - case CARDEVICE_I2C5: return 0x128; - case CARDEVICE_ACTMON: return 0x3E8; - case CARDEVICE_BPMP: return 0; - default: generic_panic(); - } -} - -static inline uint32_t get_special_clk_val(CarDevice dev) { - switch (dev) { - case CARDEVICE_UARTA: return 0; - case CARDEVICE_UARTB: return 0; - case CARDEVICE_I2C1: return (6 << 29); - case CARDEVICE_I2C5: return (6 << 29); - case CARDEVICE_ACTMON: return (6 << 29); - case CARDEVICE_BPMP: return 0; - default: generic_panic(); - } -} - -static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; -static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; - -void clk_enable(CarDevice dev) { - uint32_t special_reg; - if ((special_reg = get_special_clk_reg(dev))) { - MAKE_CAR_REG(special_reg) = get_special_clk_val(dev); - } - MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); -} - -void clk_disable(CarDevice dev) { - MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); -} - -void rst_enable(CarDevice dev) { - MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); -} - -void rst_disable(CarDevice dev) { - MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); -} - -void clkrst_enable(CarDevice dev) { - clk_enable(dev); - rst_disable(dev); -} - -void clkrst_disable(CarDevice dev) { - rst_enable(dev); - clk_disable(dev); -} - -void clkrst_reboot(CarDevice dev) { - clkrst_disable(dev); - clkrst_enable(dev); -} - -void clkrst_enable_fuse_regs(bool enable) { - CLK_RST_CONTROLLER_MISC_CLK_ENB_0 = ((CLK_RST_CONTROLLER_MISC_CLK_ENB_0 & 0xEFFFFFFF) | ((enable & 1) << 28)); -} \ No newline at end of file diff --git a/exosphere/src/car.h b/exosphere/src/car.h deleted file mode 100644 index dad0e61ed..000000000 --- a/exosphere/src/car.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_CLOCK_AND_RESET_H -#define EXOSPHERE_CLOCK_AND_RESET_H - -#include - -#include "memory_map.h" - -/* Exosphere Driver for the Tegra X1 Clock and Reset registers. */ - -#define CAR_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_CLKRST)) - -#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) - -#define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048) -#define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) - -#define NUM_CAR_BANKS 7 - -typedef enum { - CARDEVICE_UARTA = 6, - CARDEVICE_UARTB = 7, - CARDEVICE_I2C1 = 12, - CARDEVICE_I2C5 = 47, - CARDEVICE_ACTMON = 119, - CARDEVICE_BPMP = 1 -} CarDevice; - -void clk_enable(CarDevice dev); -void clk_disable(CarDevice dev); -void rst_enable(CarDevice dev); -void rst_disable(CarDevice dev); - -void clkrst_enable(CarDevice dev); -void clkrst_disable(CarDevice dev); -void clkrst_reboot(CarDevice dev); - -void clkrst_enable_fuse_regs(bool enable); - -#endif diff --git a/exosphere/src/coldboot_init.c b/exosphere/src/coldboot_init.c deleted file mode 100644 index 19f0576fb..000000000 --- a/exosphere/src/coldboot_init.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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 "utils.h" -#include "arm.h" -#include "mmu.h" -#include "memory_map.h" -#include "arm.h" -#include "package2.h" -#include "timers.h" -#include "exocfg.h" - -#undef MAILBOX_NX_BOOTLOADER_BASE -#undef TIMERS_BASE -#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? (MMIO_GET_DEVICE_7X_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) : (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) -#define TIMERS_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_TMRs_WDTs)) - -extern const uint8_t __start_cold[]; - -/* warboot_init.c */ -extern unsigned int g_exosphere_target_firmware_for_init; -void init_dma_controllers(unsigned int target_firmware); -void set_memory_registers_enable_mmu_1x_ttbr0(void); -void set_memory_registers_enable_mmu_5x_ttbr0(void); - -static void identity_map_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_tbl) { - static const uintptr_t addrs[] = { TUPLE_FOLD_LEFT_0(EVAL(IDENTIY_MAPPING_ID_MAX), _MMAPID, COMMA) }; - static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(IDENTIY_MAPPING_ID_MAX), _MMAPID, COMMA) }; - static const uint64_t attribs[] = { TUPLE_FOLD_LEFT_2(EVAL(IDENTIY_MAPPING_ID_MAX), _MMAPID, COMMA) }; - static const uint64_t is_block[] = { TUPLE_FOLD_LEFT_3(EVAL(IDENTIY_MAPPING_ID_MAX), _MMAPID, COMMA) }; - - for(size_t i = 0; i < IDENTIY_MAPPING_ID_MAX; i++) { - identity_map_mapping(mmu_l1_tbl, mmu_l3_tbl, addrs[i], sizes[i], attribs[i], is_block[i]); - } -} - -static void mmio_map_all_devices(uintptr_t *mmu_l3_tbl, unsigned int target_firmware) { - static const uintptr_t pas[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; - static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; - static const bool is_secure[] = { TUPLE_FOLD_LEFT_2(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; - - static const uintptr_t pas_7x[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV7X, COMMA) }; - - for(size_t i = 0, offset = 0; i < MMIO_DEVID_MAX; i++) { - uintptr_t pa = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? pas[i] : pas_7x[i]; - mmio_map_device(mmu_l3_tbl, MMIO_BASE + offset, pa, sizes[i], is_secure[i]); - offset += sizes[i]; - offset += 0x1000; - } -} - -static void lp0_entry_map_all_ram_segments(uintptr_t *mmu_l3_tbl) { - static const uintptr_t pas[] = { TUPLE_FOLD_LEFT_0(EVAL(LP0_ENTRY_RAM_SEGMENT_ID_MAX), _MMAPLP0ES, COMMA) }; - static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(LP0_ENTRY_RAM_SEGMENT_ID_MAX), _MMAPLP0ES, COMMA) }; - static const uint64_t attribs[] = { TUPLE_FOLD_LEFT_2(EVAL(LP0_ENTRY_RAM_SEGMENT_ID_MAX), _MMAPLP0ES, COMMA) }; - - for(size_t i = 0, offset = 0; i < LP0_ENTRY_RAM_SEGMENT_ID_MAX; i++) { - lp0_entry_map_ram_segment(mmu_l3_tbl, LP0_ENTRY_RAM_SEGMENT_BASE + offset, pas[i], sizes[i], attribs[i]); - offset += 0x10000; - } -} - -static void warmboot_map_all_ram_segments(uintptr_t *mmu_l3_tbl) { - static const uintptr_t pas[] = { TUPLE_FOLD_LEFT_0(EVAL(WARMBOOT_RAM_SEGMENT_ID_MAX), _MMAPWBS, COMMA) }; - static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(WARMBOOT_RAM_SEGMENT_ID_MAX), _MMAPWBS, COMMA) }; - static const uint64_t attribs[] = { TUPLE_FOLD_LEFT_2(EVAL(WARMBOOT_RAM_SEGMENT_ID_MAX), _MMAPWBS, COMMA) }; - - for(size_t i = 0, offset = 0; i < WARMBOOT_RAM_SEGMENT_ID_MAX; i++) { - warmboot_map_ram_segment(mmu_l3_tbl, WARMBOOT_RAM_SEGMENT_BASE + offset, pas[i], sizes[i], attribs[i]); - offset += sizes[i]; - } -} - -static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl, unsigned int target_firmware) { - static const uintptr_t offs[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; - static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; - static const size_t increments[] = { TUPLE_FOLD_LEFT_2(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; - static const bool is_executable[] = { TUPLE_FOLD_LEFT_3(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; - - static const uintptr_t offs_5x[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZ5XS, COMMA) }; - - for(size_t i = 0, offset = 0; i < TZRAM_SEGMENT_ID_MAX; i++) { - uintptr_t off = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) ? offs[i] : offs_5x[i]; - tzram_map_segment(mmu_l3_tbl, TZRAM_SEGMENT_BASE + offset, 0x7C010000ull + off, sizes[i], is_executable[i]); - offset += increments[i]; - } -} - -static void configure_ttbls(unsigned int target_firmware) { - uintptr_t *mmu_l1_tbl; - uintptr_t *mmu_l2_tbl; - uintptr_t *mmu_l3_tbl; - if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); - mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - } else { - mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); - mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - } - - mmu_init_table(mmu_l1_tbl, 64); /* 33-bit address space */ - mmu_init_table(mmu_l2_tbl, 4096); - /* - Nintendo uses the same L3 table for everything, but they make sure - nothing clashes. - */ - mmu_init_table(mmu_l3_tbl, 4096); - - mmu_map_table(1, mmu_l1_tbl, 0x40000000, mmu_l2_tbl, 0); - mmu_map_table(1, mmu_l1_tbl, 0x1C0000000, mmu_l2_tbl, 0); - - mmu_map_table(2, mmu_l2_tbl, 0x40000000, mmu_l3_tbl, 0); - mmu_map_table(2, mmu_l2_tbl, 0x7C000000, mmu_l3_tbl, 0); - mmu_map_table(2, mmu_l2_tbl, 0x1F0000000ull, mmu_l3_tbl, 0); - - identity_map_all_mappings(mmu_l1_tbl, mmu_l3_tbl); - mmio_map_all_devices(mmu_l3_tbl, target_firmware); - lp0_entry_map_all_ram_segments(mmu_l3_tbl); - warmboot_map_all_ram_segments(mmu_l3_tbl); - tzram_map_all_segments(mmu_l3_tbl, target_firmware); -} - -static void do_relocation(const coldboot_crt0_reloc_list_t *reloc_list, size_t index) { - extern const uint8_t __glob_origin__[]; - uint64_t *p_vma = (uint64_t *)reloc_list->relocs[index].vma; - bool is_clear = reloc_list->relocs[index].lma == 0; - size_t offset = reloc_list->relocs[index].lma - (uintptr_t)__glob_origin__; - const uint64_t *p_lma = (const uint64_t *)(reloc_list->reloc_base + offset); - size_t size = reloc_list->relocs[index].end_vma - reloc_list->relocs[index].vma; - - for(size_t i = 0; i < size / 8; i++) { - p_vma[i] = is_clear ? 0 : p_lma[i]; - } -} - -uintptr_t get_coldboot_crt0_temp_stack_address(void) { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; -} - -uintptr_t get_coldboot_crt0_stack_address(void) { - if (exosphere_get_target_firmware_for_init() < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; - } else { - return TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; - } - -} - -void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold) { - //MAILBOX_NX_SECMON_BOOT_TIME = TIMERUS_CNTR_1US_0; - - /* Custom approach */ - reloc_list->reloc_base = start_cold; - - /* TODO: Set NX BOOTLOADER clock time field */ - - /* This at least copies .warm_crt0 to its VMA. */ - for(size_t i = 0; i < reloc_list->nb_relocs_pre_mmu_init; i++) { - do_relocation(reloc_list, i); - } - /* At this point, we can (and will) access functions located in .warm_crt0 */ - - /* - From https://events.static.linuxfound.org/sites/events/files/slides/slides_17.pdf : - Caches may write back dirty lines at any time: - - To make space for new allocations - - Even if MMU is off - - Even if Cacheable accesses are disabled (caches are never 'off') - - It should be fine to clear that here and not before. - */ - flush_dcache_all(); - invalidate_icache_all(); - - /* Set target firmware. */ - g_exosphere_target_firmware_for_init = exosphere_get_target_firmware_for_init(); - - /* Initialize DMA controllers, and write to AHB_GIZMO_TZRAM. */ - /* TZRAM accesses should work normally after this point. */ - init_dma_controllers(g_exosphere_target_firmware_for_init); - - configure_ttbls(g_exosphere_target_firmware_for_init); - if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - set_memory_registers_enable_mmu_1x_ttbr0(); - } else { - set_memory_registers_enable_mmu_5x_ttbr0(); - } - - /* Copy or clear the remaining sections */ - for(size_t i = 0; i < reloc_list->nb_relocs_post_mmu_init; i++) { - do_relocation(reloc_list, reloc_list->nb_relocs_pre_mmu_init + i); - } - - flush_dcache_all(); - invalidate_icache_all(); - /* At this point we can access all the mapped segments (all other functions, data...) normally */ -} diff --git a/exosphere/src/coldboot_main.c b/exosphere/src/coldboot_main.c deleted file mode 100644 index 0b0fb76c5..000000000 --- a/exosphere/src/coldboot_main.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 "utils.h" -#include "mmu.h" -#include "memory_map.h" -#include "arm.h" -#include "cpu_context.h" - -extern uint8_t __pk2ldr_start__[], __pk2ldr_end__[]; - -void coldboot_main(void) { - uintptr_t *mmu_l3_table = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - uintptr_t pk2ldr = TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_PK2LDR); - - /* Clear and unmap pk2ldr (which is reused as exception entry stacks) */ - memset((void *)pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__); - mmu_unmap_range(3, mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__); - tlb_invalidate_all_inner_shareable(); - - core_jump_to_lower_el(); -} diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c deleted file mode 100644 index a69de35b0..000000000 --- a/exosphere/src/configitem.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * 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 - -#include "bootconfig.h" -#include "configitem.h" -#include "interrupt.h" -#include "package2.h" -#include "se.h" -#include "fuse.h" -#include "utils.h" -#include "masterkey.h" -#include "exocfg.h" -#include "smc_ams.h" -#include "arm.h" - -#define u8 uint8_t -#define u32 uint32_t -#include "rebootstub_bin.h" -#undef u8 -#undef u32 - -static bool g_hiz_mode_enabled = false; -static bool g_debugmode_override_user = false, g_debugmode_override_priv = false; -static bool g_enable_usermode_exception_handlers = true; -static bool g_enable_usermode_pmu_access = false; - -uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { - switch (item) { - case CONFIGITEM_HIZMODE: - g_hiz_mode_enabled = (value != 0); - break; - case CONFIGITEM_NEEDS_REBOOT: - /* Force a reboot, if requested. */ - { - switch (value) { - case REBOOT_KIND_NO_REBOOT: - return 0; - case REBOOT_KIND_TO_RCM: - /* Set reboot kind = rcm. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; - break; - case REBOOT_KIND_TO_WB_PAYLOAD: - /* Set reboot kind = warmboot. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; - /* Patch SDRAM init to perform an SVC immediately after second write */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x2E38DFFF; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x6001DC28; - /* Set SVC handler to jump to reboot stub in IRAM. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x520ull) = 0x4003F000; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x53Cull) = 0x6000F208; - - /* Copy reboot stub payload. */ - ams_map_irampage(0x4003F000); - for (unsigned int i = 0; i < rebootstub_bin_size; i += 4) { - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i); - } - ams_unmap_irampage(); - - /* Ensure stub is flushed. */ - flush_dcache_all(); - break; - default: - return 2; - } - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; - while (1) { } - } - break; - case CONFIGITEM_NEEDS_SHUTDOWN: - /* Force a shutdown, if requested. */ - { - if (value == 0) { - return 0; - } - /* Set reboot kind = warmboot. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; - /* Patch SDRAM init to perform an SVC immediately after second write */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x2E38DFFF; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x6001DC28; - /* Set SVC handler to jump to reboot stub in IRAM. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x520ull) = 0x4003F000; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x53Cull) = 0x6000F208; - - /* Copy reboot stub payload. */ - ams_map_irampage(0x4003F000); - for (unsigned int i = 0; i < rebootstub_bin_size; i += 4) { - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i); - } - /* Tell rebootstub to shut down. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + 0x10) = 0x0; - ams_unmap_irampage(); - - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; - while (1) { } - } - break; - default: - return 2; - } - - return 0; -} - -bool configitem_is_recovery_boot(void) { - uint64_t is_recovery_boot; - if (configitem_get(true, CONFIGITEM_ISRECOVERYBOOT, &is_recovery_boot) != 0) { - generic_panic(); - } - - return is_recovery_boot != 0; -} - -bool configitem_is_retail(void) { - uint64_t is_retail; - if (configitem_get(true, CONFIGITEM_ISRETAIL, &is_retail) != 0) { - generic_panic(); - } - - return is_retail != 0; -} - -bool configitem_is_hiz_mode_enabled(void) { - return g_hiz_mode_enabled; -} - -void configitem_set_hiz_mode_enabled(bool enabled) { - g_hiz_mode_enabled = enabled; -} - -bool configitem_is_debugmode_priv(void) { - uint64_t debugmode = 0; - if (configitem_get(true, CONFIGITEM_ISDEBUGMODE, &debugmode) != 0) { - generic_panic(); - } - - return debugmode != 0; -} - -uint64_t configitem_get_hardware_type(void) { - uint64_t hardware_type; - if (configitem_get(true, CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) { - generic_panic(); - } - return hardware_type; -} - -void configitem_set_debugmode_override(bool user, bool priv) { - g_debugmode_override_user = user; - g_debugmode_override_priv = priv; -} - -void configitem_disable_usermode_exception_handlers(void) { - g_enable_usermode_exception_handlers = false; -} - -void configitem_enable_usermode_pmu_access(void) { - g_enable_usermode_pmu_access = true; -} - -uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) { - uint32_t result = 0; - switch (item) { - case CONFIGITEM_DISABLEPROGRAMVERIFICATION: - *p_outvalue = (int)(bootconfig_disable_program_verification()); - break; - case CONFIGITEM_DRAMID: - *p_outvalue = fuse_get_dram_id(); - break; - case CONFIGITEM_SECURITYENGINEIRQ: - /* SE is interrupt #0x2C. */ - *p_outvalue = INTERRUPT_ID_USER_SECURITY_ENGINE; - break; - case CONFIGITEM_VERSION: - *p_outvalue = fuse_get_expected_fuse_version(exosphere_get_target_firmware()); - break; - case CONFIGITEM_HARDWARETYPE: - *p_outvalue = fuse_get_hardware_type(exosphere_get_target_firmware()); - break; - case CONFIGITEM_ISRETAIL: - *p_outvalue = fuse_get_retail_type(); - break; - case CONFIGITEM_ISRECOVERYBOOT: - *p_outvalue = (int)(bootconfig_is_recovery_boot()); - break; - case CONFIGITEM_DEVICEID: - *p_outvalue = fuse_get_device_id(); - break; - case CONFIGITEM_BOOTREASON: - /* For some reason, Nintendo removed it on 4.0 */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - *p_outvalue = bootconfig_get_boot_reason(); - } else { - result = 2; - } - break; - case CONFIGITEM_MEMORYARRANGE: - *p_outvalue = bootconfig_get_memory_arrangement(); - break; - case CONFIGITEM_ISDEBUGMODE: - if ((privileged && g_debugmode_override_priv) || (!privileged && g_debugmode_override_user)) { - *p_outvalue = 1; - } else { - *p_outvalue = (int)(bootconfig_is_debug_mode()); - } - break; - case CONFIGITEM_KERNELCONFIGURATION: - { - uint64_t config = bootconfig_get_kernel_configuration(); - /* Enable usermode exception handlers by default. */ - if (g_enable_usermode_exception_handlers) { - config |= KERNELCONFIGFLAG_ENABLE_USER_EXCEPTION_HANDLERS; - } - /* Allow for enabling usermode pmu access. */ - if (g_enable_usermode_pmu_access) { - config |= KERNELCONFIGFLAG_ENABLE_USER_PMU_ACCESS; - } - *p_outvalue = config; - } - break; - case CONFIGITEM_HIZMODE: - *p_outvalue = (int)g_hiz_mode_enabled; - break; - case CONFIGITEM_ISQUESTUNIT: - /* Added on 3.0, used to determine whether console is a kiosk unit. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { - *p_outvalue = (fuse_get_reserved_odm(4) >> 10) & 1; - } else { - result = 2; - } - break; - case CONFIGITEM_NEWHARDWARETYPE_5X: - /* Added in 5.x, currently hardcoded to 0. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - *p_outvalue = 0; - } else { - result = 2; - } - break; - case CONFIGITEM_NEWKEYGENERATION_5X: - /* Added in 5.x. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - *p_outvalue = fuse_get_5x_key_generation(); - } else { - result = 2; - } - break; - case CONFIGITEM_PACKAGE2HASH_5X: - /* Added in 5.x. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0 && bootconfig_is_recovery_boot()) { - bootconfig_get_package2_hash_for_recovery(p_outvalue); - } else { - result = 2; - } - break; - case CONFIGITEM_EXOSPHERE_VERSION: - /* UNOFFICIAL: Gets information about the current exosphere version. */ - *p_outvalue = ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MAJOR & 0xFF) << 56ull) | - ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MINOR & 0xFF) << 48ull) | - ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MICRO & 0xFF) << 40ull) | - ((uint64_t)(mkey_get_revision() & 0xFF) << 32ull) | - ((uint64_t)(exosphere_get_target_firmware()) << 0ull); - break; - case CONFIGITEM_NEEDS_REBOOT: - /* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting. */ - *p_outvalue = 0; - break; - case CONFIGITEM_NEEDS_SHUTDOWN: - /* UNOFFICIAL: The fact that we are executing means we aren't in the process of shutting down. */ - *p_outvalue = 0; - break; - case CONFIGITEM_EXOSPHERE_VERHASH: - /* UNOFFICIAL: Gets information about the current exosphere git commit hash. */ - *p_outvalue = ATMOSPHERE_RELEASE_VERSION_HASH; - break; - case CONFIGITEM_HAS_RCM_BUG_PATCH: - /* UNOFFICIAL: Gets whether this unit has the RCM bug patched. */ - *p_outvalue = (int)(fuse_has_rcm_bug_patch()); - break; - case CONFIGITEM_SHOULD_BLANK_PRODINFO: - /* UNOFFICIAL: Gets whether this unit should simulate a "blanked" PRODINFO. */ - *p_outvalue = exosphere_should_blank_prodinfo(); - break; - case CONFIGITEM_ALLOW_CAL_WRITES: - /* UNOFFICIAL: Gets whether this unit should allow writing to the calibration partition. */ - *p_outvalue = exosphere_should_allow_writing_to_cal(); - break; - default: - result = 2; - break; - } - return result; -} diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h deleted file mode 100644 index 103b07c15..000000000 --- a/exosphere/src/configitem.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_CFG_ITEM_H -#define EXOSPHERE_CFG_ITEM_H - -#include -#include - -typedef enum { - CONFIGITEM_DISABLEPROGRAMVERIFICATION = 1, - CONFIGITEM_DRAMID = 2, - CONFIGITEM_SECURITYENGINEIRQ = 3, - CONFIGITEM_VERSION = 4, - CONFIGITEM_HARDWARETYPE = 5, - CONFIGITEM_ISRETAIL = 6, - CONFIGITEM_ISRECOVERYBOOT = 7, - CONFIGITEM_DEVICEID = 8, - CONFIGITEM_BOOTREASON = 9, - CONFIGITEM_MEMORYARRANGE = 10, - CONFIGITEM_ISDEBUGMODE = 11, - CONFIGITEM_KERNELCONFIGURATION = 12, - CONFIGITEM_HIZMODE = 13, - CONFIGITEM_ISQUESTUNIT = 14, - CONFIGITEM_NEWHARDWARETYPE_5X = 15, - CONFIGITEM_NEWKEYGENERATION_5X = 16, - CONFIGITEM_PACKAGE2HASH_5X = 17, - - /* These are unofficial, for usage by Exosphere. */ - CONFIGITEM_EXOSPHERE_VERSION = 65000, - CONFIGITEM_NEEDS_REBOOT = 65001, - CONFIGITEM_NEEDS_SHUTDOWN = 65002, - CONFIGITEM_EXOSPHERE_VERHASH = 65003, - CONFIGITEM_HAS_RCM_BUG_PATCH = 65004, - CONFIGITEM_SHOULD_BLANK_PRODINFO = 65005, - CONFIGITEM_ALLOW_CAL_WRITES = 65006, -} ConfigItem; - -#define REBOOT_KIND_NO_REBOOT 0 -#define REBOOT_KIND_TO_RCM 1 -#define REBOOT_KIND_TO_WB_PAYLOAD 2 - -uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value); -uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue); - -bool configitem_is_recovery_boot(void); -bool configitem_is_retail(void); -bool configitem_is_hiz_mode_enabled(void); -bool configitem_is_debugmode_priv(void); - -void configitem_set_debugmode_override(bool user, bool priv); -void configitem_disable_usermode_exception_handlers(void); -void configitem_enable_usermode_pmu_access(void); -void configitem_set_hiz_mode_enabled(bool enabled); - -uint64_t configitem_get_hardware_type(void); - -#endif diff --git a/exosphere/src/cpu_context.c b/exosphere/src/cpu_context.c deleted file mode 100644 index 914467194..000000000 --- a/exosphere/src/cpu_context.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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 -#include "arm.h" -#include "cpu_context.h" -#include "car.h" -#include "exocfg.h" -#include "flow.h" -#include "pmc.h" -#include "timers.h" -#include "smc_api.h" -#include "utils.h" -#include "synchronization.h" -#include "preprocessor.h" - -#define SAVE_SYSREG64(reg) do { __asm__ __volatile__ ("mrs %0, " #reg : "=r"(temp_reg) :: "memory"); g_cpu_contexts[current_core].reg = temp_reg; } while(false) -#define SAVE_SYSREG32(reg) do { __asm__ __volatile__ ("mrs %0, " #reg : "=r"(temp_reg) :: "memory"); g_cpu_contexts[current_core].reg = (uint32_t)temp_reg; } while(false) -#define SAVE_BP_REG(i, _) SAVE_SYSREG64(DBGBVR##i##_EL1); SAVE_SYSREG64(DBGBCR##i##_EL1); -#define SAVE_WP_REG(i, _) SAVE_SYSREG64(DBGWVR##i##_EL1); SAVE_SYSREG64(DBGWCR##i##_EL1); - -#define RESTORE_SYSREG64(reg) do { temp_reg = g_cpu_contexts[current_core].reg; __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false) -#define RESTORE_SYSREG32(reg) RESTORE_SYSREG64(reg) -#define RESTORE_BP_REG(i, _) RESTORE_SYSREG64(DBGBVR##i##_EL1); RESTORE_SYSREG64(DBGBCR##i##_EL1); -#define RESTORE_WP_REG(i, _) RESTORE_SYSREG64(DBGWVR##i##_EL1); RESTORE_SYSREG64(DBGWCR##i##_EL1); - -/* start.s */ -void __attribute__((noreturn)) __jump_to_lower_el(uint64_t arg, uintptr_t ep, uint32_t spsr); - -static saved_cpu_context_t g_cpu_contexts[NUM_CPU_CORES] = {0}; - -void use_core_entrypoint_and_argument(uint32_t core, uintptr_t *entrypoint_addr, uint64_t *argument) { - saved_cpu_context_t *ctx = &g_cpu_contexts[core]; - if(ctx->ELR_EL3 == 0 || ctx->is_active) { - panic(0xF7F00007); /* invalid context */ - } - - *entrypoint_addr = ctx->ELR_EL3; - *argument = ctx->argument; - - ctx->ELR_EL3 = 0; - ctx->argument = 0; - ctx->is_active = 1; -} - -void set_core_entrypoint_and_argument(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) { - g_cpu_contexts[core].ELR_EL3 = entrypoint_addr; - g_cpu_contexts[core].argument = argument; -} - -static __attribute__((target("cmodel=large"), noinline)) -critical_section_t *get_boot_critical_section(void) { - return &g_boot_critical_section; -} - -void __attribute__((noreturn)) core_jump_to_lower_el(void) { - uintptr_t ep; - uint64_t arg; - unsigned int core_id = get_core_id(); - uint32_t spsr = get_spsr(); - critical_section_t *critsec = get_boot_critical_section(); - - use_core_entrypoint_and_argument(core_id, &ep, &arg); - critical_section_leave(critsec); - flush_dcache_range(critsec, (uint8_t *)critsec + sizeof(critical_section_t)); - /* already does a dsb sy */ - __sev(); - - /* Nintendo hardcodes EL1, but we can boot fine using other EL1/EL2 modes as well */ - __jump_to_lower_el(arg, ep, 0b1111 << 6 | (spsr & 0b1101)); /* only keep EL, SPSel, set DAIF */ -} - -uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) { - /* Is core valid? */ - if (core >= NUM_CPU_CORES) { - return 0xFFFFFFFE; - } - - /* Is core already on? */ - if (g_cpu_contexts[core].is_active) { - return 0xFFFFFFFC; - } - - set_core_entrypoint_and_argument(core, entrypoint_addr, argument); - - static const uint32_t status_masks[NUM_CPU_CORES] = {0x4000, 0x200, 0x400, 0x800}; - static const uint32_t toggle_vals[NUM_CPU_CORES] = {0xE, 0x9, 0xA, 0xB}; - - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - /* Reset the core */ - CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 = (1 << (core + 0x10)) | (1 << core); - } - - /* Check if we're already in the correct state. */ - if ((APBDEV_PMC_PWRGATE_STATUS_0 & status_masks[core]) != status_masks[core]) { - uint32_t counter = 5001; - - /* Poll the start bit until 0 */ - while (APBDEV_PMC_PWRGATE_TOGGLE_0 & 0x100) { - wait(1); - counter--; - if (counter < 1) { - goto CPU_ON_SUCCESS; - } - } - - /* Program PWRGATE_TOGGLE with the START bit set to 1, selecting CE[N] */ - APBDEV_PMC_PWRGATE_TOGGLE_0 = toggle_vals[core] | 0x100; - - /* Poll until we're in the correct state. */ - counter = 5001; - while (counter > 0) { - if ((APBDEV_PMC_PWRGATE_STATUS_0 & status_masks[core]) == status_masks[core]) { - break; - } - wait(1); - counter--; - } - } - -CPU_ON_SUCCESS: - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - /* Start the core */ - CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = (1 << (core + 0x10)) | (1 << core); - } - - return 0; -} - -void power_down_current_core(void) { - unsigned int current_core = get_core_id(); - flow_set_csr(current_core, 0); - flow_set_halt_events(current_core, false); - flow_set_cc4_ctrl(current_core, 0); - save_current_core_context(); - g_cpu_contexts[current_core].is_active = 0; - flush_dcache_all(); - finalize_powerdown(); -} - -uint32_t cpu_off(void) { - unsigned int current_core = get_core_id(); - if (current_core == 3) { - power_down_current_core(); - } else { - clear_priv_smc_in_progress(); - call_with_stack_pointer(get_exception_entry_stack_address(current_core), power_down_current_core); - } - while (true) { - /* Wait forever. */ - } - return 0; -} - -void save_current_core_context(void) { - unsigned int current_core = get_core_id(); - uint64_t temp_reg = 1; - /* Write 1 to OS lock .*/ - __asm__ __volatile__ ("msr oslar_el1, %0" : : "r"(temp_reg)); - - /* Save system registers. */ - - SAVE_SYSREG32(OSDTRRX_EL1); - SAVE_SYSREG32(OSDTRTX_EL1); - SAVE_SYSREG32(MDSCR_EL1); - SAVE_SYSREG32(OSECCR_EL1); - SAVE_SYSREG32(MDCCINT_EL1); - SAVE_SYSREG32(DBGCLAIMCLR_EL1); - SAVE_SYSREG32(DBGVCR32_EL2); - SAVE_SYSREG32(SDER32_EL3); - SAVE_SYSREG32(MDCR_EL2); - SAVE_SYSREG32(MDCR_EL3); - SAVE_SYSREG32(SPSR_EL3); - - EVAL(REPEAT(6, SAVE_BP_REG, ~)); - EVAL(REPEAT(4, SAVE_WP_REG, ~)); - - /* Mark context as saved. */ - g_cpu_contexts[current_core].is_saved = 1; -} - -void restore_current_core_context(void) { - unsigned int current_core = get_core_id(); - uint64_t temp_reg; - - if (g_cpu_contexts[current_core].is_saved) { - RESTORE_SYSREG32(OSDTRRX_EL1); - RESTORE_SYSREG32(OSDTRTX_EL1); - RESTORE_SYSREG32(MDSCR_EL1); - RESTORE_SYSREG32(OSECCR_EL1); - RESTORE_SYSREG32(MDCCINT_EL1); - RESTORE_SYSREG32(DBGCLAIMCLR_EL1); - RESTORE_SYSREG32(DBGVCR32_EL2); - RESTORE_SYSREG32(SDER32_EL3); - RESTORE_SYSREG32(MDCR_EL2); - RESTORE_SYSREG32(MDCR_EL3); - RESTORE_SYSREG32(SPSR_EL3); - - EVAL(REPEAT(6, RESTORE_BP_REG, ~)); - EVAL(REPEAT(4, RESTORE_WP_REG, ~)); - - g_cpu_contexts[current_core].is_saved = 0; - } -} - -bool is_core_active(uint32_t core) { - return g_cpu_contexts[core].is_active != 0; -} - -void set_core_is_active(uint32_t core, bool is_active) { - g_cpu_contexts[core].is_active = (is_active) ? 1 : 0; -} - -void set_current_core_active(void) { - set_core_is_active(get_core_id(), true); -} - -void set_current_core_inactive(void) { - set_core_is_active(get_core_id(), false); -} - diff --git a/exosphere/src/cpu_context.h b/exosphere/src/cpu_context.h deleted file mode 100644 index dbdec20c8..000000000 --- a/exosphere/src/cpu_context.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_CPU_CTX_H -#define EXOSPHERE_CPU_CTX_H - -#include "utils.h" -#include "synchronization.h" - -/* Exosphere CPU Management functionality. */ - -extern critical_section_t g_boot_critical_section; - -typedef struct { - uint64_t argument; - uint64_t ELR_EL3; - int is_active; - int is_saved; - uint32_t OSDTRRX_EL1; - uint32_t OSDTRTX_EL1; - uint32_t MDSCR_EL1; - uint32_t OSECCR_EL1; - uint32_t MDCCINT_EL1; - uint32_t DBGCLAIMCLR_EL1; - uint32_t DBGVCR32_EL2; - uint32_t SDER32_EL3; - uint32_t MDCR_EL2; - uint32_t MDCR_EL3; - uint32_t SPSR_EL3; /* not in official code */ - uint64_t DBGBVR0_EL1; - uint64_t DBGBCR0_EL1; - uint64_t DBGBVR1_EL1; - uint64_t DBGBCR1_EL1; - uint64_t DBGBVR2_EL1; - uint64_t DBGBCR2_EL1; - uint64_t DBGBVR3_EL1; - uint64_t DBGBCR3_EL1; - uint64_t DBGBVR4_EL1; - uint64_t DBGBCR4_EL1; - uint64_t DBGBVR5_EL1; - uint64_t DBGBCR5_EL1; - uint64_t DBGWVR0_EL1; - uint64_t DBGWCR0_EL1; - uint64_t DBGWVR1_EL1; - uint64_t DBGWCR1_EL1; - uint64_t DBGWVR2_EL1; - uint64_t DBGWCR2_EL1; - uint64_t DBGWVR3_EL1; - uint64_t DBGWCR3_EL1; -} saved_cpu_context_t; - -#define NUM_CPU_CORES 4 - -void save_current_core_context(void); -void restore_current_core_context(void); - -bool is_core_active(uint32_t core); -void set_core_is_active(uint32_t core, bool is_active); -void set_current_core_active(void); -void set_current_core_inactive(void); - -void use_core_entrypoint_and_argument(uint32_t core, uintptr_t *entrypoint_addr, uint64_t *argument); -void set_core_entrypoint_and_argument(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument); -void __attribute__((noreturn)) core_jump_to_lower_el(void); - -uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument); -uint32_t cpu_off(void); - - -#endif diff --git a/exosphere/src/emummc_cfg.h b/exosphere/src/emummc_cfg.h deleted file mode 100644 index b8d0f90be..000000000 --- a/exosphere/src/emummc_cfg.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_EMUMMC_CONFIG_H -#define EXOSPHERE_EMUMMC_CONFIG_H - -#include -#include -#include "utils.h" - -/* "EFS0" */ -#define MAGIC_EMUMMC_CONFIG (0x30534645) - -#define EMUMMC_FILE_PATH_MAX (0x80) - -typedef enum { - EMUMMC_TYPE_NONE = 0, - EMUMMC_TYPE_PARTITION = 1, - EMUMMC_TYPE_FILES = 2, -} emummc_type_t; - -typedef enum { - EMUMMC_MMC_NAND = 0, - EMUMMC_MMC_SD = 1, - EMUMMC_MMC_GC = 2, -} emummc_mmc_t; - -typedef struct { - uint32_t magic; - uint32_t type; - uint32_t id; - uint32_t fs_version; -} emummc_base_config_t; - -typedef struct { - uint64_t start_sector; -} emummc_partition_config_t; - -typedef struct { - char path[EMUMMC_FILE_PATH_MAX]; -} emummc_file_config_t; - -typedef struct { - emummc_base_config_t base_cfg; - union { - emummc_partition_config_t partition_cfg; - emummc_file_config_t file_cfg; - }; - char emu_dir_path[EMUMMC_FILE_PATH_MAX]; -} exo_emummc_config_t; - -_Static_assert(sizeof(exo_emummc_config_t) == 0x110, "exo_emummc_config_t definition!"); - -#endif diff --git a/exosphere/src/exceptions.s b/exosphere/src/exceptions.s deleted file mode 100644 index 501efe0ae..000000000 --- a/exosphere/src/exceptions.s +++ /dev/null @@ -1,254 +0,0 @@ -/* Some macros taken from https://github.com/ARM-software/arm-trusted-firmware/blob/master/include/common/aarch64/asm_macros.S */ -/* - * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - - -/* - * Declare the exception vector table, enforcing it is aligned on a - * 2KB boundary, as required by the ARMv8 architecture. - * Use zero bytes as the fill value to be stored in the padding bytes - * so that it inserts illegal AArch64 instructions. This increases - * security, robustness and potentially facilitates debugging. - */ -.macro vector_base label, section_name=.vectors -.section \section_name, "ax" -.align 11, 0 -\label: -.endm - -/* - * Create an entry in the exception vector table, enforcing it is - * aligned on a 128-byte boundary, as required by the ARMv8 architecture. - * Use zero bytes as the fill value to be stored in the padding bytes - * so that it inserts illegal AArch64 instructions. This increases - * security, robustness and potentially facilitates debugging. - */ -.macro vector_entry label, section_name=.vectors -.cfi_sections .debug_frame -.section \section_name, "ax" -.align 7, 0 -.type \label, %function -.func \label -.cfi_startproc -\label: -.endm - -/* - * This macro verifies that the given vector doesnt exceed the - * architectural limit of 32 instructions. This is meant to be placed - * immediately after the last instruction in the vector. It takes the - * vector entry as the parameter - */ -.macro check_vector_size since - .endfunc - .cfi_endproc - .if (. - \since) > (32 * 4) - .error "Vector exceeds 32 instructions" - .endif -.endm - -/* Actual Vectors for Exosphere. */ -.global exosphere_vectors -vector_base exosphere_vectors - -/* Current EL, SP0 */ -.global unknown_exception -unknown_exception: -vector_entry synch_sp0 - /* Panic with color FF7700, code 10. */ - mov x0, #0x10 - movk x0, #0x07F0,lsl#16 - b panic - check_vector_size synch_sp0 - -vector_entry irq_sp0 - b unknown_exception - check_vector_size irq_sp0 - -vector_entry fiq_sp0 - b unknown_exception - check_vector_size fiq_sp0 - -vector_entry serror_sp0 - b unknown_exception - check_vector_size serror_sp0 - -/* Current EL, SPx */ -vector_entry synch_spx - b unknown_exception - check_vector_size synch_spx - -vector_entry irq_spx - b unknown_exception - check_vector_size irq_spx - -vector_entry fiq_spx - b unknown_exception - check_vector_size fiq_spx - -vector_entry serror_spx - b unknown_exception - check_vector_size serror_spx - -/* Lower EL, A64 */ -vector_entry synch_a64 - stp x29, x30, [sp, #-0x10]! - /* Verify SMC. */ - mrs x30, esr_el3 - lsr w29, w30, #0x1A - cmp w29, #0x17 - ldp x29, x30, [sp],#0x10 - b.ne unknown_exception - /* Call appropriate handler. */ - stp x29, x30, [sp, #-0x10]! - mrs x29, mpidr_el1 - and x29, x29, #0x3 - cmp x29, #0x3 - b.ne handle_core012_smc_exception - bl handle_core3_smc_exception - ldp x29, x30, [sp],#0x10 - eret - check_vector_size synch_a64 - -vector_entry irq_a64 - b unknown_exception - check_vector_size irq_a64 - -vector_entry fiq_a64 - stp x29, x30, [sp, #-0x10]! - mrs x29, mpidr_el1 - and x29, x29, #0x3 - cmp x29, #0x3 - b.ne unknown_exception - stp x28, x29, [sp, #-0x10]! - stp x26, x27, [sp, #-0x10]! - bl handle_fiq_exception - ldp x26, x27, [sp],#0x10 - ldp x28, x29, [sp],#0x10 - ldp x29, x30, [sp],#0x10 - eret - check_vector_size fiq_a64 - -vector_entry serror_a64 - b unknown_exception - .endfunc - .cfi_endproc -/* To save space, insert in an unused vector segment. */ -.global handle_core012_smc_exception -.type handle_core012_smc_exception, %function -handle_core012_smc_exception: - stp x6, x7, [sp, #-0x10]! - stp x4, x5, [sp, #-0x10]! - stp x2, x3, [sp, #-0x10]! - stp x0, x1, [sp, #-0x10]! - bl set_priv_smc_in_progress - bl get_smc_core012_stack_address - mov x29, x0 - ldp x0, x1, [sp],#0x10 - ldp x2, x3, [sp],#0x10 - ldp x4, x5, [sp],#0x10 - ldp x6, x7, [sp],#0x10 - mov x30, sp - mov sp, x29 - stp x29, x30, [sp, #-0x10]! - bl handle_core3_smc_exception - ldp x29, x30, [sp],#0x10 - mov sp, x30 - stp x6, x7, [sp, #-0x10]! - stp x4, x5, [sp, #-0x10]! - stp x2, x3, [sp, #-0x10]! - stp x0, x1, [sp, #-0x10]! - bl clear_priv_smc_in_progress - ldp x0, x1, [sp],#0x10 - ldp x2, x3, [sp],#0x10 - ldp x4, x5, [sp],#0x10 - ldp x6, x7, [sp],#0x10 - ldp x29, x30, [sp],#0x10 - eret - -/* Lower EL, A32 */ -vector_entry synch_a32 - b unknown_exception - check_vector_size synch_a32 - -vector_entry irq_a32 - b unknown_exception - check_vector_size irq_a32 - -vector_entry fiq_a32 - b fiq_a64 - .endfunc - .cfi_endproc -/* To save space, insert in an unused vector segment. */ -.global handle_fiq_exception -.type handle_fiq_exception, %function -handle_fiq_exception: - stp x29, x30, [sp, #-0x10]! - stp x24, x25, [sp, #-0x10]! - stp x22, x23, [sp, #-0x10]! - stp x20, x21, [sp, #-0x10]! - stp x18, x19, [sp, #-0x10]! - stp x16, x17, [sp, #-0x10]! - stp x14, x15, [sp, #-0x10]! - stp x12, x13, [sp, #-0x10]! - stp x10, x11, [sp, #-0x10]! - stp x8, x9, [sp, #-0x10]! - stp x6, x7, [sp, #-0x10]! - stp x4, x5, [sp, #-0x10]! - stp x2, x3, [sp, #-0x10]! - stp x0, x1, [sp, #-0x10]! - bl handle_registered_interrupt - ldp x0, x1, [sp],#0x10 - ldp x2, x3, [sp],#0x10 - ldp x4, x5, [sp],#0x10 - ldp x6, x7, [sp],#0x10 - ldp x8, x9, [sp],#0x10 - ldp x10, x11, [sp],#0x10 - ldp x12, x13, [sp],#0x10 - ldp x14, x15, [sp],#0x10 - ldp x16, x17, [sp],#0x10 - ldp x18, x19, [sp],#0x10 - ldp x20, x21, [sp],#0x10 - ldp x22, x23, [sp],#0x10 - ldp x24, x25, [sp],#0x10 - ldp x29, x30, [sp],#0x10 - ret - -vector_entry serror_a32 - b unknown_exception - .endfunc - .cfi_endproc -/* To save space, insert in an unused vector segment. */ -.global handle_core3_smc_exception -.type handle_core3_smc_exception, %function -handle_core3_smc_exception: - stp x29, x30, [sp, #-0x10]! - stp x18, x19, [sp, #-0x10]! - stp x16, x17, [sp, #-0x10]! - stp x14, x15, [sp, #-0x10]! - stp x12, x13, [sp, #-0x10]! - stp x10, x11, [sp, #-0x10]! - stp x8, x9, [sp, #-0x10]! - stp x6, x7, [sp, #-0x10]! - stp x4, x5, [sp, #-0x10]! - stp x2, x3, [sp, #-0x10]! - stp x0, x1, [sp, #-0x10]! - mrs x0, esr_el3 - and x0, x0, #0xFFFF - mov x1, sp - bl call_smc_handler - ldp x0, x1, [sp],#0x10 - ldp x2, x3, [sp],#0x10 - ldp x4, x5, [sp],#0x10 - ldp x6, x7, [sp],#0x10 - ldp x8, x9, [sp],#0x10 - ldp x10, x11, [sp],#0x10 - ldp x12, x13, [sp],#0x10 - ldp x14, x15, [sp],#0x10 - ldp x16, x17, [sp],#0x10 - ldp x18, x19, [sp],#0x10 - ldp x29, x30, [sp],#0x10 - ret diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c deleted file mode 100644 index f757f9824..000000000 --- a/exosphere/src/exocfg.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "exocfg.h" -#include "mmu.h" -#include "memory_map.h" - -static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_CONFIG, ATMOSPHERE_TARGET_FIRMWARE_CURRENT, EXOSPHERE_FLAGS_DEFAULT}; -static bool g_has_loaded_config = false; - -#define EXOSPHERE_CHECK_FLAG(flag) ((g_exosphere_cfg.flags & flag) != 0) - -static unsigned int exosphere_is_emummc() { - return g_exosphere_cfg.emummc_cfg.base_cfg.magic == MAGIC_EMUMMC_CONFIG && g_exosphere_cfg.emummc_cfg.base_cfg.type != EMUMMC_TYPE_NONE; -} - -/* Read config out of IRAM, return target firmware version. */ -unsigned int exosphere_load_config(void) { - if (g_has_loaded_config) { - generic_panic(); - } - g_has_loaded_config = true; - - const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG.magic; - - if (magic == MAGIC_EXOSPHERE_CONFIG) { - g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG; - } - - return g_exosphere_cfg.target_firmware; -} - -unsigned int exosphere_get_target_firmware(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return g_exosphere_cfg.target_firmware; -} - -unsigned int exosphere_should_perform_620_keygen(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return false; -} - -unsigned int exosphere_should_override_debugmode_priv(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV); -} - -unsigned int exosphere_should_override_debugmode_user(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_USER); -} - -unsigned int exosphere_should_disable_usermode_exception_handlers(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS); -} - -unsigned int exosphere_should_enable_usermode_pmu_access(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS); -} - -unsigned int exosphere_should_blank_prodinfo(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_BLANK_PRODINFO); -} - -unsigned int exosphere_should_allow_writing_to_cal(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - if (exosphere_is_emummc()) { - return 1; - } else { - return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC); - } -} - -const exo_emummc_config_t *exosphere_get_emummc_config(void) { - if (!g_has_loaded_config) { - generic_panic(); - } - - return &g_exosphere_cfg.emummc_cfg; -} diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h deleted file mode 100644 index 6be2787b7..000000000 --- a/exosphere/src/exocfg.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_EXOSPHERE_CONFIG_H -#define EXOSPHERE_EXOSPHERE_CONFIG_H - -#include -#include -#include "utils.h" - -#include "memory_map.h" -#include "emummc_cfg.h" - -/* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ - -/* "EXO0" */ -#define MAGIC_EXOSPHERE_CONFIG (0x304F5845) - -#define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1 - -#define MAILBOX_EXOSPHERE_CONFIG (*((volatile exosphere_config_t *)(0x8000F000ull))) - -/* Exosphere config in DRAM shares physical/virtual mapping. */ -#define MAILBOX_EXOSPHERE_CONFIG_PHYS MAILBOX_EXOSPHERE_CONFIG - -#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN_DEPRECATED (1 << 0u) -#define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u) -#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) -#define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u) -#define EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS (1 << 4u) -#define EXOSPHERE_FLAG_BLANK_PRODINFO (1 << 5u) -#define EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC (1 << 6u) -#define EXOSPHERE_FLAGS_DEFAULT (EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV) - -typedef struct { - uint32_t magic; - uint32_t target_firmware; - uint32_t flags; - uint32_t reserved[5]; - exo_emummc_config_t emummc_cfg; -} exosphere_config_t; - -_Static_assert(sizeof(exosphere_config_t) == 0x20 + sizeof(exo_emummc_config_t), "exosphere config definition"); - -unsigned int exosphere_load_config(void); -unsigned int exosphere_get_target_firmware(void); -unsigned int exosphere_should_perform_620_keygen(void); -unsigned int exosphere_should_override_debugmode_priv(void); -unsigned int exosphere_should_override_debugmode_user(void); -unsigned int exosphere_should_disable_usermode_exception_handlers(void); -unsigned int exosphere_should_enable_usermode_pmu_access(void); -unsigned int exosphere_should_blank_prodinfo(void); -unsigned int exosphere_should_allow_writing_to_cal(void); - -const exo_emummc_config_t *exosphere_get_emummc_config(void); - -static inline unsigned int exosphere_get_target_firmware_for_init(void) { - const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic; - if (magic == MAGIC_EXOSPHERE_CONFIG) { - return MAILBOX_EXOSPHERE_CONFIG_PHYS.target_firmware; - } else { - return ATMOSPHERE_TARGET_FIRMWARE_CURRENT; - } -} - -#endif diff --git a/exosphere/src/flow.h b/exosphere/src/flow.h deleted file mode 100644 index e24696116..000000000 --- a/exosphere/src/flow.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_FLOW_CTLR_H -#define EXOSPHERE_FLOW_CTLR_H - -#include -#include -#include "cpu_context.h" -#include "memory_map.h" - -/* Exosphere register definitions for the Tegra X1 Flow Controller. */ - -static inline uintptr_t get_flow_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_FLOWCTRL); -} - -#define FLOW_BASE (get_flow_base()) - -#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_BASE + ofs) - -#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) -#define FLOW_CTLR_FLOW_DBG_QUAL_0 MAKE_FLOW_REG(0x050) -#define FLOW_CTLR_L2FLUSH_CONTROL_0 MAKE_FLOW_REG(0x094) -#define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098) - - -static const struct { - unsigned int CPUN_CSR_OFS; - unsigned int HALT_CPUN_EVENTS_OFS; - unsigned int CC4_COREN_CTRL_OFS; -} g_flow_core_offsets[NUM_CPU_CORES] = { - {0x008, 0x000, 0x06C}, - {0x018, 0x014, 0x070}, - {0x020, 0x01C, 0x074}, - {0x028, 0x024, 0x078}, -}; - -static inline void flow_set_cc4_ctrl(uint32_t core, uint32_t cc4_ctrl) { - MAKE_FLOW_REG(g_flow_core_offsets[core].CC4_COREN_CTRL_OFS) = cc4_ctrl; -} - -static inline void flow_set_halt_events(uint32_t core, bool halt_events) { - MAKE_FLOW_REG(g_flow_core_offsets[core].HALT_CPUN_EVENTS_OFS) = (halt_events ? 0x40000F00 : 0x40000000); -} - -static inline void flow_set_csr(uint32_t core, uint32_t csr) { - MAKE_FLOW_REG(g_flow_core_offsets[core].CPUN_CSR_OFS) = (0x100 << core) | (csr << 12) | 0xC001; -} - -static inline void flow_clear_csr0_and_events(uint32_t core) { - MAKE_FLOW_REG(g_flow_core_offsets[core].CPUN_CSR_OFS) = 0; - MAKE_FLOW_REG(g_flow_core_offsets[core].HALT_CPUN_EVENTS_OFS) = 0; -} - -#endif diff --git a/exosphere/src/fuse.c b/exosphere/src/fuse.c deleted file mode 100644 index b10b6f7a8..000000000 --- a/exosphere/src/fuse.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * 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 - -#include "car.h" -#include "fuse.h" -#include "masterkey.h" -#include "pmc.h" -#include "timers.h" - -static bool g_has_checked_for_rcm_bug_patch = false; -static bool g_has_rcm_bug_patch = false; - -/* Prototypes for internal commands. */ -void fuse_enable_power(void); -void fuse_disable_power(void); -void fuse_wait_idle(void); - -/* Initialize the fuse driver */ -void fuse_init(void) { - /* Make all fuse registers visible, disable the private key and disable programming. */ - clkrst_enable_fuse_regs(true); - fuse_disable_private_key(); - fuse_disable_programming(); - - /* TODO: Should we allow this to be done later? */ - if (!g_has_checked_for_rcm_bug_patch) { - (void)(fuse_has_rcm_bug_patch()); - } -} - -/* Disable access to the private key and set the TZ sticky bit. */ -void fuse_disable_private_key(void) { - FUSE_REGS->FUSE_PRIVATEKEYDISABLE = 0x10; -} - -/* Disables all fuse programming. */ -void fuse_disable_programming(void) { - FUSE_REGS->FUSE_DISABLEREGPROGRAM = 1; -} - -/* Enable power to the fuse hardware array. */ -void fuse_enable_power(void) { - APBDEV_PMC_FUSE_CTRL &= ~(0x200); /* Clear PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */ - mdelay(1); - APBDEV_PMC_FUSE_CTRL |= 0x100; /* Set PMC_FUSE_CTRL_PS18_LATCH_SET. */ - mdelay(1); -} - -/* Disable power to the fuse hardware array. */ -void fuse_disable_power(void) { - APBDEV_PMC_FUSE_CTRL &= ~(0x100); /* Clear PMC_FUSE_CTRL_PS18_LATCH_SET. */ - mdelay(1); - APBDEV_PMC_FUSE_CTRL |= 0x200; /* Set PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */ - mdelay(1); -} - -/* Wait for the fuse driver to go idle. */ -void fuse_wait_idle(void) { - uint32_t ctrl_val = 0; - - /* Wait for STATE_IDLE */ - while ((ctrl_val & (0xF0000)) != 0x40000) - ctrl_val = FUSE_REGS->FUSE_FUSECTRL; -} - -/* Read a fuse from the hardware array. */ -uint32_t fuse_hw_read(uint32_t addr) { - /* Wait for idle state. */ - fuse_wait_idle(); - - /* Program the target address. */ - FUSE_REGS->FUSE_FUSEADDR = addr; - - /* Enable read operation in control register. */ - uint32_t ctrl_val = FUSE_REGS->FUSE_FUSECTRL; - ctrl_val &= ~0x3; - ctrl_val |= 0x1; /* Set READ command. */ - FUSE_REGS->FUSE_FUSECTRL = ctrl_val; - - /* Wait for idle state. */ - fuse_wait_idle(); - - return FUSE_REGS->FUSE_FUSERDATA; -} - -/* Write a fuse in the hardware array. */ -void fuse_hw_write(uint32_t value, uint32_t addr) { - /* Wait for idle state. */ - fuse_wait_idle(); - - /* Program the target address and value. */ - FUSE_REGS->FUSE_FUSEADDR = addr; - FUSE_REGS->FUSE_FUSEWDATA = value; - - /* Enable write operation in control register. */ - uint32_t ctrl_val = FUSE_REGS->FUSE_FUSECTRL; - ctrl_val &= ~0x3; - ctrl_val |= 0x2; /* Set WRITE command. */ - FUSE_REGS->FUSE_FUSECTRL = ctrl_val; - - /* Wait for idle state. */ - fuse_wait_idle(); -} - -/* Sense the fuse hardware array into the shadow cache. */ -void fuse_hw_sense(void) { - /* Wait for idle state. */ - fuse_wait_idle(); - - /* Enable sense operation in control register */ - uint32_t ctrl_val = FUSE_REGS->FUSE_FUSECTRL; - ctrl_val &= ~0x3; - ctrl_val |= 0x3; /* Set SENSE_CTRL command */ - FUSE_REGS->FUSE_FUSECTRL = ctrl_val; - - /* Wait for idle state. */ - fuse_wait_idle(); -} - -/* Read the SKU info register from the shadow cache. */ -uint32_t fuse_get_sku_info(void) { - return FUSE_CHIP_REGS->FUSE_SKU_INFO; -} - -/* Read the bootrom patch version from a register in the shadow cache. */ -uint32_t fuse_get_bootrom_patch_version(void) { - return FUSE_CHIP_REGS->FUSE_SOC_SPEEDO_1_CALIB; -} - -/* Read a spare bit register from the shadow cache */ -uint32_t fuse_get_spare_bit(uint32_t idx) { - if (idx < 32) { - return FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx]; - } else { - return 0; - } -} - -/* Read a reserved ODM register from the shadow cache. */ -uint32_t fuse_get_reserved_odm(uint32_t idx) { - if (idx < 8) { - return FUSE_CHIP_REGS->FUSE_RESERVED_ODM[idx]; - } else { - return 0; - } -} - -/* Get the DRAM ID using values in the shadow cache. */ -uint32_t fuse_get_dram_id(void) { - return ((fuse_get_reserved_odm(4) >> 3) & 0x7); -} - -/* Derive the Device ID using values in the shadow cache. */ -uint64_t fuse_get_device_id(void) { - uint64_t device_id = 0; - uint64_t y_coord = FUSE_CHIP_REGS->FUSE_OPT_Y_COORDINATE & 0x1FF; - uint64_t x_coord = FUSE_CHIP_REGS->FUSE_OPT_X_COORDINATE & 0x1FF; - uint64_t wafer_id = FUSE_CHIP_REGS->FUSE_OPT_WAFER_ID & 0x3F; - uint32_t lot_code = FUSE_CHIP_REGS->FUSE_OPT_LOT_CODE_0; - uint64_t fab_code = FUSE_CHIP_REGS->FUSE_OPT_FAB_CODE & 0x3F; - - uint64_t derived_lot_code = 0; - for (unsigned int i = 0; i < 5; i++) { - derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F); - } - derived_lot_code &= 0x03FFFFFF; - - device_id |= y_coord << 0; - device_id |= x_coord << 9; - device_id |= wafer_id << 18; - device_id |= derived_lot_code << 24; - device_id |= fab_code << 50; - - return device_id; -} - -/* Derive the Hardware Type using values in the shadow cache. */ -uint32_t fuse_get_hardware_type(uint32_t target_firmware) { - uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4); - uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1)); - - /* Firmware from versions 1.0.0 to 3.0.2. */ - if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); - if (hardware_type >= 1) { - return (hardware_type > 2) ? 3 : hardware_type - 1; - } else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) { - return 0; - } else { - return 3; - } - } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* Firmware versions from 4.0.0 to 6.2.0. */ - static const uint32_t types[] = {0,1,4,3}; - hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C); - hardware_type--; - return (hardware_type > 3) ? 4 : types[hardware_type]; - } else { /* Firmware versions from 7.0.0 onwards. */ - /* Always return 0 in retail. */ - return 0; - } -} - -/* Derive the Retail Type using values in the shadow cache. */ -uint32_t fuse_get_retail_type(void) { - /* Retail Type = IS_RETAIL | UNIT_TYPE. */ - uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4); - uint32_t retail_type = (((fuse_reserved_odm4 >> 7) & 4) | (fuse_reserved_odm4 & 3)); - if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */ - return 1; - } else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */ - return 0; - } - return 2; /* IS_RETAIL | DEV_UNIT */ -} - -/* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */ -void fuse_get_hardware_info(void *dst) { - uint32_t hw_info[0x4]; - - uint32_t ops_reserved = FUSE_CHIP_REGS->FUSE_OPT_OPS_RESERVED & 0x3F; - uint32_t y_coord = FUSE_CHIP_REGS->FUSE_OPT_Y_COORDINATE & 0x1FF; - uint32_t x_coord = FUSE_CHIP_REGS->FUSE_OPT_X_COORDINATE & 0x1FF; - uint32_t wafer_id = FUSE_CHIP_REGS->FUSE_OPT_WAFER_ID & 0x3F; - uint32_t lot_code_0 = FUSE_CHIP_REGS->FUSE_OPT_LOT_CODE_0; - uint32_t lot_code_1 = FUSE_CHIP_REGS->FUSE_OPT_LOT_CODE_1 & 0x0FFFFFFF; - uint32_t fab_code = FUSE_CHIP_REGS->FUSE_OPT_FAB_CODE & 0x3F; - uint32_t vendor_code = FUSE_CHIP_REGS->FUSE_OPT_VENDOR_CODE & 0xF; - - /* Hardware Info = OPS_RESERVED || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */ - hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (ops_reserved)); - hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2)); - hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6)); - hw_info[3] = (uint32_t)(vendor_code); - - memcpy(dst, hw_info, 0x10); -} - -/* Get the Key Generation value. */ -uint32_t fuse_get_5x_key_generation(void) { - if ((fuse_get_reserved_odm(4) & 0x800) && (fuse_get_reserved_odm(0) == 0x8E61ECAE) && (fuse_get_reserved_odm(1) == 0xF2BA3BB2)) { - return (fuse_get_reserved_odm(2) & 0x1F); - } else { - return 0; - } -} - -/* Returns the fuse version expected for the firmware. */ -uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware) { - if (fuse_get_retail_type() != 0) { - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) { - return 13; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_1_0) { - return 12; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0) { - return 11; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) { - return 10; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { - return 9; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) { - return 8; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - return 7; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - return 6; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - return 5; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_2) { - return 4; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { - return 3; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - return 2; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_1_0_0) { - return 1; - } else { - return 0; - } - } else { - return (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) ? 1 : 0; - } -} - -/* Check for RCM bug patches. */ -bool fuse_has_rcm_bug_patch(void) { - /* Only check for RCM bug patch once, and cache our result. */ - if (!g_has_checked_for_rcm_bug_patch) { - /* Some patched units use XUSB in RCM. */ - if (FUSE_CHIP_REGS->FUSE_RESERVED_SW & 0x80) { - g_has_rcm_bug_patch = true; - } - - /* Other units have a proper ipatch instead. */ - { - uint32_t word_count = FUSE_CHIP_REGS->FUSE_FIRST_BOOTROM_PATCH_SIZE & 0x7f; - uint32_t word_addr = 191; - - while (word_count) { - uint32_t word0 = fuse_hw_read(word_addr); - uint32_t ipatch_count = (word0 >> 16) & 0xf; - - for (uint32_t i = 0; i < ipatch_count; i++) { - uint32_t word = fuse_hw_read(word_addr - (i + 1)); - uint32_t addr = (word >> 16) * 2; - - if (addr == 0x769a) { - g_has_rcm_bug_patch = true; - } - } - - word_addr -= word_count; - word_count = word0 >> 25; - } - } - } - g_has_checked_for_rcm_bug_patch = true; - - return g_has_rcm_bug_patch; -} \ No newline at end of file diff --git a/exosphere/src/fuse.h b/exosphere/src/fuse.h deleted file mode 100644 index 931f7ea08..000000000 --- a/exosphere/src/fuse.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_FUSE_H -#define EXOSPHERE_FUSE_H - -#include -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 FUSE registers. */ - -typedef struct { - uint32_t FUSE_FUSECTRL; - uint32_t FUSE_FUSEADDR; - uint32_t FUSE_FUSERDATA; - uint32_t FUSE_FUSEWDATA; - uint32_t FUSE_FUSETIME_RD1; - uint32_t FUSE_FUSETIME_RD2; - uint32_t FUSE_FUSETIME_PGM1; - uint32_t FUSE_FUSETIME_PGM2; - uint32_t FUSE_PRIV2INTFC_START; - uint32_t FUSE_FUSEBYPASS; - uint32_t FUSE_PRIVATEKEYDISABLE; - uint32_t FUSE_DISABLEREGPROGRAM; - uint32_t FUSE_WRITE_ACCESS_SW; - uint32_t FUSE_PWR_GOOD_SW; - uint32_t _0x38; - uint32_t FUSE_PRIV2RESHIFT; - uint32_t _0x40[0x3]; - uint32_t FUSE_FUSETIME_RD3; - uint32_t _0x50[0xC]; - uint32_t FUSE_PRIVATE_KEY0_NONZERO; - uint32_t FUSE_PRIVATE_KEY1_NONZERO; - uint32_t FUSE_PRIVATE_KEY2_NONZERO; - uint32_t FUSE_PRIVATE_KEY3_NONZERO; - uint32_t FUSE_PRIVATE_KEY4_NONZERO; - uint32_t _0x90[0x1C]; -} tegra_fuse_t; - -typedef struct { - uint32_t FUSE_PRODUCTION_MODE; - uint32_t FUSE_JTAG_SECUREID_VALID; - uint32_t FUSE_ODM_LOCK; - uint32_t FUSE_OPT_OPENGL_EN; - uint32_t FUSE_SKU_INFO; - uint32_t FUSE_CPU_SPEEDO_0_CALIB; - uint32_t FUSE_CPU_IDDQ_CALIB; - uint32_t FUSE_DAC_CRT_CALIB; - uint32_t FUSE_DAC_HDTV_CALIB; - uint32_t FUSE_DAC_SDTV_CALIB; - uint32_t FUSE_OPT_FT_REV; - uint32_t FUSE_CPU_SPEEDO_1_CALIB; - uint32_t FUSE_CPU_SPEEDO_2_CALIB; - uint32_t FUSE_SOC_SPEEDO_0_CALIB; - uint32_t FUSE_SOC_SPEEDO_1_CALIB; - uint32_t FUSE_SOC_SPEEDO_2_CALIB; - uint32_t FUSE_SOC_IDDQ_CALIB; - uint32_t FUSE_RESERVED_PRODUCTION_WP; - uint32_t FUSE_FA; - uint32_t FUSE_RESERVED_PRODUCTION; - uint32_t FUSE_HDMI_LANE0_CALIB; - uint32_t FUSE_HDMI_LANE1_CALIB; - uint32_t FUSE_HDMI_LANE2_CALIB; - uint32_t FUSE_HDMI_LANE3_CALIB; - uint32_t FUSE_ENCRYPTION_RATE; - uint32_t FUSE_PUBLIC_KEY[0x8]; - uint32_t FUSE_TSENSOR1_CALIB; - uint32_t FUSE_TSENSOR2_CALIB; - uint32_t FUSE_VSENSOR_CALIB; - uint32_t FUSE_OPT_CP_REV; - uint32_t FUSE_OPT_PFG; - uint32_t FUSE_TSENSOR0_CALIB; - uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE; - uint32_t FUSE_SECURITY_MODE; - uint32_t FUSE_PRIVATE_KEY[0x5]; - uint32_t FUSE_ARM_JTAG_DIS; - uint32_t FUSE_BOOT_DEVICE_INFO; - uint32_t FUSE_RESERVED_SW; - uint32_t FUSE_OPT_VP9_DISABLE; - uint32_t FUSE_RESERVED_ODM[0x8]; - uint32_t FUSE_OBS_DIS; - uint32_t FUSE_NOR_INFO; - uint32_t FUSE_USB_CALIB; - uint32_t FUSE_SKU_DIRECT_CONFIG; - uint32_t FUSE_KFUSE_PRIVKEY_CTRL; - uint32_t FUSE_PACKAGE_INFO; - uint32_t FUSE_OPT_VENDOR_CODE; - uint32_t FUSE_OPT_FAB_CODE; - uint32_t FUSE_OPT_LOT_CODE_0; - uint32_t FUSE_OPT_LOT_CODE_1; - uint32_t FUSE_OPT_WAFER_ID; - uint32_t FUSE_OPT_X_COORDINATE; - uint32_t FUSE_OPT_Y_COORDINATE; - uint32_t FUSE_OPT_SEC_DEBUG_EN; - uint32_t FUSE_OPT_OPS_RESERVED; - uint32_t FUSE_SATA_CALIB; - uint32_t FUSE_GPU_IDDQ_CALIB; - uint32_t FUSE_TSENSOR3_CALIB; - uint32_t FUSE_SKU_BOND_OUT_L; - uint32_t FUSE_SKU_BOND_OUT_H; - uint32_t FUSE_SKU_BOND_OUT_U; - uint32_t FUSE_SKU_BOND_OUT_V; - uint32_t FUSE_SKU_BOND_OUT_W; - uint32_t FUSE_OPT_SAMPLE_TYPE; - uint32_t FUSE_OPT_SUBREVISION; - uint32_t FUSE_OPT_SW_RESERVED_0; - uint32_t FUSE_OPT_SW_RESERVED_1; - uint32_t FUSE_TSENSOR4_CALIB; - uint32_t FUSE_TSENSOR5_CALIB; - uint32_t FUSE_TSENSOR6_CALIB; - uint32_t FUSE_TSENSOR7_CALIB; - uint32_t FUSE_OPT_PRIV_SEC_EN; - uint32_t FUSE_PKC_DISABLE; - uint32_t _0x16C; - uint32_t _0x170; - uint32_t _0x174; - uint32_t _0x178; - uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE; - uint32_t FUSE_TSENSOR_COMMON; - uint32_t FUSE_OPT_CP_BIN; - uint32_t FUSE_OPT_GPU_DISABLE; - uint32_t FUSE_OPT_FT_BIN; - uint32_t FUSE_OPT_DONE_MAP; - uint32_t _0x194; - uint32_t FUSE_APB2JTAG_DISABLE; - uint32_t FUSE_ODM_INFO; - uint32_t _0x1A0; - uint32_t _0x1A4; - uint32_t FUSE_ARM_CRYPT_DE_FEATURE; - uint32_t _0x1AC; - uint32_t _0x1B0; - uint32_t _0x1B4; - uint32_t _0x1B8; - uint32_t _0x1BC; - uint32_t FUSE_WOA_SKU_FLAG; - uint32_t FUSE_ECO_RESERVE_1; - uint32_t FUSE_GCPLEX_CONFIG_FUSE; - uint32_t FUSE_PRODUCTION_MONTH; - uint32_t FUSE_RAM_REPAIR_INDICATOR; - uint32_t FUSE_TSENSOR9_CALIB; - uint32_t _0x1D8; - uint32_t FUSE_VMIN_CALIBRATION; - uint32_t FUSE_AGING_SENSOR_CALIBRATION; - uint32_t FUSE_DEBUG_AUTHENTICATION; - uint32_t FUSE_SECURE_PROVISION_INDEX; - uint32_t FUSE_SECURE_PROVISION_INFO; - uint32_t FUSE_OPT_GPU_DISABLE_CP1; - uint32_t FUSE_SPARE_ENDIS; - uint32_t FUSE_ECO_RESERVE_0; - uint32_t _0x1FC; - uint32_t _0x200; - uint32_t FUSE_RESERVED_CALIB0; - uint32_t FUSE_RESERVED_CALIB1; - uint32_t FUSE_OPT_GPU_TPC0_DISABLE; - uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1; - uint32_t FUSE_OPT_CPU_DISABLE; - uint32_t FUSE_OPT_CPU_DISABLE_CP1; - uint32_t FUSE_TSENSOR10_CALIB; - uint32_t FUSE_TSENSOR10_CALIB_AUX; - uint32_t FUSE_OPT_RAM_SVOP_DP; - uint32_t FUSE_OPT_RAM_SVOP_PDP; - uint32_t FUSE_OPT_RAM_SVOP_REG; - uint32_t FUSE_OPT_RAM_SVOP_SP; - uint32_t FUSE_OPT_RAM_SVOP_SMPDP; - uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2; - uint32_t FUSE_OPT_GPU_TPC1_DISABLE; - uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1; - uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2; - uint32_t FUSE_OPT_CPU_DISABLE_CP2; - uint32_t FUSE_OPT_GPU_DISABLE_CP2; - uint32_t FUSE_USB_CALIB_EXT; - uint32_t FUSE_RESERVED_FIELD; - uint32_t FUSE_OPT_ECC_EN; - uint32_t _0x25C; - uint32_t _0x260; - uint32_t _0x264; - uint32_t _0x268; - uint32_t _0x26C; - uint32_t _0x270; - uint32_t _0x274; - uint32_t _0x278; - uint32_t FUSE_SPARE_REALIGNMENT_REG; - uint32_t FUSE_SPARE_BIT[0x20]; -} tegra_fuse_chip_t; - -static inline volatile tegra_fuse_t *fuse_get_regs(void) { - return (volatile tegra_fuse_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_FUSE) + 0x800); -} - -static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) { - return (volatile tegra_fuse_chip_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_FUSE) + 0x900); -} - -#define FUSE_REGS (fuse_get_regs()) -#define FUSE_CHIP_REGS (fuse_chip_get_regs()) - -void fuse_init(void); -void fuse_disable_programming(void); -void fuse_disable_private_key(void); - -uint32_t fuse_get_sku_info(void); -uint32_t fuse_get_spare_bit(uint32_t idx); -uint32_t fuse_get_reserved_odm(uint32_t idx); -uint32_t fuse_get_bootrom_patch_version(void); -uint64_t fuse_get_device_id(void); -uint32_t fuse_get_dram_id(void); -uint32_t fuse_get_hardware_type(uint32_t target_firmware); -uint32_t fuse_get_retail_type(void); -void fuse_get_hardware_info(void *dst); -uint32_t fuse_get_5x_key_generation(void); -bool fuse_has_rcm_bug_patch(void); - -uint32_t fuse_hw_read(uint32_t addr); -void fuse_hw_write(uint32_t value, uint32_t addr); -void fuse_hw_sense(void); - - -uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware); - -#endif diff --git a/exosphere/src/gcm.c b/exosphere/src/gcm.c deleted file mode 100644 index 239093c34..000000000 --- a/exosphere/src/gcm.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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 - -#include "arm.h" -#include "utils.h" -#include "fuse.h" -#include "gcm.h" - -#include "sealedkeys.h" -#include "se.h" - -/* Shifts right a little endian 128-bit value. */ -static void shr_128(uint64_t *val) { - val[0] >>= 1; - val[0] |= (val[1] & 1) << 63; - val[1] >>= 1; -} - -/* Shifts left a little endian 128-bit value. */ -static void shl_128(uint64_t *val) { - val[1] <<= 1; - val[1] |= (val[0] & (1ull << 63)) >> 63; - val[0] <<= 1; -} - -/* Multiplies two 128-bit numbers X,Y in the GF(128) Galois Field. */ -static void gf128_mul(uint8_t *dst, const uint8_t *x, const uint8_t *y) { - uint8_t x_work[0x10]; - uint8_t y_work[0x10]; - uint8_t dst_work[0x10]; - - uint64_t *p_x = (uint64_t *)(&x_work[0]); - uint64_t *p_y = (uint64_t *)(&y_work[0]); - uint64_t *p_dst = (uint64_t *)(&dst_work[0]); - - /* Initialize buffers. */ - for (unsigned int i = 0; i < 0x10; i++) { - x_work[i] = x[0xF-i]; - y_work[i] = y[0xF-i]; - dst_work[i] = 0; - } - - /* Perform operation for each bit in y. */ - for (unsigned int round = 0; round < 0x80; round++) { - p_dst[0] ^= p_x[0] * ((y_work[0xF] & 0x80) >> 7); - p_dst[1] ^= p_x[1] * ((y_work[0xF] & 0x80) >> 7); - shl_128(p_y); - uint8_t xval = 0xE1 * (x_work[0] & 1); - shr_128(p_x); - x_work[0xF] ^= xval; - } - - for (unsigned int i = 0; i < 0x10; i++) { - dst[i] = dst_work[0xF-i]; - } -} - - - -/* Performs an AES-GCM GHASH operation over the data into dst. */ -static void ghash(void *dst, const void *data, size_t data_size, const void *j_block, bool encrypt) { - uint8_t x[0x10] = {0}; - uint8_t h[0x10]; - - uint64_t *p_x = (uint64_t *)(&x[0]); - uint64_t *p_data = (uint64_t *)data; - - /* H = aes_ecb_encrypt(zeroes) */ - se_aes_128_ecb_encrypt_block(KEYSLOT_SWITCH_TEMPKEY, h, 0x10, x, 0x10); - - size_t total_size = data_size; - - while (data_size >= 0x10) { - /* X = (X ^ current_block) * H */ - p_x[0] ^= p_data[0]; - p_x[1] ^= p_data[1]; - gf128_mul(x, x, h); - - /* Increment p_data by 0x10 bytes. */ - p_data += 2; - data_size -= 0x10; - } - - /* Nintendo's code *discards all data in the last block* if unaligned. */ - /* And treats that block as though it were all-zero. */ - /* This is a bug, they just forget to XOR with the copy of the last block they save. */ - if (data_size & 0xF) { - gf128_mul(x, x, h); - } - - uint64_t xor_size = total_size << 3; - xor_size = __builtin_bswap64(xor_size); - - /* Due to a Nintendo bug, the wrong QWORD gets XOR'd in the "final output block" case. */ - if (encrypt) { - p_x[0] ^= xor_size; - } else { - p_x[1] ^= xor_size; - } - - gf128_mul(x, x, h); - - /* If final output block, XOR with encrypted J block. */ - if (encrypt) { - se_aes_128_ecb_encrypt_block(KEYSLOT_SWITCH_TEMPKEY, h, 0x10, j_block, 0x10); - for (unsigned int i = 0; i < 0x10; i++) { - x[i] ^= h[i]; - } - } - /* Copy output. */ - memcpy(dst, x, 0x10); -} - - -/* This function is a doozy. It decrypts and validates a (non-standard) AES-GCM wrapped keypair. */ -size_t gcm_decrypt_key(void *dst, size_t dst_size, const void *src, size_t src_size, const void *sealed_kek, size_t kek_size, const void *wrapped_key, size_t key_size, unsigned int usecase, bool is_personalized, uint8_t *out_deviceid_high) { - if (is_personalized == 0) { - /* Devkit keys use a different keyformat without a MAC/Device ID. */ - if (src_size <= 0x10 || src_size - 0x10 > dst_size) { - generic_panic(); - } - } else { - if (src_size <= 0x30 || src_size - 0x20 > dst_size) { - generic_panic(); - } - } - - uint8_t intermediate_buf[0x400] = {0}; - - /* Unwrap the key */ - unseal_key(KEYSLOT_SWITCH_TEMPKEY, sealed_kek, kek_size, usecase); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, KEYSLOT_SWITCH_TEMPKEY, wrapped_key, key_size); - - /* Decrypt the GCM keypair, AES-CTR with CTR = blob[:0x10]. */ - se_aes_ctr_crypt(KEYSLOT_SWITCH_TEMPKEY, intermediate_buf, dst_size, src + 0x10, src_size - 0x10, src, 0x10); - - if (!is_personalized) { - /* Devkit non-personalized keys have no further authentication. */ - memcpy(dst, intermediate_buf, src_size - 0x10); - memset(intermediate_buf, 0, sizeof(intermediate_buf)); - return src_size - 0x10; - } - - /* J = GHASH(CTR); */ - uint8_t j_block[0x10]; - ghash(j_block, src, 0x10, NULL, false); - - /* MAC = GHASH(PLAINTEXT) ^ ENCRYPT(J) */ - /* Note: That MAC is calculated over plaintext is non-standard. */ - /* It is supposed to be over the ciphertext. */ - uint8_t calc_mac[0x10]; - ghash(calc_mac, intermediate_buf, src_size - 0x20, j_block, true); - - /* Const-time memcmp. */ - const uint8_t *src_bytes = src; - int different = 0; - for (unsigned int i = 0; i < 0x10; i++) { - different |= src_bytes[src_size - 0x10 + i] ^ calc_mac[i]; - } - if (different) { - return 0; - } - - if ((read64be(intermediate_buf, src_size - 0x28) & 0x00FFFFFFFFFFFFFFULL) != fuse_get_device_id()) { - return 0; - } - - if (out_deviceid_high != NULL) { - *out_deviceid_high = intermediate_buf[src_size - 0x28]; - } - - memcpy(dst, intermediate_buf, src_size - 0x30); - memset(intermediate_buf, 0, sizeof(intermediate_buf)); - return src_size - 0x30; -} - -void gcm_encrypt_key(void *dst, size_t dst_size, const void *src, size_t src_size, const void *sealed_kek, size_t kek_size, const void *wrapped_key, size_t key_size, unsigned int usecase, uint64_t deviceid_high) { - uint8_t intermediate_buf[0x400] = {0}; - if (src_size + 0x30 > dst_size) { - generic_panic(); - } - - /* Unwrap the key */ - unseal_key(KEYSLOT_SWITCH_TEMPKEY, sealed_kek, kek_size, usecase); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, KEYSLOT_SWITCH_TEMPKEY, wrapped_key, key_size); - - /* Generate a random CTR. */ - flush_dcache_range(intermediate_buf, intermediate_buf + 0x10); - se_generate_random(KEYSLOT_SWITCH_RNGKEY, intermediate_buf, 0x10); - flush_dcache_range(intermediate_buf, intermediate_buf + 0x10); - - /* Copy in the src. */ - memcpy(intermediate_buf + 0x10, src, src_size); - - /* Write Device ID. */ - write64be(intermediate_buf, src_size + 0x18, fuse_get_device_id() | (deviceid_high << 56)); - - /* J = GHASH(CTR); */ - uint8_t j_block[0x10]; - ghash(j_block, intermediate_buf, 0x10, NULL, false); - - /* MAC = GHASH(PLAINTEXT) ^ ENCRYPT(J) */ - /* Note: That MAC is calculated over plaintext is non-standard. */ - /* It is supposed to be over the ciphertext. */ - ghash(intermediate_buf + src_size + 0x20, intermediate_buf + 0x10, src_size + 0x10, j_block, true); - - /* Encrypt the GCM keypair, AES-CTR with CTR = blob[:0x10]. */ - se_aes_ctr_crypt(KEYSLOT_SWITCH_TEMPKEY, intermediate_buf + 0x10, src_size + 0x10, intermediate_buf + 0x10, src_size + 0x10, intermediate_buf, 0x10); - - /* Copy the wrapped key out. */ - memcpy(dst, intermediate_buf, src_size + 0x30); - memset(intermediate_buf, 0, sizeof(intermediate_buf)); -} diff --git a/exosphere/src/gcm.h b/exosphere/src/gcm.h deleted file mode 100644 index 4fe491532..000000000 --- a/exosphere/src/gcm.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_GCM_H -#define EXOSPHERE_GCM_H - -#include -#include - -size_t gcm_decrypt_key(void *dst, size_t dst_size, - const void *src, size_t src_size, - const void *sealed_kek, size_t kek_size, - const void *wrapped_key, size_t key_size, - unsigned int usecase, bool is_personalized, - uint8_t *out_deviceid_high); - - -void gcm_encrypt_key(void *dst, size_t dst_size, - const void *src, size_t src_size, - const void *sealed_kek, size_t kek_size, - const void *wrapped_key, size_t key_size, - unsigned int usecase, uint64_t deviceid_high); - -#endif diff --git a/exosphere/src/i2c.c b/exosphere/src/i2c.c deleted file mode 100644 index 281cc6e96..000000000 --- a/exosphere/src/i2c.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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 "i2c.h" -#include "utils.h" -#include "timers.h" -#include "pinmux.h" - -/* Prototypes for internal commands. */ -volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id); -void i2c_load_config(volatile tegra_i2c_t *regs); - -bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size); -bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size); - -bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size); -bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size); - -/* Configure I2C pinmux. */ -void i2c_config(I2CDevice id) { - volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); - - switch (id) { - case I2C_1: - pinmux->gen1_i2c_scl = PINMUX_INPUT; - pinmux->gen1_i2c_sda = PINMUX_INPUT; - break; - case I2C_2: - pinmux->gen2_i2c_scl = PINMUX_INPUT; - pinmux->gen2_i2c_sda = PINMUX_INPUT; - break; - case I2C_3: - pinmux->gen3_i2c_scl = PINMUX_INPUT; - pinmux->gen3_i2c_sda = PINMUX_INPUT; - break; - case I2C_4: - pinmux->cam_i2c_scl = PINMUX_INPUT; - pinmux->cam_i2c_sda = PINMUX_INPUT; - break; - case I2C_5: - pinmux->pwr_i2c_scl = PINMUX_INPUT; - pinmux->pwr_i2c_sda = PINMUX_INPUT; - break; - case I2C_6: - /* Unused. */ - break; - default: break; - } -} - -/* Initialize I2C based on registers. */ -void i2c_init(I2CDevice id) { - volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); - - /* Setup divisor, and clear the bus. */ - regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; - regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; - - /* Load hardware configuration. */ - i2c_load_config(regs); - - /* Wait a while until BUS_CLEAR_DONE is set. */ - for (unsigned int i = 0; i < 10; i++) { - wait(25); - if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { - break; - } - } - - /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ - regs->I2C_I2C_BUS_CLEAR_STATUS_0; - - /* Read and set the Interrupt Status. */ - uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0; - regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; -} - -/* Sets a bit in a PMIC register over I2C during CPU shutdown. */ -void i2c_send_pmic_cpu_shutdown_cmd(void) { - uint32_t val = 0; - /* PMIC == Device 4:3C. */ - i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); - val |= 4; - i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); -} - -/* Queries the value of TI charger bit over I2C. */ -bool i2c_query_ti_charger_bit_7(void) { - uint32_t val = 0; - /* TI Charger = Device 0:6B. */ - i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); - return (val & 0x80) != 0; -} - -/* Clears TI charger bit over I2C. */ -void i2c_clear_ti_charger_bit_7(void) { - uint32_t val = 0; - /* TI Charger = Device 0:6B. */ - i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); - val &= 0x7F; - i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); -} - -/* Sets TI charger bit over I2C. */ -void i2c_set_ti_charger_bit_7(void) { - uint32_t val = 0; - /* TI Charger = Device 0:6B. */ - i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); - val |= 0x80; - i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); -} - -/* Get registers pointer based on I2C ID. */ -volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id) { - switch (id) { - case I2C_1: - return I2C1_REGS; - case I2C_2: - return I2C2_REGS; - case I2C_3: - return I2C3_REGS; - case I2C_4: - return I2C4_REGS; - case I2C_5: - return I2C5_REGS; - case I2C_6: - return I2C6_REGS; - default: - generic_panic(); - } - return NULL; -} - -/* Load hardware config for I2C4. */ -void i2c_load_config(volatile tegra_i2c_t *regs) { - /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ - regs->I2C_I2C_CONFIG_LOAD_0 = 0x25; - - /* Wait a bit for master config to be loaded. */ - for (unsigned int i = 0; i < 20; i++) { - wait(1); - if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) { - break; - } - } -} - -/* Reads a register from a device over I2C, writes result to output. */ -bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size) { - volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); - uint32_t val = r; - - /* Write single byte register ID to device. */ - if (!i2c_write(regs, device, &val, 1)) { - return false; - } - /* Limit output size to 32-bits. */ - if (dst_size > 4) { - return false; - } - - return i2c_read(regs, device, dst, dst_size); -} - -/* Writes a value to a register over I2C. */ -bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size) { - uint32_t val = r; - if (src_size == 0) { - return true; - } else if (src_size <= 3) { - memcpy(((uint8_t *)&val) + 1, src, src_size); - return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1); - } else { - return false; - } -} - -/* Writes bytes to device over I2C. */ -bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) { - if (src_size > 4) { - return false; - } else if (src_size == 0) { - return true; - } - - /* Set device for 7-bit write mode. */ - regs->I2C_I2C_CMD_ADDR0_0 = device << 1; - - /* Load in data to write. */ - regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0); - - /* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ - regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800; - - i2c_load_config(regs); - - /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); - - while (regs->I2C_I2C_STATUS_0 & 0x100) { - /* Wait until not busy. */ - } - - /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ - return (regs->I2C_I2C_STATUS_0 & 0xF) == 0; -} - -/* Reads bytes from device over I2C. */ -bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) { - if (dst_size > 4) { - return false; - } else if (dst_size == 0) { - return true; - } - - /* Set device for 7-bit read mode. */ - regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1; - - /* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ - regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840; - - i2c_load_config(regs); - - /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); - - while (regs->I2C_I2C_STATUS_0 & 0x100) { - /* Wait until not busy. */ - } - - /* Ensure success. */ - if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) { - return false; - } - - uint32_t val = regs->I2C_I2C_CMD_DATA1_0; - memcpy(dst, &val, dst_size); - return true; -} diff --git a/exosphere/src/i2c.h b/exosphere/src/i2c.h deleted file mode 100644 index eb004972a..000000000 --- a/exosphere/src/i2c.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_I2C_H -#define EXOSPHERE_I2C_H - -#include -#include -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 I2C registers. */ - -#define MAX77621_CPU_I2C_ADDR 0x1B -#define MAX77621_GPU_I2C_ADDR 0x1C -#define MAX17050_I2C_ADDR 0x36 -#define MAX77620_PWR_I2C_ADDR 0x3C -#define MAX77620_RTC_I2C_ADDR 0x68 -#define BQ24193_I2C_ADDR 0x6B - -typedef enum { - I2C_1 = 0, - I2C_2 = 1, - I2C_3 = 2, - I2C_4 = 3, - I2C_5 = 4, - I2C_6 = 5, -} I2CDevice; - -typedef struct { - uint32_t I2C_I2C_CNFG_0; - uint32_t I2C_I2C_CMD_ADDR0_0; - uint32_t I2C_I2C_CMD_ADDR1_0; - uint32_t I2C_I2C_CMD_DATA1_0; - uint32_t I2C_I2C_CMD_DATA2_0; - uint32_t _0x14; - uint32_t _0x18; - uint32_t I2C_I2C_STATUS_0; - uint32_t I2C_I2C_SL_CNFG_0; - uint32_t I2C_I2C_SL_RCVD_0; - uint32_t I2C_I2C_SL_STATUS_0; - uint32_t I2C_I2C_SL_ADDR1_0; - uint32_t I2C_I2C_SL_ADDR2_0; - uint32_t I2C_I2C_TLOW_SEXT_0; - uint32_t _0x38; - uint32_t I2C_I2C_SL_DELAY_COUNT_0; - uint32_t I2C_I2C_SL_INT_MASK_0; - uint32_t I2C_I2C_SL_INT_SOURCE_0; - uint32_t I2C_I2C_SL_INT_SET_0; - uint32_t _0x4C; - uint32_t I2C_I2C_TX_PACKET_FIFO_0; - uint32_t I2C_I2C_RX_FIFO_0; - uint32_t I2C_PACKET_TRANSFER_STATUS_0; - uint32_t I2C_FIFO_CONTROL_0; - uint32_t I2C_FIFO_STATUS_0; - uint32_t I2C_INTERRUPT_MASK_REGISTER_0; - uint32_t I2C_INTERRUPT_STATUS_REGISTER_0; - uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0; - uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0; - uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0; - uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0; - uint32_t I2C_I2C_SLV_RX_FIFO_0; - uint32_t I2C_I2C_SLV_PACKET_STATUS_0; - uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0; - uint32_t I2C_I2C_BUS_CLEAR_STATUS_0; - uint32_t I2C_I2C_CONFIG_LOAD_0; - uint32_t _0x90; - uint32_t I2C_I2C_INTERFACE_TIMING_0_0; - uint32_t I2C_I2C_INTERFACE_TIMING_1_0; - uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0; - uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; -} tegra_i2c_t; - -static inline uintptr_t get_i2c_dtv_234_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DTV_I2C234); -} - -static inline uintptr_t get_i2c56_spi2b_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_I2C56_SPI2B); -} - -#define I2C1_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x000)) -#define I2C2_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x400)) -#define I2C3_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x500)) -#define I2C4_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x700)) -#define I2C5_REGS ((volatile tegra_i2c_t *)(get_i2c56_spi2b_base() + 0x000)) -#define I2C6_REGS ((volatile tegra_i2c_t *)(get_i2c56_spi2b_base() + 0x100)) - -void i2c_config(I2CDevice id); - -void i2c_init(I2CDevice id); -bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size); -bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size); - -void i2c_send_pmic_cpu_shutdown_cmd(void); -bool i2c_query_ti_charger_bit_7(void); -void i2c_clear_ti_charger_bit_7(void); -void i2c_set_ti_charger_bit_7(void); - -#endif diff --git a/exosphere/src/interrupt.c b/exosphere/src/interrupt.c deleted file mode 100644 index 889ccdc95..000000000 --- a/exosphere/src/interrupt.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "interrupt.h" - -/* Global of registered handlers. */ -static struct { - unsigned int id; - void (*handler)(void); -} g_registered_interrupts[MAX_REGISTERED_INTERRUPTS] = { {0} }; - -static unsigned int get_interrupt_id(void) { - return GICC_IAR; -} - -/* Initializes the GIC. This must be called during wakeup. */ -void intr_initialize_gic(void) { - /* Setup interrupts 0-0x1F as nonsecure with highest non-secure priority. */ - GICD_IGROUPR[0] = 0xFFFFFFFF; - for (unsigned int i = 0; i < 0x20; i++) { - GICD_IPRIORITYR[i] = GIC_PRI_HIGHEST_NONSECURE; - } - - /* Setup the GICC. */ - GICC_CTLR = 0x1D9; - GICC_PMR = GIC_PRI_HIGHEST_NONSECURE; - GICC_BPR = 7; -} - -/* Initializes Interrupt Groups 1-7 in the GIC. Called by pk2ldr. */ -void intr_initialize_gic_nonsecure(void) { - for (unsigned int i = 1; i < 8; i++) { - GICD_IGROUPR[i] = 0xFFFFFFFF; - } - - for (unsigned int i = 0x20; i < 0xE0; i++) { - GICD_IPRIORITYR[i] = GIC_PRI_HIGHEST_NONSECURE; - } - GICD_CTLR = 1; -} - -/* Sets GICC_CTLR to appropriate pre-sleep value. */ -void intr_prepare_gicc_for_sleep(void) { - GICC_CTLR = 0x1E0; -} - -/* Sets an interrupt's group in the GICD. */ -void intr_set_group(unsigned int id, int group) { - GICD_IGROUPR[id >> 5] = (GICD_IGROUPR[id >> 5] & (~(1 << (id & 0x1F)))) | ((group & 1) << (id & 0x1F)); -} - -/* Sets an interrupt id as pending in the GICD. */ -void intr_set_pending(unsigned int id) { - GICD_ISPENDR[id >> 5] = 1 << (id & 0x1F); -} - -/* Sets an interrupt's priority in the GICD. */ -void intr_set_priority(unsigned int id, uint8_t priority) { - GICD_IPRIORITYR[id] = priority; -} - -/* Sets an interrupt's target CPU mask in the GICD. */ -void intr_set_cpu_mask(unsigned int id, uint8_t mask) { - GICD_ITARGETSR[id] = mask; -} - -/* Sets an interrupt's edge/level bits in the GICD. */ -void intr_set_edge_level(unsigned int id, int edge_level) { - GICD_ICFGR[id >> 4] = GICD_ICFGR[id >> 4] & ((~(3 << ((id & 0xF) << 1))) | (((edge_level & 1) << 1) << ((id & 0xF) << 1))); -} - -/* Sets an interrupt's enabled status in the GICD. */ -void intr_set_enabled(unsigned int id, int enabled) { - GICD_ISENABLER[id >> 5] = (enabled & 1) << (id & 0x1F); -} - -/* To be called by FIQ handler. */ -void handle_registered_interrupt(void) { - unsigned int interrupt_id = get_interrupt_id(); - if (interrupt_id <= 0xDF) { - bool found_handler = false; - for (unsigned int i = 0; i < MAX_REGISTERED_INTERRUPTS; i++) { - if (g_registered_interrupts[i].id == interrupt_id) { - found_handler = true; - g_registered_interrupts[i].handler(); - /* Mark that interrupt is done. */ - GICC_EOIR = interrupt_id; - break; - } - } - /* We must have found a handler, or something went wrong. */ - if (!found_handler) { - generic_panic(); - } - } -} - -/* Registers an interrupt into the global. */ -void intr_register_handler(unsigned int id, void (*handler)(void)) { - bool registered_handler = false; - for (unsigned int i = 0; i < MAX_REGISTERED_INTERRUPTS; i++) { - if (g_registered_interrupts[i].id == 0) { - g_registered_interrupts[i].handler = handler; - g_registered_interrupts[i].id = id; - registered_handler = true; - break; - } - } - /* Failure to register is an error condition. */ - if (!registered_handler) { - generic_panic(); - } -} - diff --git a/exosphere/src/interrupt.h b/exosphere/src/interrupt.h deleted file mode 100644 index 86cfd2c0a..000000000 --- a/exosphere/src/interrupt.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_INTERRUPT_H -#define EXOSPHERE_INTERRUPT_H - -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 GIC-400 registers. */ - - -#define MAX_REGISTERED_INTERRUPTS 4 -#define INTERRUPT_ID_SECURITY_ENGINE 0x5A -#define INTERRUPT_ID_ACTIVITY_MONITOR_4X 0x4D -#define INTERRUPT_ID_1C 0x1C -#define INTERRUPT_ID_USER_SECURITY_ENGINE 0x2C - -static inline uintptr_t get_gicd_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_GICD); -} - -static inline uintptr_t get_gicc_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_GICC); -} - -#define GICD_BASE (get_gicd_base()) -#define GICC_BASE (get_gicc_base()) - -#define GICD_CTLR MAKE_REG32(GICD_BASE + 0x000ull) -#define GICD_IGROUPR ((volatile uint32_t *)(GICD_BASE + 0x080ull)) -#define GICD_ISENABLER ((volatile uint32_t *)(GICD_BASE + 0x100ull)) -#define GICD_ISPENDR ((volatile uint32_t *)(GICD_BASE + 0x200ull)) -#define GICD_IPRIORITYR ((volatile uint8_t *)(GICD_BASE + 0x400ull)) -#define GICD_ITARGETSR ((volatile uint8_t *)(GICD_BASE + 0x800ull)) -#define GICD_ICFGR ((volatile uint32_t *)(GICD_BASE + 0xC00ull)) - -#define GICC_CTLR MAKE_REG32(GICC_BASE + 0x0000ull) -#define GICC_PMR MAKE_REG32(GICC_BASE + 0x0004ull) -#define GICC_BPR MAKE_REG32(GICC_BASE + 0x0008ull) -#define GICC_IAR MAKE_REG32(GICC_BASE + 0x000CULL) -#define GICC_EOIR MAKE_REG32(GICC_BASE + 0x0010ull) - -#define GIC_PRI_HIGHEST_SECURE 0x00 -#define GIC_PRI_HIGHEST_NONSECURE 0x80 - -#define GIC_GROUP_SECURE 0 -#define GIC_GROUP_NONSECURE 1 - -/* To be called by FIQ handler. */ -void handle_registered_interrupt(void); - -/* Initializes the GIC. This must be called during wakeup. */ -void intr_initialize_gic(void); -void intr_initialize_gic_nonsecure(void); - -void intr_prepare_gicc_for_sleep(void); - - -void intr_register_handler(unsigned int id, void (*handler)(void)); -void intr_set_group(unsigned int id, int group); -void intr_set_pending(unsigned int id); -void intr_set_priority(unsigned int id, uint8_t priority); -void intr_set_cpu_mask(unsigned int id, uint8_t mask); -void intr_set_edge_level(unsigned int id, int edge_level); -void intr_set_enabled(unsigned int id, int enabled); -#endif diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c deleted file mode 100644 index 86692dc69..000000000 --- a/exosphere/src/masterkey.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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 -#include - -#include "utils.h" -#include "configitem.h" -#include "masterkey.h" -#include "se.h" - -static unsigned int g_mkey_revision = 0; -static bool g_determined_mkey_revision = false; - -static uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10]; -static uint8_t g_old_devicekeys[MASTERKEY_NUM_NEW_DEVICE_KEYS - 1][0x10]; - - -/* TODO: Extend with new vectors, as needed. */ -/* Dev unit keys. */ -static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = -{ - {0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE}, /* Zeroes encrypted with Master Key 00. */ - {0x39, 0x33, 0xF9, 0x31, 0xBA, 0xE4, 0xA7, 0x21, 0x2C, 0xDD, 0xB7, 0xD8, 0xB4, 0x4E, 0x37, 0x23}, /* Master key 00 encrypted with Master key 01. */ - {0x97, 0x29, 0xB0, 0x32, 0x43, 0x14, 0x8C, 0xA6, 0x85, 0xE9, 0x5A, 0x94, 0x99, 0x39, 0xAC, 0x5D}, /* Master key 01 encrypted with Master key 02. */ - {0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */ - {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ - {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ - {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ - {0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */ - {0xEC, 0xE1, 0x46, 0x89, 0x37, 0xFD, 0xD2, 0x15, 0x8C, 0x3F, 0x24, 0x82, 0xEF, 0x49, 0x68, 0x04}, /* Master key 07 encrypted with Master key 08. */ - {0x43, 0x3D, 0xC5, 0x3B, 0xEF, 0x91, 0x02, 0x21, 0x61, 0x54, 0x63, 0x8A, 0x35, 0xE7, 0xCA, 0xEE}, /* Master key 08 encrypted with Master key 09. */ - {0x6C, 0x2E, 0xCD, 0xB3, 0x34, 0x61, 0x77, 0xF5, 0xF9, 0xB1, 0xDD, 0x61, 0x98, 0x19, 0x3E, 0xD4}, /* Master key 09 encrypted with Master key 0A. */ -}; - -/* Retail unit keys. */ -static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = -{ - {0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D}, /* Zeroes encrypted with Master Key 00. */ - {0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD}, /* Master key 00 encrypted with Master key 01. */ - {0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */ - {0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */ - {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ - {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ - {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ - {0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */ - {0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29}, /* Master key 07 encrypted with Master key 08. */ - {0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80}, /* Master key 08 encrypted with Master key 09. */ - {0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A}, /* Master key 09 encrypted with Master key 0A. */ -}; - -bool check_mkey_revision(unsigned int revision, bool is_retail) { - uint8_t final_vector[0x10]; - - unsigned int check_keyslot = KEYSLOT_SWITCH_MASTERKEY; - if (revision > 0) { - /* Generate old master key array. */ - for (unsigned int i = revision; i > 0; i--) { - se_aes_ecb_decrypt_block(check_keyslot, g_old_masterkeys[i-1], 0x10, is_retail ? mkey_vectors[i] : mkey_vectors_dev[i], 0x10); - set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_masterkeys[i-1], 0x10); - check_keyslot = KEYSLOT_SWITCH_TEMPKEY; - } - } - - se_aes_ecb_decrypt_block(check_keyslot, final_vector, 0x10, is_retail ? mkey_vectors[0] : mkey_vectors_dev[0], 0x10); - for (unsigned int i = 0; i < 0x10; i++) { - if (final_vector[i] != 0) { - return false; - } - } - return true; -} - -void mkey_detect_revision(void) { - if (g_determined_mkey_revision) { - generic_panic(); - } - - for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) { - if (check_mkey_revision(rev, configitem_is_retail())) { - g_determined_mkey_revision = true; - g_mkey_revision = rev; - break; - } - } - - /* We must have determined the master key, or we're not running on a Switch. */ - if (!g_determined_mkey_revision) { - /* Panic in bright red. */ - panic(0x00F00060); - } -} - -unsigned int mkey_get_revision(void) { - if (!g_determined_mkey_revision) { - generic_panic(); - } - - return g_mkey_revision; -} - -unsigned int mkey_get_keyslot(unsigned int revision) { - if (!g_determined_mkey_revision || revision >= MASTERKEY_REVISION_MAX) { - generic_panic(); - } - - if (revision > g_mkey_revision) { - generic_panic(); - } - - if (revision == g_mkey_revision) { - return KEYSLOT_SWITCH_MASTERKEY; - } else { - /* Load into a temp keyslot. */ - set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_masterkeys[revision], 0x10); - return KEYSLOT_SWITCH_TEMPKEY; - } -} - -void set_old_devkey(unsigned int revision, const uint8_t *key) { - if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_MAX <= revision) { - generic_panic(); - } - - memcpy(g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], key, 0x10); -} - -unsigned int devkey_get_keyslot(unsigned int revision) { - if (!g_determined_mkey_revision || revision > g_mkey_revision) { - generic_panic(); - } - - if (revision < MASTERKEY_REVISION_400_410) { - return KEYSLOT_SWITCH_4XOLDDEVICEKEY; - } else if (revision < g_mkey_revision) { - /* Load into a temp keyslot. */ - set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], 0x10); - return KEYSLOT_SWITCH_TEMPKEY; - } else { - return KEYSLOT_SWITCH_DEVICEKEY; - } -} diff --git a/exosphere/src/masterkey.h b/exosphere/src/masterkey.h deleted file mode 100644 index 93a03c760..000000000 --- a/exosphere/src/masterkey.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_MASTERKEY_H -#define EXOSPHERE_MASTERKEY_H - -/* This is glue code to enable master key support across versions. */ - -/* TODO: Update to 0xC on release of new master key. */ -#define MASTERKEY_REVISION_MAX 0xB - -#define MASTERKEY_REVISION_100_230 0x00 -#define MASTERKEY_REVISION_300 0x01 -#define MASTERKEY_REVISION_301_302 0x02 -#define MASTERKEY_REVISION_400_410 0x03 -#define MASTERKEY_REVISION_500_510 0x04 -#define MASTERKEY_REVISION_600_610 0x05 -#define MASTERKEY_REVISION_620 0x06 -#define MASTERKEY_REVISION_700_800 0x07 -#define MASTERKEY_REVISION_810 0x08 -#define MASTERKEY_REVISION_900 0x09 -#define MASTERKEY_REVISION_910_CURRENT 0x0A - -#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) - -/* This should be called early on in initialization. */ -void mkey_detect_revision(void); - -unsigned int mkey_get_revision(void); - -unsigned int mkey_get_keyslot(unsigned int revision); - -void set_old_devkey(unsigned int revision, const uint8_t *key); -unsigned int devkey_get_keyslot(unsigned int revision); - -#endif \ No newline at end of file diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c deleted file mode 100644 index 41e999124..000000000 --- a/exosphere/src/mc.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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 "memory_map.h" -#include "mc.h" -#include "exocfg.h" - -typedef struct { - uint64_t address; - uint64_t size; -} saved_carveout_info_t; - -static saved_carveout_info_t g_saved_carveouts[2] = { - {0x80060000ull, KERNEL_CARVEOUT_SIZE_MAX}, - {0x00000000ull, 0x00000000ull} -}; - -volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) { - if (CARVEOUT_ID_MIN <= carveout && carveout <= CARVEOUT_ID_MAX) { - return (volatile security_carveout_t *)(MC_BASE + 0xC08ull + 0x50 * (carveout - CARVEOUT_ID_MIN)); - } - generic_panic(); - return NULL; -} - -void configure_gpu_ucode_carveout(void) { - /* Starting in 6.0.0, Carveout 2 is configured later on and adds read permission to TSEC. */ - /* This is a helper function to make this easier... */ - volatile security_carveout_t *carveout = get_carveout_by_id(2); - carveout->paddr_low = 0x80020000; - carveout->paddr_high = 0; - carveout->size_big_pages = 2; /* 0x40000 */ - carveout->client_access_0 = 0; - carveout->client_access_1 = 0; - carveout->client_access_2 = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); - carveout->client_access_3 = 0; - carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); - carveout->client_force_internal_access_0 = 0; - carveout->client_force_internal_access_1 = 0; - carveout->client_force_internal_access_2 = 0; - carveout->client_force_internal_access_3 = 0; - carveout->client_force_internal_access_4 = 0; - carveout->config = 0x440167E; -} - -void configure_default_carveouts(void) { - /* Configure Carveout 1 (UNUSED) */ - volatile security_carveout_t *carveout = get_carveout_by_id(1); - carveout->paddr_low = 0; - carveout->paddr_high = 0; - carveout->size_big_pages = 0; - carveout->client_access_0 = 0; - carveout->client_access_1 = 0; - carveout->client_access_2 = 0; - carveout->client_access_3 = 0; - carveout->client_access_4 = 0; - carveout->client_force_internal_access_0 = 0; - carveout->client_force_internal_access_1 = 0; - carveout->client_force_internal_access_2 = 0; - carveout->client_force_internal_access_3 = 0; - carveout->client_force_internal_access_4 = 0; - carveout->config = 0x4000006; - - /* Configure Carveout 2 (GPU UCODE) */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - configure_gpu_ucode_carveout(); - } - - /* Configure Carveout 3 (UNUSED GPU) */ - carveout = get_carveout_by_id(3); - carveout->paddr_low = 0; - carveout->paddr_high = 0; - carveout->size_big_pages = 0; - carveout->client_access_0 = 0; - carveout->client_access_1 = 0; - carveout->client_access_2 = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); - carveout->client_access_3 = 0; - carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); - carveout->client_force_internal_access_0 = 0; - carveout->client_force_internal_access_1 = 0; - carveout->client_force_internal_access_2 = 0; - carveout->client_force_internal_access_3 = 0; - carveout->client_force_internal_access_4 = 0; - carveout->config = 0x4401E7E; - - /* Configure default Kernel carveouts based on 2.0.0+. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - /* Configure Carveout 4 (KERNEL_BUILTINS) */ - configure_kernel_carveout(4, g_saved_carveouts[0].address, g_saved_carveouts[0].size); - - /* Configure Carveout 5 (KERNEL_UNUSED) */ - configure_kernel_carveout(5, g_saved_carveouts[1].address, g_saved_carveouts[1].size); - } else { - for (unsigned int i = 4; i <= 5; i++) { - carveout = get_carveout_by_id(i); - carveout->paddr_low = 0; - carveout->paddr_high = 0; - carveout->size_big_pages = 0; - carveout->client_access_0 = 0; - carveout->client_access_1 = 0; - carveout->client_access_2 = 0; - carveout->client_access_3 = 0; - carveout->client_access_4 = 0; - carveout->client_force_internal_access_0 = 0; - carveout->client_force_internal_access_1 = 0; - carveout->client_force_internal_access_2 = 0; - carveout->client_force_internal_access_3 = 0; - carveout->client_force_internal_access_4 = 0; - carveout->config = 0x4000006; - } - } -} - -void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size) { - if (carveout_id != 4 && carveout_id != 5) { - generic_panic(); - } - - g_saved_carveouts[carveout_id-4].address = address; - g_saved_carveouts[carveout_id-4].size = size; - - volatile security_carveout_t *carveout = get_carveout_by_id(carveout_id); - carveout->paddr_low = (uint32_t)(address & 0xFFFFFFFF); - carveout->paddr_high = (uint32_t)(address >> 32); - carveout->size_big_pages = (uint32_t)(size >> 17); - carveout->client_access_0 = (BIT(CSR_PTCR) | BIT(CSR_DISPLAY0A) | BIT(CSR_DISPLAY0AB) | BIT(CSR_DISPLAY0B) | BIT(CSR_DISPLAY0BB) | BIT(CSR_DISPLAY0C) | BIT(CSR_DISPLAY0CB) | BIT(CSR_AFIR) | BIT(CSR_DISPLAYHC) | BIT(CSR_DISPLAYHCB) | BIT(CSR_HDAR) | BIT(CSR_HOST1XDMAR) | BIT(CSR_HOST1XR) | BIT(CSR_NVENCSRD) | BIT(CSR_PPCSAHBDMAR) | BIT(CSR_PPCSAHBSLVR)); - carveout->client_access_1 = (BIT(CSR_MPCORER) | BIT(CSW_NVENCSWR) | BIT(CSW_AFIW) | BIT(CSW_HDAW) | BIT(CSW_HOST1XW) | BIT(CSW_MPCOREW) | BIT(CSW_PPCSAHBDMAW) | BIT(CSW_PPCSAHBSLVW)); - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) { - carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW)); - carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); - carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR)); - } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0) { - carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW)); - carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); - carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR) | BIT(CSR_TSECSRDB) | BIT(CSW_TSECSWRB)); - } else { - carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW) | BIT(CSR_TSECSRD) | BIT(CSW_TSECSWR)); - carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); - carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR)); - } - carveout->client_force_internal_access_0 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) && (carveout_id == 4)) ? BIT(CSR_AVPCARM7R) : 0; - carveout->client_force_internal_access_1 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0; - carveout->client_force_internal_access_2 = 0; - carveout->client_force_internal_access_3 = 0; - carveout->client_force_internal_access_4 = 0; - carveout->config = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0) ? 0x4CB : 0x8B; -} diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h deleted file mode 100644 index 9d4c5f78d..000000000 --- a/exosphere/src/mc.h +++ /dev/null @@ -1,631 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_MC_H -#define EXOSPHERE_MC_H - -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 Memory Controller. */ - -static inline uintptr_t get_mc_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC); -} - -#define MC_BASE (get_mc_base()) -#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) - -#define MC_INTSTATUS 0x0 -#define MC_INTMASK 0x4 -#define MC_ERR_STATUS 0x8 -#define MC_ERR_ADR 0xc -#define MC_SMMU_CONFIG 0x10 -#define MC_SMMU_TLB_CONFIG 0x14 -#define MC_SMMU_PTC_CONFIG 0x18 -#define MC_SMMU_PTB_ASID 0x1c -#define MC_SMMU_PTB_DATA 0x20 -#define MC_SMMU_TLB_FLUSH 0x30 -#define MC_SMMU_PTC_FLUSH 0x34 -#define MC_SMMU_ASID_SECURITY 0x38 -#define MC_SMMU_ASID_SECURITY_1 0x3c -#define MC_SMMU_ASID_SECURITY_2 0x9e0 -#define MC_SMMU_ASID_SECURITY_3 0x9e4 -#define MC_SMMU_ASID_SECURITY_4 0x9e8 -#define MC_SMMU_ASID_SECURITY_5 0x9ec -#define MC_SMMU_ASID_SECURITY_6 0x9f0 -#define MC_SMMU_ASID_SECURITY_7 0x9f4 -#define MC_SMMU_AFI_ASID 0x238 -#define MC_SMMU_AVPC_ASID 0x23c -#define MC_SMMU_PPCS1_ASID 0x298 -#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 -#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c -#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 -#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 -#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 -#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 -#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 -#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 -#define MC_PCFIFO_CLIENT_CONFIG3 0xddc -#define MC_PCFIFO_CLIENT_CONFIG4 0xde0 -#define MC_EMEM_CFG 0x50 -#define MC_EMEM_ADR_CFG 0x54 -#define MC_EMEM_ADR_CFG_DEV0 0x58 -#define MC_EMEM_ADR_CFG_DEV1 0x5c -#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60 -#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64 -#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68 -#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c -#define MC_SECURITY_CFG0 0x70 -#define MC_SECURITY_CFG1 0x74 -#define MC_SECURITY_CFG3 0x9bc -#define MC_SECURITY_RSV 0x7c -#define MC_EMEM_ARB_CFG 0x90 -#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 -#define MC_EMEM_ARB_TIMING_RCD 0x98 -#define MC_EMEM_ARB_TIMING_RP 0x9c -#define MC_EMEM_ARB_TIMING_RC 0xa0 -#define MC_EMEM_ARB_TIMING_RAS 0xa4 -#define MC_EMEM_ARB_TIMING_FAW 0xa8 -#define MC_EMEM_ARB_TIMING_RRD 0xac -#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 -#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 -#define MC_EMEM_ARB_TIMING_R2R 0xb8 -#define MC_EMEM_ARB_TIMING_W2W 0xbc -#define MC_EMEM_ARB_TIMING_R2W 0xc0 -#define MC_EMEM_ARB_TIMING_W2R 0xc4 -#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0 -#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4 -#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0 -#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4 -#define MC_EMEM_ARB_DA_TURNS 0xd0 -#define MC_EMEM_ARB_DA_COVERS 0xd4 -#define MC_EMEM_ARB_MISC0 0xd8 -#define MC_EMEM_ARB_MISC1 0xdc -#define MC_EMEM_ARB_MISC2 0xc8 -#define MC_EMEM_ARB_RING1_THROTTLE 0xe0 -#define MC_EMEM_ARB_RING3_THROTTLE 0xe4 -#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0 -#define MC_EMEM_ARB_OVERRIDE 0xe8 -#define MC_EMEM_ARB_RSV 0xec -#define MC_CLKEN_OVERRIDE 0xf4 -#define MC_TIMING_CONTROL_DBG 0xf8 -#define MC_TIMING_CONTROL 0xfc -#define MC_STAT_CONTROL 0x100 -#define MC_STAT_STATUS 0x104 -#define MC_STAT_EMC_CLOCK_LIMIT 0x108 -#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c -#define MC_STAT_EMC_CLOCKS 0x110 -#define MC_STAT_EMC_CLOCKS_MSBS 0x114 -#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118 -#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158 -#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c -#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c -#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20 -#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24 -#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198 -#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8 -#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c -#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac -#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28 -#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c -#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0 -#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0 -#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120 -#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c -#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c -#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134 -#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174 -#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c -#define MC_STAT_EMC_SET0_COUNT 0x138 -#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c -#define MC_STAT_EMC_SET1_COUNT 0x178 -#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c -#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140 -#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144 -#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180 -#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184 -#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148 -#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c -#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188 -#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c -#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150 -#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190 -#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8 -#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc -#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8 -#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc -#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0 -#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0 -#define MC_CLIENT_HOTRESET_CTRL 0x200 -#define MC_CLIENT_HOTRESET_CTRL_1 0x970 -#define MC_CLIENT_HOTRESET_STATUS 0x204 -#define MC_CLIENT_HOTRESET_STATUS_1 0x974 -#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208 -#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c -#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210 -#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214 -#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94 -#define MC_EMEM_ARB_HYSTERESIS_0 0x218 -#define MC_EMEM_ARB_HYSTERESIS_1 0x21c -#define MC_EMEM_ARB_HYSTERESIS_2 0x220 -#define MC_EMEM_ARB_HYSTERESIS_3 0x224 -#define MC_EMEM_ARB_HYSTERESIS_4 0xb84 -#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0 -#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4 -#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8 -#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc -#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0 -#define MC_EMEM_ARB_DHYST_CTRL 0xbcc -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8 -#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec -#define MC_RESERVED_RSV 0x3fc -#define MC_DISB_EXTRA_SNAP_LEVELS 0x408 -#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4 -#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0 -#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18 -#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08 -#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10 -#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c -#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40 -#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414 -#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc -#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c -#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14 -#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0 -#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac -#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c -#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48 -#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8 -#define MC_USBX_EXTRA_SNAP_LEVELS 0x404 -#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8 -#define MC_SD_EXTRA_SNAP_LEVELS 0xa04 -#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c -#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8 -#define MC_GK_EXTRA_SNAP_LEVELS 0xa00 -#define MC_VE2_EXTRA_SNAP_LEVELS 0x410 -#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44 -#define MC_VIDEO_PROTECT_BOM 0x648 -#define MC_VIDEO_PROTECT_SIZE_MB 0x64c -#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978 -#define MC_VIDEO_PROTECT_REG_CTRL 0x650 -#define MC_ERR_VPR_STATUS 0x654 -#define MC_ERR_VPR_ADR 0x658 -#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418 -#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590 -#define MC_IRAM_BOM 0x65c -#define MC_IRAM_TOM 0x660 -#define MC_IRAM_ADR_HI 0x980 -#define MC_IRAM_REG_CTRL 0x964 -#define MC_EMEM_CFG_ACCESS_CTRL 0x664 -#define MC_TZ_SECURITY_CTRL 0x668 -#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c -#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4 -#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc -#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8 -#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80 -#define MC_SEC_CARVEOUT_BOM 0x670 -#define MC_SEC_CARVEOUT_SIZE_MB 0x674 -#define MC_SEC_CARVEOUT_ADR_HI 0x9d4 -#define MC_SEC_CARVEOUT_REG_CTRL 0x678 -#define MC_ERR_SEC_STATUS 0x67c -#define MC_ERR_SEC_ADR 0x680 -#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684 -#define MC_STUTTER_CONTROL 0x688 -#define MC_RESERVED_RSV_1 0x958 -#define MC_DVFS_PIPE_SELECT 0x95c -#define MC_AHB_PTSA_MIN 0x4e0 -#define MC_AUD_PTSA_MIN 0x54c -#define MC_MLL_MPCORER_PTSA_RATE 0x44c -#define MC_RING2_PTSA_RATE 0x440 -#define MC_USBD_PTSA_RATE 0x530 -#define MC_USBX_PTSA_MIN 0x528 -#define MC_USBD_PTSA_MIN 0x534 -#define MC_APB_PTSA_MAX 0x4f0 -#define MC_JPG_PTSA_RATE 0x584 -#define MC_DIS_PTSA_MIN 0x420 -#define MC_AVP_PTSA_MAX 0x4fc -#define MC_AVP_PTSA_RATE 0x4f4 -#define MC_RING1_PTSA_MIN 0x480 -#define MC_DIS_PTSA_MAX 0x424 -#define MC_SD_PTSA_MAX 0x4d8 -#define MC_MSE_PTSA_RATE 0x4c4 -#define MC_VICPC_PTSA_MIN 0x558 -#define MC_PCX_PTSA_MAX 0x4b4 -#define MC_ISP_PTSA_RATE 0x4a0 -#define MC_A9AVPPC_PTSA_MIN 0x48c -#define MC_RING2_PTSA_MAX 0x448 -#define MC_AUD_PTSA_RATE 0x548 -#define MC_HOST_PTSA_MIN 0x51c -#define MC_MLL_MPCORER_PTSA_MAX 0x454 -#define MC_SD_PTSA_MIN 0x4d4 -#define MC_RING1_PTSA_RATE 0x47c -#define MC_JPG_PTSA_MIN 0x588 -#define MC_HDAPC_PTSA_MIN 0x62c -#define MC_AVP_PTSA_MIN 0x4f8 -#define MC_JPG_PTSA_MAX 0x58c -#define MC_VE_PTSA_MAX 0x43c -#define MC_DFD_PTSA_MAX 0x63c -#define MC_VICPC_PTSA_RATE 0x554 -#define MC_GK_PTSA_MAX 0x544 -#define MC_VICPC_PTSA_MAX 0x55c -#define MC_SDM_PTSA_MAX 0x624 -#define MC_SAX_PTSA_RATE 0x4b8 -#define MC_PCX_PTSA_MIN 0x4b0 -#define MC_APB_PTSA_MIN 0x4ec -#define MC_GK2_PTSA_MIN 0x614 -#define MC_PCX_PTSA_RATE 0x4ac -#define MC_RING1_PTSA_MAX 0x484 -#define MC_HDAPC_PTSA_RATE 0x628 -#define MC_MLL_MPCORER_PTSA_MIN 0x450 -#define MC_GK2_PTSA_MAX 0x618 -#define MC_AUD_PTSA_MAX 0x550 -#define MC_GK2_PTSA_RATE 0x610 -#define MC_ISP_PTSA_MAX 0x4a8 -#define MC_DISB_PTSA_RATE 0x428 -#define MC_VE2_PTSA_MAX 0x49c -#define MC_DFD_PTSA_MIN 0x638 -#define MC_FTOP_PTSA_RATE 0x50c -#define MC_A9AVPPC_PTSA_RATE 0x488 -#define MC_VE2_PTSA_MIN 0x498 -#define MC_USBX_PTSA_MAX 0x52c -#define MC_DIS_PTSA_RATE 0x41c -#define MC_USBD_PTSA_MAX 0x538 -#define MC_A9AVPPC_PTSA_MAX 0x490 -#define MC_USBX_PTSA_RATE 0x524 -#define MC_FTOP_PTSA_MAX 0x514 -#define MC_HDAPC_PTSA_MAX 0x630 -#define MC_SD_PTSA_RATE 0x4d0 -#define MC_DFD_PTSA_RATE 0x634 -#define MC_FTOP_PTSA_MIN 0x510 -#define MC_SDM_PTSA_RATE 0x61c -#define MC_AHB_PTSA_RATE 0x4dc -#define MC_SMMU_SMMU_PTSA_MAX 0x460 -#define MC_RING2_PTSA_MIN 0x444 -#define MC_SDM_PTSA_MIN 0x620 -#define MC_APB_PTSA_RATE 0x4e8 -#define MC_MSE_PTSA_MIN 0x4c8 -#define MC_HOST_PTSA_RATE 0x518 -#define MC_VE_PTSA_RATE 0x434 -#define MC_AHB_PTSA_MAX 0x4e4 -#define MC_SAX_PTSA_MIN 0x4bc -#define MC_SMMU_SMMU_PTSA_MIN 0x45c -#define MC_ISP_PTSA_MIN 0x4a4 -#define MC_HOST_PTSA_MAX 0x520 -#define MC_SAX_PTSA_MAX 0x4c0 -#define MC_VE_PTSA_MIN 0x438 -#define MC_GK_PTSA_MIN 0x540 -#define MC_MSE_PTSA_MAX 0x4cc -#define MC_DISB_PTSA_MAX 0x430 -#define MC_DISB_PTSA_MIN 0x42c -#define MC_SMMU_SMMU_PTSA_RATE 0x458 -#define MC_VE2_PTSA_RATE 0x494 -#define MC_GK_PTSA_RATE 0x53c -#define MC_PTSA_GRANT_DECREMENT 0x960 -#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4 -#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0 -#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380 -#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384 -#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc -#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8 -#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370 -#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0 -#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374 -#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 -#define MC_LATENCY_ALLOWANCE_VIC_0 0x394 -#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 -#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8 -#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc -#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390 -#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694 -#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 -#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c -#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 -#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0 -#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698 -#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec -#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0 -#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4 -#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8 -#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 -#define MC_LATENCY_ALLOWANCE_HC_1 0x314 -#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0 -#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4 -#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c -#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec -#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320 -#define MC_LATENCY_ALLOWANCE_VI2_0 0x398 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4 -#define MC_LATENCY_ALLOWANCE_SATA_0 0x350 -#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690 -#define MC_LATENCY_ALLOWANCE_HC_0 0x310 -#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8 -#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac -#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4 -#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388 -#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328 -#define MC_LATENCY_ALLOWANCE_HDA_0 0x318 -#define MC_MIN_LENGTH_APE_0 0xb34 -#define MC_MIN_LENGTH_DCB_2 0x8a8 -#define MC_MIN_LENGTH_A9AVP_0 0x950 -#define MC_MIN_LENGTH_TSEC_0 0x93c -#define MC_MIN_LENGTH_DC_1 0x898 -#define MC_MIN_LENGTH_AXIAP_0 0x94c -#define MC_MIN_LENGTH_ISP2B_0 0x930 -#define MC_MIN_LENGTH_VI2_0 0x944 -#define MC_MIN_LENGTH_DCB_0 0x8a0 -#define MC_MIN_LENGTH_DCB_1 0x8a4 -#define MC_MIN_LENGTH_PPCS_1 0x8f4 -#define MC_MIN_LENGTH_NVJPG_0 0xb3c -#define MC_MIN_LENGTH_HDA_0 0x8c4 -#define MC_MIN_LENGTH_NVENC_0 0x8d4 -#define MC_MIN_LENGTH_SDMMC_0 0xb18 -#define MC_MIN_LENGTH_ISP2B_1 0x934 -#define MC_MIN_LENGTH_HC_1 0x8c0 -#define MC_MIN_LENGTH_DC_3 0xb20 -#define MC_MIN_LENGTH_AVPC_0 0x890 -#define MC_MIN_LENGTH_VIC_0 0x940 -#define MC_MIN_LENGTH_ISP2_0 0x91c -#define MC_MIN_LENGTH_HC_0 0x8bc -#define MC_MIN_LENGTH_SE_0 0xb38 -#define MC_MIN_LENGTH_NVDEC_0 0xb30 -#define MC_MIN_LENGTH_SATA_0 0x8fc -#define MC_MIN_LENGTH_DC_0 0x894 -#define MC_MIN_LENGTH_XUSB_1 0x92c -#define MC_MIN_LENGTH_DC_2 0x89c -#define MC_MIN_LENGTH_SDMMCAA_0 0xb14 -#define MC_MIN_LENGTH_GPU_0 0xb04 -#define MC_MIN_LENGTH_ETR_0 0xb44 -#define MC_MIN_LENGTH_AFI_0 0x88c -#define MC_MIN_LENGTH_PPCS_0 0x8f0 -#define MC_MIN_LENGTH_ISP2_1 0x920 -#define MC_MIN_LENGTH_XUSB_0 0x928 -#define MC_MIN_LENGTH_MPCORE_0 0x8cc -#define MC_MIN_LENGTH_TSECB_0 0xb48 -#define MC_MIN_LENGTH_SDMMCA_0 0xb10 -#define MC_MIN_LENGTH_GPU2_0 0xb40 -#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c -#define MC_MIN_LENGTH_PTC_0 0x8f8 -#define MC_EMEM_ARB_OVERRIDE_1 0x968 -#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984 -#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988 -#define MC_EMEM_ARB_STATS_0 0x990 -#define MC_EMEM_ARB_STATS_1 0x994 -#define MC_MTS_CARVEOUT_BOM 0x9a0 -#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4 -#define MC_MTS_CARVEOUT_ADR_HI 0x9a8 -#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac -#define MC_ERR_MTS_STATUS 0x9b0 -#define MC_ERR_MTS_ADR 0x9b4 -#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 -#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74 -#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8 -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10 -#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04 -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c -#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4 -#define MC_SECURITY_CARVEOUT2_CFG0 0xc58 -#define MC_SECURITY_CARVEOUT1_CFG0 0xc08 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84 -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68 -#define MC_SECURITY_CARVEOUT3_BOM 0xcac -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70 -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60 -#define MC_SECURITY_CARVEOUT3_CFG0 0xca8 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8 -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88 -#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64 -#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50 -#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14 -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14 -#define MC_SECURITY_CARVEOUT1_BOM 0xc0c -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58 -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24 -#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4 -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78 -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18 -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c -#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8 -#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60 -#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00 -#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc -#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80 -#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54 -#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4 -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74 -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc -#define MC_SECURITY_CARVEOUT4_BOM 0xcfc -#define MC_SECURITY_CARVEOUT5_CFG0 0xd48 -#define MC_SECURITY_CARVEOUT2_BOM 0xc5c -#define MC_SECURITY_CARVEOUT5_BOM 0xd4c -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24 -#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c -#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0 -#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10 -#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20 -#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c -#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c -#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08 -#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 -#define MC_DA_CONFIG0 0x9dc - -/* Virtual aliases */ -#define VIRT_MC_SECURITY_CFG3 MAKE_MC_REG(MC_SECURITY_CFG3) - -/* Memory Controller clients */ -#define CLIENT_ACCESS_NUM_CLIENTS 32 -typedef enum { - /* _ACCESS0 */ - CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), - - /* _ACCESS1 */ - CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), - - /* _ACCESS2 */ - CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), - - /* _ACCESS3 */ - CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), - - /* _ACCESS4 */ - CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), - CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) -} McClient; - -/* Memory Controller carveouts */ -#define CARVEOUT_ID_MIN 1 -#define CARVEOUT_ID_MAX 5 -#define KERNEL_CARVEOUT_SIZE_MAX 0x1FFE0000 -typedef struct { - uint32_t config; - uint32_t paddr_low; - uint32_t paddr_high; - uint32_t size_big_pages; - uint32_t client_access_0; - uint32_t client_access_1; - uint32_t client_access_2; - uint32_t client_access_3; - uint32_t client_access_4; - uint32_t client_force_internal_access_0; - uint32_t client_force_internal_access_1; - uint32_t client_force_internal_access_2; - uint32_t client_force_internal_access_3; - uint32_t client_force_internal_access_4; - uint8_t padding[0x18]; -} security_carveout_t; - -volatile security_carveout_t *get_carveout_by_id(unsigned int carveout); -void configure_default_carveouts(void); -void configure_gpu_ucode_carveout(void); -void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size); - -#endif \ No newline at end of file diff --git a/exosphere/src/mc0.h b/exosphere/src/mc0.h deleted file mode 100644 index 8e4f51848..000000000 --- a/exosphere/src/mc0.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_MC0_H -#define EXOSPHERE_MC0_H - -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 MC0. */ - -static inline uintptr_t get_mc0_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC0); -} - -#define MC0_BASE (get_mc0_base()) -#define MAKE_MC0_REG(n) MAKE_REG32(MC0_BASE + n) - -#endif diff --git a/exosphere/src/mc1.h b/exosphere/src/mc1.h deleted file mode 100644 index bcdfe03be..000000000 --- a/exosphere/src/mc1.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_MC0_H -#define EXOSPHERE_MC0_H - -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 MC1. */ - -static inline uintptr_t get_mc1_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC1); -} - -#define MC1_BASE (get_mc1_base()) -#define MAKE_MC1_REG(n) MAKE_REG32(MC1_BASE + n) - -#endif diff --git a/exosphere/src/memory_map.h b/exosphere/src/memory_map.h deleted file mode 100644 index aca65bf69..000000000 --- a/exosphere/src/memory_map.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_MEMORY_MAP_H -#define EXOSPHERE_MEMORY_MAP_H - -#include "mmu.h" -#include "preprocessor.h" - -#define ATTRIB_MEMTYPE_NORMAL MMU_PTE_BLOCK_MEMTYPE(MMU_MT_NORMAL) -#define ATTRIB_MEMTYPE_DEVICE MMU_PTE_BLOCK_MEMTYPE(MMU_MT_DEVICE_NGNRE) - -/* Identity mappings (addr, size, additional attributes, is block range) */ -#define _MMAPID0 ( 0x40006000ull, 0x01000ull, 0ull, false ) /* Part of iRAM-A, where our coldboot crt0 is */ -#define _MMAPID1 ( 0x40020000ull, 0x20000ull, 0ull, false ) /* iRAM-C+D */ -#define _MMAPID2 ( 0x7C010000ull, 0x10000ull, 0ull, false ) /* TZRAM (contains the secmon's warmboot crt0) */ -#define _MMAPID3 ( 0x80000000ull, 4ull << 30, MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_NS, true ) /* DRAM (4GB) */ - -/* MMIO (addr, size, is secure) */ -#define _MMAPDEV0 ( 0x50041000ull, 0x1000ull, true ) /* ARM Interrupt Distributor */ -#define _MMAPDEV1 ( 0x50042000ull, 0x2000ull, true ) /* Interrupt Controller Physical CPU interface */ -#define _MMAPDEV2 ( 0x70006000ull, 0x1000ull, false ) /* UART */ -#define _MMAPDEV3 ( 0x60006000ull, 0x1000ull, false ) /* Clock and Reset */ -#define _MMAPDEV4 ( 0x7000E000ull, 0x1000ull, true ) /* RTC, PMC */ -#define _MMAPDEV5 ( 0x60005000ull, 0x1000ull, true ) /* TMRs, WDTs */ -#define _MMAPDEV6 ( 0x6000C000ull, 0x1000ull, true ) /* System Registers */ -#define _MMAPDEV7 ( 0x70012000ull, 0x2000ull, true ) /* SE */ -#define _MMAPDEV8 ( 0x700F0000ull, 0x1000ull, true ) /* SYSCTR0 */ -#define _MMAPDEV9 ( 0x70019000ull, 0x1000ull, true ) /* MC */ -#define _MMAPDEV10 ( 0x7000F000ull, 0x1000ull, true ) /* FUSE (0x7000F800) */ -#define _MMAPDEV11 ( 0x70000000ull, 0x4000ull, true ) /* MISC */ -#define _MMAPDEV12 ( 0x60007000ull, 0x1000ull, true ) /* Flow Controller */ -#define _MMAPDEV13 ( 0x40002000ull, 0x1000ull, true ) /* NX bootloader mailbox page */ -#define _MMAPDEV14 ( 0x7000D000ull, 0x1000ull, true ) /* I2C-5,6 - SPI 2B-1 to 4 */ -#define _MMAPDEV15 ( 0x6000D000ull, 0x1000ull, true ) /* GPIO-1 - GPIO-8 */ -#define _MMAPDEV16 ( 0x7000C000ull, 0x1000ull, true ) /* I2C-I2C4 */ -#define _MMAPDEV17 ( 0x6000F000ull, 0x1000ull, true ) /* Exception vectors */ -#define _MMAPDEV18 ( 0x7001C000ull, 0x1000ull, true ) /* MC0 */ -#define _MMAPDEV19 ( 0x7001D000ull, 0x1000ull, true ) /* MC1 */ -#define _MMAPDEV20 ( 0x00000000ull, 0x1000ull, true ) /* AMS irampage, NOT mapped at startup */ -#define _MMAPDEV21 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */ -#define _MMAPDEV22 ( 0x40038000ull, 0x1000ull, true ) /* DEBUG: IRAM */ - -/* MMIO 7.0.0+. (addr). */ -#define _MMAPDEV7X0 ( 0x50041000ull ) /* ARM Interrupt Distributor */ -#define _MMAPDEV7X1 ( 0x50042000ull ) /* Interrupt Controller Physical CPU interface */ -#define _MMAPDEV7X2 ( 0x70006000ull ) /* UART */ -#define _MMAPDEV7X3 ( 0x60006000ull ) /* Clock and Reset */ -#define _MMAPDEV7X4 ( 0x7000E000ull ) /* RTC, PMC */ -#define _MMAPDEV7X5 ( 0x60005000ull ) /* TMRs, WDTs */ -#define _MMAPDEV7X6 ( 0x6000C000ull ) /* System Registers */ -#define _MMAPDEV7X7 ( 0x70012000ull ) /* SE */ -#define _MMAPDEV7X8 ( 0x700F0000ull ) /* SYSCTR0 */ -#define _MMAPDEV7X9 ( 0x70019000ull ) /* MC */ -#define _MMAPDEV7X10 ( 0x7000F000ull ) /* FUSE (0x7000F800) */ -#define _MMAPDEV7X11 ( 0x70000000ull ) /* MISC */ -#define _MMAPDEV7X12 ( 0x60007000ull ) /* Flow Controller */ -#define _MMAPDEV7X13 ( 0x40000000ull ) /* NX bootloader mailbox page */ -#define _MMAPDEV7X14 ( 0x7000D000ull ) /* I2C-5,6 - SPI 2B-1 to 4 */ -#define _MMAPDEV7X15 ( 0x6000D000ull ) /* GPIO-1 - GPIO-8 */ -#define _MMAPDEV7X16 ( 0x7000C000ull ) /* I2C-I2C4 */ -#define _MMAPDEV7X17 ( 0x6000F000ull ) /* Exception vectors */ -#define _MMAPDEV7X18 ( 0x7001C000ull ) /* MC0 */ -#define _MMAPDEV7X19 ( 0x7001D000ull ) /* MC1 */ -#define _MMAPDEV7X20 ( 0x00000000ull ) /* AMS irampage, NOT mapped at startup */ -#define _MMAPDEV7X21 ( 0x00000000ull ) /* AMS userpage, NOT mapped at startup */ -#define _MMAPDEV7X22 ( 0x40038000ull ) /* DEBUG: IRAM */ - -/* LP0 entry ram segments (addr, size, additional attributes) */ -#define _MMAPLP0ES0 ( 0x40020000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM */ -#define _MMAPLP0ES1 ( 0x40003000ull, 0x01000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* LP0 entry code */ -#define _MMAPLP0ES2 ( 0x7C010000ull, 0x10000ull, MMU_AP_PRIV_RO | ATTRIB_MEMTYPE_NORMAL ) /* TZRAM to encrypt */ - -/* Warmboot data ram segments (addr, size, additional attributes) */ -#define _MMAPWBS0 ( 0x8000F000ull, 0x01000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted SE state for bootROM */ -#define _MMAPWBS1 ( 0x80010000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM for warmboot.bin */ - -/* TZRAM segments (offset, size, VA increment, is executable) */ -#define _MMAPTZS0 ( 0x3000ull, 0x10000 - 0x2000 - 0x3000ull, 0x10000ull, true ) /* Warmboot crt0 sections and main code segment */ -#define _MMAPTZS1 ( 0x10000 - 0x2000ull, 0x2000ull, 0x04000ull, true ) /* pk2ldr segment */ -#define _MMAPTZS2 ( 0ull, 0ull, 0x02000ull, false ) /* SPL .bss buffer, NOT mapped at startup */ -#define _MMAPTZS3 ( 0x10000 - 0x2000ull, 0x1000ull, 0x02000ull, false ) /* Core 0ull1,2 stack */ -#define _MMAPTZS4 ( 0x10000 - 0x1000ull, 0x1000ull, 0x02000ull, false ) /* Core 3 stack */ -#define _MMAPTZS5 ( 0ull, 0x1000ull, 0x02000ull, true ) /* Secure Monitor exception vectors, some init stacks */ -#define _MMAPTZS6 ( 0x1000ull, 0x1000ull, 0x02000ull, false ) /* L2 translation table */ -#define _MMAPTZS7 ( 0x2000ull, 0x1000ull, 0x02000ull, false ) /* L3 translation table */ - -/* TZRAM segments for 5.0.0+. (offset). */ -#define _MMAPTZ5XS0 ( 0x3000ull ) /* Warmboot crt0 sections and main code segment */ -#define _MMAPTZ5XS1 ( 0ull ) /* pk2ldr segment */ -#define _MMAPTZ5XS2 ( 0ull ) /* SPL .bss buffer, NOT mapped at startup */ -#define _MMAPTZ5XS3 ( 0ull ) /* Core 0ull1,2 stack */ -#define _MMAPTZ5XS4 ( 0x1000ull ) /* Core 3 stack */ -#define _MMAPTZ5XS5 ( 0x2000ull ) /* Secure Monitor exception vectors, some init stacks */ -#define _MMAPTZ5XS6 ( 0x10000 - 0x2000ull ) /* L2 translation table */ -#define _MMAPTZ5XS7 ( 0x10000 - 0x1000ull ) /* L3 translation table */ - -#define MMIO_BASE 0x1F0080000ull -#define LP0_ENTRY_RAM_SEGMENT_BASE (MMIO_BASE + 0x000100000ull) -#define WARMBOOT_RAM_SEGMENT_BASE (LP0_ENTRY_RAM_SEGMENT_BASE + 0x000047000ull) /* increment seems to be arbitrary ? */ -#define TZRAM_SEGMENT_BASE (MMIO_BASE + 0x000160000ull) - -#define IDENTITY_MAPPING_IRAM_A_CCRT0 0 -#define IDENTITY_MAPPING_IRAM_CD 1 -#define IDENTITY_MAPPING_TZRAM 2 -#define IDENTITY_MAPPING_DRAM 3 -#define IDENTIY_MAPPING_ID_MAX 4 - -#define MMIO_DEVID_GICD 0 -#define MMIO_DEVID_GICC 1 -#define MMIO_DEVID_UART 2 -#define MMIO_DEVID_CLKRST 3 -#define MMIO_DEVID_RTC_PMC 4 -#define MMIO_DEVID_TMRs_WDTs 5 -#define MMIO_DEVID_SYSREGS 6 -#define MMIO_DEVID_SE 7 -#define MMIO_DEVID_SYSCTR0 8 -#define MMIO_DEVID_MC 9 -#define MMIO_DEVID_FUSE 10 -#define MMIO_DEVID_MISC 11 -#define MMIO_DEVID_FLOWCTRL 12 -#define MMIO_DEVID_NXBOOTLOADER_MAILBOX 13 -#define MMIO_DEVID_I2C56_SPI2B 14 -#define MMIO_DEVID_GPIO 15 -#define MMIO_DEVID_DTV_I2C234 16 -#define MMIO_DEVID_EXCEPTION_VECTORS 17 -#define MMIO_DEVID_MC0 18 -#define MMIO_DEVID_MC1 19 -#define MMIO_DEVID_AMS_IRAM_PAGE 20 -#define MMIO_DEVID_AMS_USER_PAGE 21 -#define MMIO_DEVID_DEBUG_IRAM 22 -#define MMIO_DEVID_MAX 23 - -#define LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM 0 -#define LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE 1 -#define LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM 2 -#define LP0_ENTRY_RAM_SEGMENT_ID_MAX 3 - -#define WARMBOOT_RAM_SEGMENT_ID_SE_STATE 0 -#define WARMBOOT_RAM_SEGMENT_ID_TZRAM 1 -#define WARMBOOT_RAM_SEGMENT_ID_MAX 2 - -#define TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN 0 -#define TZRAM_SEGMENT_ID_PK2LDR 1 -#define TZRAM_SEGMENT_ID_USERPAGE 2 -#define TZRAM_SEGMENT_ID_CORE012_STACK 3 -#define TZRAM_SEGMENT_ID_CORE3_STACK 4 -#define TZRAM_SEGEMENT_ID_SECMON_EVT 5 -#define TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE 6 -#define TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE 7 -#define TZRAM_SEGMENT_ID_MAX 8 - -#define IDENTITY_GET_MAPPING_ADDRESS(mapping_id) (TUPLE_ELEM_0(CAT(_MMAPID, EVAL(mapping_id)))) -#define IDENTITY_GET_MAPPING_SIZE(mapping_id) (TUPLE_ELEM_1(CAT(_MMAPID, EVAL(mapping_id)))) -#define IDENTITY_GET_MAPPING_ATTRIBS(mapping_id) (TUPLE_ELEM_2(CAT(_MMAPID, EVAL(mapping_id)))) -#define IDENTITY_IS_MAPPING_BLOCK_RANGE(mapping_id) (TUPLE_ELEM_3(CAT(_MMAPID, EVAL(mapping_id)))) - -#define MMIO_GET_DEVICE_PA(device_id) (TUPLE_ELEM_0(CAT(_MMAPDEV, EVAL(device_id)))) -#define MMIO_GET_DEVICE_7X_PA(device_id) (TUPLE_ELEM_0(CAT(_MMAPDEV, EVAL(device_id)))) -#define MMIO_GET_DEVICE_ADDRESS(device_id)\ -(\ - (TUPLE_FOLD_LEFT_1(EVAL(device_id), _MMAPDEV, PLUS) EVAL(MMIO_BASE)) +\ - 0x1000ull * (device_id)\ -) -#define MMIO_GET_DEVICE_SIZE(device_id) (TUPLE_ELEM_1(CAT(_MMAPDEV, EVAL(device_id)))) -#define MMIO_IS_DEVICE_SECURE(device_id) (TUPLE_ELEM_2(CAT(_MMAPDEV, EVAL(device_id)))) - -#define LP0_ENTRY_GET_RAM_SEGMENT_PA(segment_id) (TUPLE_ELEM_0(CAT(_MMAPLP0ES, EVAL(segment_id)))) -#define LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(segment_id) (EVAL(LP0_ENTRY_RAM_SEGMENT_BASE) + 0x10000ull * (segment_id)) -#define LP0_ENTRY_GET_RAM_SEGMENT_SIZE(segment_id) (TUPLE_ELEM_1(CAT(_MMAPLP0ES, EVAL(segment_id)))) -#define LP0_ENTRY_GET_RAM_SEGMENT_ATTRIBS(segment_id) (TUPLE_ELEM_2(CAT(_MMAPLP0ES, EVAL(segment_id)))) - -#define WARMBOOT_GET_RAM_SEGMENT_PA(segment_id) (TUPLE_ELEM_0(CAT(_MMAPWBS, EVAL(segment_id)))) -#define WARMBOOT_GET_RAM_SEGMENT_ADDRESS(segment_id) (TUPLE_FOLD_LEFT_1(EVAL(segment_id), _MMAPWBS, PLUS) EVAL(WARMBOOT_RAM_SEGMENT_BASE)) -#define WARMBOOT_GET_RAM_SEGMENT_SIZE(segment_id) (TUPLE_ELEM_1(CAT(_MMAPWBS, EVAL(segment_id)))) -#define WARMBOOT_GET_RAM_SEGMENT_ATTRIBS(segment_id) (TUPLE_ELEM_2(CAT(_MMAPWBS, EVAL(segment_id)))) - -#define TZRAM_GET_SEGMENT_PA(segment_id) (0x7C010000ull + (TUPLE_ELEM_0(CAT(_MMAPTZS, EVAL(segment_id))))) -#define TZRAM_GET_SEGMENT_5X_PA(segment_id) (0x7C010000ull + (TUPLE_ELEM_0(CAT(_MMAPTZ5XS, EVAL(segment_id))))) -#define TZRAM_GET_SEGMENT_ADDRESS(segment_id) (TUPLE_FOLD_LEFT_2(EVAL(segment_id), _MMAPTZS, PLUS) EVAL(TZRAM_SEGMENT_BASE)) -#define TZRAM_GET_SEGMENT_SIZE(segment_id) (TUPLE_ELEM_1(CAT(_MMAPTZS, EVAL(segment_id)))) -#define TZRAM_IS_SEGMENT_EXECUTABLE(segment_id) (TUPLE_ELEM_3(CAT(_MMAPTZS, EVAL(segment_id)))) - -/**********************************************************************************************/ -/* We don't need unmapping functions */ - -ALINLINE static inline void identity_map_mapping(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_tbl, uintptr_t addr, size_t size, uint64_t attribs, bool is_block_range) { - if (is_block_range) { - mmu_map_block_range(1, mmu_l1_tbl, addr, addr, size, attribs | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_NORMAL); - } - else { - mmu_map_page_range(mmu_l3_tbl, addr, addr, size, attribs | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_NORMAL); - } -} -ALINLINE static inline void mmio_map_device(uintptr_t *mmu_l3_tbl, uintptr_t addr, uintptr_t pa, size_t size, bool is_secure) { - static const uint64_t secure_device_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_DEVICE; - static const uint64_t device_attributes = MMU_PTE_BLOCK_NS | secure_device_attributes; - - uint64_t attributes = is_secure ? secure_device_attributes : device_attributes; - mmu_map_page_range(mmu_l3_tbl, addr, pa, size, attributes); -} - -ALINLINE static inline void lp0_entry_map_ram_segment(uintptr_t *mmu_l3_tbl, uintptr_t addr, uintptr_t pa, size_t size, uint64_t attribs) { - uint64_t attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | attribs; - - mmu_map_page_range(mmu_l3_tbl, addr, pa, size, attributes); -} - -ALINLINE static inline void warmboot_map_ram_segment(uintptr_t *mmu_l3_tbl, uintptr_t addr, uintptr_t pa, size_t size, uint64_t attribs) { - uint64_t attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | attribs; - - mmu_map_page_range(mmu_l3_tbl, addr, pa, size, attributes); -} - -ALINLINE static inline void tzram_map_segment(uintptr_t *mmu_l3_tbl, uintptr_t addr, uintptr_t pa, size_t size, bool is_executable) { - uint64_t attributes = (is_executable ? 0 : MMU_PTE_BLOCK_XN) | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_NORMAL; - - mmu_map_page_range(mmu_l3_tbl, addr, pa, size, attributes); -} - -#endif diff --git a/exosphere/src/misc.h b/exosphere/src/misc.h deleted file mode 100644 index 40b633c4b..000000000 --- a/exosphere/src/misc.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_MISC_H -#define EXOSPHERE_MISC_H - -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 MISC Registers. */ - -#define MISC_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MISC)) -#define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n) - -#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 MAKE_MISC_REG(0x0C00) -#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 MAKE_MISC_REG(0x0C04) -#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 MAKE_MISC_REG(0x0C08) - -#endif diff --git a/exosphere/src/mmu.h b/exosphere/src/mmu.h deleted file mode 100644 index ed4cba784..000000000 --- a/exosphere/src/mmu.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_MMU_H -#define EXOSPHERE_MMU_H - -#include -#include -#include -#include "utils.h" - - -#ifndef MMU_GRANULE_TYPE -#define MMU_GRANULE_TYPE 0 /* 0: 4KB, 1: 64KB, 2: 16KB. The Switch always uses a 4KB granule size. */ -#endif - -#if MMU_GRANULE_TYPE == 0 -#define MMU_Lx_SHIFT(x) (12 + 9 * (3 - (x))) -#define MMU_Lx_MASK(x) MASKL(9) -#elif MMU_GRANULE_TYPE == 1 -/* 64 KB, no L0 here */ -#define MMU_Lx_SHIFT(x) (16 + 13 * (3 - (x))) -#define MMU_Lx_MASK(x) ((x) == 1 ? MASKL(5) : MASKL(13)) -#elif MMU_GRANULE_TYPE == 2 -#define MMU_Lx_SHIFT(x) (14 + 11 * (3 - (x))) -#define MMU_Lx_MASK(x) ((x) == 0 ? 1 : MASKL(11)) -#endif - -/* - * The following defines are adapted from uboot: - * - * (C) Copyright 2013 - * David Feng - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* Memory attributes, see set_memory_registers_enable_mmu */ -#define MMU_MT_NORMAL 0ull -#define MMU_MT_DEVICE_NGNRE 1ull -#define MMU_MT_DEVICE_NGNRNE 2ull /* not used, also the same as Attr4-7 */ - -/* - * Hardware page table definitions. - * - */ - -#define MMU_PTE_TYPE_MASK 3ull -#define MMU_PTE_TYPE_FAULT 0ull -#define MMU_PTE_TYPE_TABLE 3ull -#define MMU_PTE_TYPE_BLOCK 1ull - -/* L3 only */ -#define MMU_PTE_TYPE_PAGE 3ull - -#define MMU_PTE_TABLE_PXN BITL(59) -#define MMU_PTE_TABLE_XN BITL(60) -#define MMU_PTE_TABLE_AP BITL(61) -#define MMU_PTE_TABLE_NS BITL(63) - -/* - * Block - */ -#define MMU_PTE_BLOCK_MEMTYPE(x) ((uint64_t)((x) << 2)) -#define MMU_PTE_BLOCK_NS BITL(5) -#define MMU_PTE_BLOCK_NON_SHAREABLE (0ull << 8) -#define MMU_PTE_BLOCK_OUTER_SHAREABLE (2ull << 8) -#define MMU_PTE_BLOCK_INNER_SHAREBLE (3ull << 8) -#define MMU_PTE_BLOCK_AF BITL(10) -#define MMU_PTE_BLOCK_NG BITL(11) -#define MMU_PTE_BLOCK_PXN BITL(53) -#define MMU_PTE_BLOCK_UXN BITL(54) -#define MMU_PTE_BLOCK_XN MMU_PTE_BLOCK_UXN - -/* - * AP[2:1] - */ -#define MMU_AP_PRIV_RW (0ull << 6) -#define MMU_AP_RW (1ull << 6) -#define MMU_AP_PRIV_RO (2ull << 6) -#define MMU_AP_RO (3ull << 6) - -/* - * S2AP[2:1] (for stage2 translations; secmon doesn't use it) - */ -#define MMU_S2AP_NONE (0ull << 6) -#define MMU_S2AP_RO (1ull << 6) -#define MMU_S2AP_WO (2ull << 6) -#define MMU_S2AP_RW (3ull << 6) - -/* - * AttrIndx[2:0] - */ -#define MMU_PMD_ATTRINDX(t) ((uint64_t)((t) << 2)) -#define MMU_PMD_ATTRINDX_MASK (7ull << 2) - -/* - * TCR flags. - */ -#define TCR_T0SZ(x) ((64 - (x)) << 0) -#define TCR_IRGN_NC (0 << 8) -#define TCR_IRGN_WBWA (1 << 8) -#define TCR_IRGN_WT (2 << 8) -#define TCR_IRGN_WBNWA (3 << 8) -#define TCR_IRGN_MASK (3 << 8) -#define TCR_ORGN_NC (0 << 10) -#define TCR_ORGN_WBWA (1 << 10) -#define TCR_ORGN_WT (2 << 10) -#define TCR_ORGN_WBNWA (3 << 10) -#define TCR_ORGN_MASK (3 << 10) -#define TCR_NOT_SHARED (0 << 12) -#define TCR_SHARED_OUTER (2 << 12) -#define TCR_SHARED_INNER (3 << 12) -#define TCR_TG0_4K (0 << 14) -#define TCR_TG0_64K (1 << 14) -#define TCR_TG0_16K (2 << 14) -#define TCR_PS(x) ((x) << 16) -#define TCR_EPD1_DISABLE BIT(23) - -#define TCR_EL1_RSVD BIT(31) -#define TCR_EL2_RSVD (BIT(31) | BIT(23)) -#define TCR_EL3_RSVD (BIT(31) | BIT(23)) - -static inline void mmu_init_table(volatile uintptr_t *tbl, size_t num_entries) { - for(size_t i = 0; i < num_entries / 8; i++) { - tbl[i] = MMU_PTE_TYPE_FAULT; - } -} - -/* - All the functions below assume base_addr is valid. - They do not invalidate the TLB, which must be done separately. -*/ - -static inline unsigned int mmu_compute_index(unsigned int level, uintptr_t base_addr) { - return (base_addr >> MMU_Lx_SHIFT(level)) & MMU_Lx_MASK(level); -} - -static inline void mmu_map_table(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t *next_lvl_tbl_pa, uint64_t attrs) { - tbl[mmu_compute_index(level, base_addr)] = (uintptr_t)next_lvl_tbl_pa | attrs | MMU_PTE_TYPE_TABLE; -} - -static inline void mmu_map_block(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, uint64_t attrs) { - tbl[mmu_compute_index(level, base_addr)] = phys_addr | attrs | MMU_PTE_BLOCK_AF | MMU_PTE_TYPE_BLOCK; -} - -static inline void mmu_map_page(uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, uint64_t attrs) { - tbl[mmu_compute_index(3, base_addr)] = phys_addr | attrs | MMU_PTE_BLOCK_AF | MMU_PTE_TYPE_PAGE; -} - -static inline void mmu_unmap(unsigned int level, uintptr_t *tbl, uintptr_t base_addr) { - tbl[mmu_compute_index(level, base_addr)] = MMU_PTE_TYPE_FAULT; -} - -static inline void mmu_unmap_page(uintptr_t *tbl, uintptr_t base_addr) { - tbl[mmu_compute_index(3, base_addr)] = MMU_PTE_TYPE_FAULT; -} - -static inline void mmu_map_block_range(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, size_t size, uint64_t attrs) { - size = ((size + (BITL(MMU_Lx_SHIFT(level)) - 1)) >> MMU_Lx_SHIFT(level)) << MMU_Lx_SHIFT(level); - for(size_t offset = 0; offset < size; offset += BITL(MMU_Lx_SHIFT(level))) { - mmu_map_block(level, tbl, base_addr + offset, phys_addr + offset, attrs); - } -} - -static inline void mmu_map_page_range(uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, size_t size, uint64_t attrs) { - size = ((size + (BITL(MMU_Lx_SHIFT(3)) - 1)) >> MMU_Lx_SHIFT(3)) << MMU_Lx_SHIFT(3); - for(size_t offset = 0; offset < size; offset += BITL(MMU_Lx_SHIFT(3))) { - mmu_map_page(tbl, base_addr + offset, phys_addr + offset, attrs); - } -} - -static inline void mmu_unmap_range(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, size_t size) { - size = ((size + (BITL(MMU_Lx_SHIFT(level)) - 1)) >> MMU_Lx_SHIFT(level)) << MMU_Lx_SHIFT(level); - for(size_t offset = 0; offset < size; offset += BITL(MMU_Lx_SHIFT(level))) { - mmu_unmap(level, tbl, base_addr + offset); - } -} - -#endif diff --git a/exosphere/src/my_libc.c b/exosphere/src/my_libc.c deleted file mode 100644 index ffd1b595b..000000000 --- a/exosphere/src/my_libc.c +++ /dev/null @@ -1,1141 +0,0 @@ -/* Note: copied from newlib */ -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -/* - * Copyright (C) 2004 CodeSourcery, LLC - * - * Permission to use, copy, modify, and distribute this file - * for any purpose is hereby granted without fee, provided that - * the above copyright notice and this notice appears in all - * copies. - * - * This file is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* Handle ELF .{pre_init,init,fini}_array sections. */ -#include - -#ifndef HAVE_INITFINI_ARRAY -#define HAVE_INITFINI_ARRAY -#endif - -#undef HAVE_INIT_FINI - -#ifdef HAVE_INITFINI_ARRAY - -/* These magic symbols are provided by the linker. */ -extern void (*__preinit_array_start []) (void) __attribute__((weak)); -extern void (*__preinit_array_end []) (void) __attribute__((weak)); -extern void (*__init_array_start []) (void) __attribute__((weak)); -extern void (*__init_array_end []) (void) __attribute__((weak)); - -#ifdef HAVE_INIT_FINI -extern void _init (void); -#endif - -/* Iterate over all the init routines. */ -void -__libc_init_array (void) -{ - size_t count; - size_t i; - - count = __preinit_array_end - __preinit_array_start; - for (i = 0; i < count; i++) - __preinit_array_start[i] (); - -#ifdef HAVE_INIT_FINI - _init (); -#endif - - count = __init_array_end - __init_array_start; - for (i = 0; i < count; i++) - __init_array_start[i] (); -} -#endif - -#ifdef HAVE_INITFINI_ARRAY -extern void (*__fini_array_start []) (void) __attribute__((weak)); -extern void (*__fini_array_end []) (void) __attribute__((weak)); - -#ifdef HAVE_INIT_FINI -extern void _fini (void); -#endif - -/* Run all the cleanup routines. */ -void -__libc_fini_array (void) -{ - size_t count; - size_t i; - - count = __fini_array_end - __fini_array_start; - for (i = count; i > 0; i--) - __fini_array_start[i-1] (); - -#ifdef HAVE_INIT_FINI - _fini (); -#endif -} -#endif - -/* -FUNCTION - <>---move possibly overlapping memory -INDEX - memmove -SYNOPSIS - #include - void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); -DESCRIPTION - This function moves <[length]> characters from the block of - memory starting at <<*<[src]>>> to the memory starting at - <<*<[dst]>>>. <> reproduces the characters correctly - at <<*<[dst]>>> even if the two areas overlap. -RETURNS - The function returns <[dst]> as passed. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - memmove ansi pure -*/ - -/* Nonzero if either X or Y is not aligned on a "long" boundary. */ -#define UNALIGNED(X, Y) \ - (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) - -/* How many bytes are copied each iteration of the 4X unrolled loop. */ -#define BIGBLOCKSIZE (sizeof (long) << 2) - -/* How many bytes are copied each iteration of the word copy loop. */ -#define LITTLEBLOCKSIZE (sizeof (long)) - -/* Threshhold for punting to the byte copier. */ -#undef TOO_SMALL -#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) - -/*SUPPRESS 20*/ -void * -//__inhibit_loop_to_libcall -memmove (void *dst_void, - const void *src_void, - size_t length) -{ -#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - char *dst = dst_void; - const char *src = src_void; - - if (src < dst && dst < src + length) - { - /* Have to copy backwards */ - src += length; - dst += length; - while (length--) - { - *--dst = *--src; - } - } - else - { - while (length--) - { - *dst++ = *src++; - } - } - - return dst_void; -#else - char *dst = dst_void; - const char *src = src_void; - long *aligned_dst; - const long *aligned_src; - - if (src < dst && dst < src + length) - { - /* Destructive overlap...have to copy backwards */ - src += length; - dst += length; - while (length--) - { - *--dst = *--src; - } - } - else - { - /* Use optimizing algorithm for a non-destructive copy to closely - match memcpy. If the size is small or either SRC or DST is unaligned, - then punt into the byte copy loop. This should be rare. */ - if (!TOO_SMALL(length) && !UNALIGNED (src, dst)) - { - aligned_dst = (long*)dst; - aligned_src = (long*)src; - - /* Copy 4X long words at a time if possible. */ - while (length >= BIGBLOCKSIZE) - { - *aligned_dst++ = *aligned_src++; - *aligned_dst++ = *aligned_src++; - *aligned_dst++ = *aligned_src++; - *aligned_dst++ = *aligned_src++; - length -= BIGBLOCKSIZE; - } - - /* Copy one long word at a time if possible. */ - while (length >= LITTLEBLOCKSIZE) - { - *aligned_dst++ = *aligned_src++; - length -= LITTLEBLOCKSIZE; - } - - /* Pick up any residual with a byte copier. */ - dst = (char*)aligned_dst; - src = (char*)aligned_src; - } - - while (length--) - { - *dst++ = *src++; - } - } - - return dst_void; -#endif /* not PREFER_SIZE_OVER_SPEED */ -} - -/* -FUNCTION - <>---copy memory regions -SYNOPSIS - #include - void* memcpy(void *restrict <[out]>, const void *restrict <[in]>, - size_t <[n]>); -DESCRIPTION - This function copies <[n]> bytes from the memory region - pointed to by <[in]> to the memory region pointed to by - <[out]>. - If the regions overlap, the behavior is undefined. -RETURNS - <> returns a pointer to the first byte of the <[out]> - region. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - memcpy ansi pure - */ - -void * -memcpy (void * dst0, - const void * __restrict src0, - size_t len0) -{ -#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - char *dst = (char *) dst0; - char *src = (char *) src0; - - void *save = dst0; - - while (len0--) - { - *dst++ = *src++; - } - - return save; -#else - char *dst = dst0; - const char *src = src0; - long *aligned_dst; - const long *aligned_src; - - /* If the size is small, or either SRC or DST is unaligned, - then punt into the byte copy loop. This should be rare. */ - if (!TOO_SMALL(len0) && !UNALIGNED (src, dst)) - { - aligned_dst = (long*)dst; - aligned_src = (long*)src; - - /* Copy 4X long words at a time if possible. */ - while (len0 >= BIGBLOCKSIZE) - { - *aligned_dst++ = *aligned_src++; - *aligned_dst++ = *aligned_src++; - *aligned_dst++ = *aligned_src++; - *aligned_dst++ = *aligned_src++; - len0 -= BIGBLOCKSIZE; - } - - /* Copy one long word at a time if possible. */ - while (len0 >= LITTLEBLOCKSIZE) - { - *aligned_dst++ = *aligned_src++; - len0 -= LITTLEBLOCKSIZE; - } - - /* Pick up any residual with a byte copier. */ - dst = (char*)aligned_dst; - src = (char*)aligned_src; - } - - while (len0--) - *dst++ = *src++; - - return dst0; -#endif /* not PREFER_SIZE_OVER_SPEED */ -} - -/* -FUNCTION - <>---set an area of memory -INDEX - memset -SYNOPSIS - #include - void *memset(void *<[dst]>, int <[c]>, size_t <[length]>); -DESCRIPTION - This function converts the argument <[c]> into an unsigned - char and fills the first <[length]> characters of the array - pointed to by <[dst]> to the value. -RETURNS - <> returns the value of <[dst]>. -PORTABILITY -<> is ANSI C. - <> requires no supporting OS subroutines. -QUICKREF - memset ansi pure -*/ - -#include - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - -#define LBLOCKSIZE (sizeof(long)) -#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) -#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) - -void * -memset (void *m, - int c, - size_t n) -{ - char *s = (char *) m; - -#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) - unsigned int i; - unsigned long buffer; - unsigned long *aligned_addr; - unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an - unsigned variable. */ - - while (UNALIGNED (s)) - { - if (n--) - *s++ = (char) c; - else - return m; - } - - if (!TOO_SMALL (n)) - { - /* If we get this far, we know that n is large and s is word-aligned. */ - aligned_addr = (unsigned long *) s; - - /* Store D into each char sized location in BUFFER so that - we can set large blocks quickly. */ - buffer = (d << 8) | d; - buffer |= (buffer << 16); - for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) - buffer = (buffer << i) | buffer; - - /* Unroll the loop. */ - while (n >= LBLOCKSIZE*4) - { - *aligned_addr++ = buffer; - *aligned_addr++ = buffer; - *aligned_addr++ = buffer; - *aligned_addr++ = buffer; - n -= 4*LBLOCKSIZE; - } - - while (n >= LBLOCKSIZE) - { - *aligned_addr++ = buffer; - n -= LBLOCKSIZE; - } - /* Pick up the remainder with a bytewise loop. */ - s = (char*)aligned_addr; - } - -#endif /* not PREFER_SIZE_OVER_SPEED */ - - while (n--) - *s++ = (char) c; - - return m; -} - -/* -FUNCTION - <>---find character in memory -INDEX - memchr -SYNOPSIS - #include - void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); -DESCRIPTION - This function searches memory starting at <<*<[src]>>> for the - character <[c]>. The search only ends with the first - occurrence of <[c]>, or after <[length]> characters; in - particular, <> does not terminate the search. -RETURNS - If the character <[c]> is found within <[length]> characters - of <<*<[src]>>>, a pointer to the character is returned. If - <[c]> is not found, then <> is returned. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - memchr ansi pure -*/ - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - - -/* Nonzero if either X or Y is not aligned on a "long" boundary. */ -#define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) - -/* How many bytes are loaded each iteration of the word copy loop. */ -#define LBLOCKSIZE (sizeof (long)) - -/* Threshhold for punting to the bytewise iterator. */ -#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) - -#if LONG_MAX == 2147483647L -#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) -#else -#if LONG_MAX == 9223372036854775807L -/* Nonzero if X (a long int) contains a NULL byte. */ -#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) -#else -#error long int is not a 32bit or 64bit type. -#endif -#endif - -#ifndef DETECTNULL -#error long int is not a 32bit or 64bit byte -#endif - -/* DETECTCHAR returns nonzero if (long)X contains the byte used - to fill (long)MASK. */ -#define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) - -void * -memchr (const void *src_void, - int c, - size_t length) -{ - const unsigned char *src = (const unsigned char *) src_void; - unsigned char d = c; - -#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) - unsigned long *asrc; - unsigned long mask; - unsigned int i; - - while (UNALIGNED (src)) - { - if (!length--) - return NULL; - if (*src == d) - return (void *) src; - src++; - } - - if (!TOO_SMALL (length)) - { - /* If we get this far, we know that length is large and src is - word-aligned. */ - /* The fast code reads the source one word at a time and only - performs the bytewise search on word-sized segments if they - contain the search character, which is detected by XORing - the word-sized segment with a word-sized block of the search - character and then detecting for the presence of NUL in the - result. */ - asrc = (unsigned long *) src; - mask = d << 8 | d; - mask = mask << 16 | mask; - for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) - mask = (mask << i) | mask; - - while (length >= LBLOCKSIZE) - { - if (DETECTCHAR (*asrc, mask)) - break; - length -= LBLOCKSIZE; - asrc++; - } - - /* If there are fewer than LBLOCKSIZE characters left, - then we resort to the bytewise loop. */ - - src = (unsigned char *) asrc; - } - -#endif /* not PREFER_SIZE_OVER_SPEED */ - - while (length--) - { - if (*src == d) - return (void *) src; - src++; - } - - return NULL; -} - -/* -FUNCTION - <>---compare two memory areas -INDEX - memcmp -SYNOPSIS - #include - int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); -DESCRIPTION - This function compares not more than <[n]> characters of the - object pointed to by <[s1]> with the object pointed to by <[s2]>. -RETURNS - The function returns an integer greater than, equal to or - less than zero according to whether the object pointed to by - <[s1]> is greater than, equal to or less than the object - pointed to by <[s2]>. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - memcmp ansi pure -*/ - - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - -/* Nonzero if either X or Y is not aligned on a "long" boundary. */ -#define UNALIGNED(X, Y) \ - (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) - -/* How many bytes are copied each iteration of the word copy loop. */ -#define LBLOCKSIZE (sizeof (long)) - -/* Threshhold for punting to the byte copier. */ -#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) - -int -memcmp (const void *m1, - const void *m2, - size_t n) -{ -#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - unsigned char *s1 = (unsigned char *) m1; - unsigned char *s2 = (unsigned char *) m2; - - while (n--) - { - if (*s1 != *s2) - { - return *s1 - *s2; - } - s1++; - s2++; - } - return 0; -#else - unsigned char *s1 = (unsigned char *) m1; - unsigned char *s2 = (unsigned char *) m2; - unsigned long *a1; - unsigned long *a2; - - /* If the size is too small, or either pointer is unaligned, - then we punt to the byte compare loop. Hopefully this will - not turn up in inner loops. */ - if (!TOO_SMALL(n) && !UNALIGNED(s1,s2)) - { - /* Otherwise, load and compare the blocks of memory one - word at a time. */ - a1 = (unsigned long*) s1; - a2 = (unsigned long*) s2; - while (n >= LBLOCKSIZE) - { - if (*a1 != *a2) - break; - a1++; - a2++; - n -= LBLOCKSIZE; - } - - /* check m mod LBLOCKSIZE remaining characters */ - - s1 = (unsigned char*)a1; - s2 = (unsigned char*)a2; - } - - while (n--) - { - if (*s1 != *s2) - return *s1 - *s2; - s1++; - s2++; - } - - return 0; -#endif /* not PREFER_SIZE_OVER_SPEED */ -} - -/* -FUNCTION - <>---search for character in string -INDEX - strchr -SYNOPSIS - #include - char * strchr(const char *<[string]>, int <[c]>); -DESCRIPTION - This function finds the first occurence of <[c]> (converted to - a char) in the string pointed to by <[string]> (including the - terminating null character). -RETURNS - Returns a pointer to the located character, or a null pointer - if <[c]> does not occur in <[string]>. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - strchr ansi pure -*/ - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - - -/* Nonzero if X is not aligned on a "long" boundary. */ -#define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) - -/* How many bytes are loaded each iteration of the word copy loop. */ -#define LBLOCKSIZE (sizeof (long)) - -char * -strchr (const char *s1, - int i) -{ - const unsigned char *s = (const unsigned char *)s1; - unsigned char c = i; - -#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) - unsigned long mask,j; - unsigned long *aligned_addr; - - /* Special case for finding 0. */ - if (!c) - { - while (UNALIGNED (s)) - { - if (!*s) - return (char *) s; - s++; - } - /* Operate a word at a time. */ - aligned_addr = (unsigned long *) s; - while (!DETECTNULL (*aligned_addr)) - aligned_addr++; - /* Found the end of string. */ - s = (const unsigned char *) aligned_addr; - while (*s) - s++; - return (char *) s; - } - - /* All other bytes. Align the pointer, then search a long at a time. */ - while (UNALIGNED (s)) - { - if (!*s) - return NULL; - if (*s == c) - return (char *) s; - s++; - } - - mask = c; - for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) - mask = (mask << j) | mask; - - aligned_addr = (unsigned long *) s; - while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) - aligned_addr++; - - /* The block of bytes currently pointed to by aligned_addr - contains either a null or the target char, or both. We - catch it using the bytewise search. */ - - s = (unsigned char *) aligned_addr; - -#endif /* not PREFER_SIZE_OVER_SPEED */ - - while (*s && *s != c) - s++; - if (*s == c) - return (char *)s; - return NULL; -} - -/* -FUNCTION - <>---character string compare - -INDEX - strcmp -SYNOPSIS - #include - int strcmp(const char *<[a]>, const char *<[b]>); -DESCRIPTION - <> compares the string at <[a]> to - the string at <[b]>. -RETURNS - If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, - <> returns a number greater than zero. If the two - strings match, <> returns zero. If <<*<[a]>>> - sorts lexicographically before <<*<[b]>>>, <> returns a - number less than zero. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - strcmp ansi pure -*/ - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - -/* Nonzero if either X or Y is not aligned on a "long" boundary. */ -#define UNALIGNED(X, Y) \ - (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) - -int -strcmp (const char *s1, - const char *s2) -{ -#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - while (*s1 != '\0' && *s1 == *s2) - { - s1++; - s2++; - } - - return (*(unsigned char *) s1) - (*(unsigned char *) s2); -#else - unsigned long *a1; - unsigned long *a2; - - /* If s1 or s2 are unaligned, then compare bytes. */ - if (!UNALIGNED (s1, s2)) - { - /* If s1 and s2 are word-aligned, compare them a word at a time. */ - a1 = (unsigned long*)s1; - a2 = (unsigned long*)s2; - while (*a1 == *a2) - { - /* To get here, *a1 == *a2, thus if we find a null in *a1, - then the strings must be equal, so return zero. */ - if (DETECTNULL (*a1)) - return 0; - - a1++; - a2++; - } - - /* A difference was detected in last few bytes of s1, so search bytewise */ - s1 = (char*)a1; - s2 = (char*)a2; - } - - while (*s1 != '\0' && *s1 == *s2) - { - s1++; - s2++; - } - return (*(unsigned char *) s1) - (*(unsigned char *) s2); -#endif /* not PREFER_SIZE_OVER_SPEED */ -} - -/* -FUNCTION - <>---copy string -INDEX - strcpy -SYNOPSIS - #include - char *strcpy(char *<[dst]>, const char *<[src]>); -DESCRIPTION - <> copies the string pointed to by <[src]> - (including the terminating null character) to the array - pointed to by <[dst]>. -RETURNS - This function returns the initial value of <[dst]>. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - strcpy ansi pure -*/ - -/*SUPPRESS 560*/ -/*SUPPRESS 530*/ - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - -/* Nonzero if either X or Y is not aligned on a "long" boundary. */ -#define UNALIGNED(X, Y) \ - (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) - -char* -strcpy (char *dst0, - const char *src0) -{ -#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - char *s = dst0; - - while ((*dst0++ = *src0++)) - ; - - return s; -#else - char *dst = dst0; - const char *src = src0; - long *aligned_dst; - const long *aligned_src; - - /* If SRC or DEST is unaligned, then copy bytes. */ - if (!UNALIGNED (src, dst)) - { - aligned_dst = (long*)dst; - aligned_src = (long*)src; - - /* SRC and DEST are both "long int" aligned, try to do "long int" - sized copies. */ - while (!DETECTNULL(*aligned_src)) - { - *aligned_dst++ = *aligned_src++; - } - - dst = (char*)aligned_dst; - src = (char*)aligned_src; - } - - while ((*dst++ = *src++)) - ; - return dst0; -#endif /* not PREFER_SIZE_OVER_SPEED */ -} - -/* -FUNCTION - <>---character string length -INDEX - strlen -SYNOPSIS - #include - size_t strlen(const char *<[str]>); -DESCRIPTION - The <> function works out the length of the string - starting at <<*<[str]>>> by counting chararacters until it - reaches a <> character. -RETURNS - <> returns the character count. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - strlen ansi pure -*/ - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - -#define LBLOCKSIZE (sizeof (long)) -#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) -size_t -strlen (const char *str) -{ - const char *start = str; - -#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) - unsigned long *aligned_addr; - - /* Align the pointer, so we can search a word at a time. */ - while (UNALIGNED (str)) - { - if (!*str) - return str - start; - str++; - } - - /* If the string is word-aligned, we can check for the presence of - a null in each word-sized block. */ - aligned_addr = (unsigned long *)str; - while (!DETECTNULL (*aligned_addr)) - aligned_addr++; - - /* Once a null is detected, we check each byte in that block for a - precise position of the null. */ - str = (char *) aligned_addr; - -#endif /* not PREFER_SIZE_OVER_SPEED */ - - while (*str) - str++; - return str - start; -} - -/* -FUNCTION - <>---character string compare - -INDEX - strncmp -SYNOPSIS - #include - int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>); -DESCRIPTION - <> compares up to <[length]> characters - from the string at <[a]> to the string at <[b]>. -RETURNS - If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, - <> returns a number greater than zero. If the two - strings are equivalent, <> returns zero. If <<*<[a]>>> - sorts lexicographically before <<*<[b]>>>, <> returns a - number less than zero. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - strncmp ansi pure -*/ - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - -#define UNALIGNED(X, Y) \ - (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) - -int -strncmp (const char *s1, - const char *s2, - size_t n) -{ -#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - if (n == 0) - return 0; - - while (n-- != 0 && *s1 == *s2) - { - if (n == 0 || *s1 == '\0') - break; - s1++; - s2++; - } - - return (*(unsigned char *) s1) - (*(unsigned char *) s2); -#else - unsigned long *a1; - unsigned long *a2; - - if (n == 0) - return 0; - - /* If s1 or s2 are unaligned, then compare bytes. */ - if (!UNALIGNED (s1, s2)) - { - /* If s1 and s2 are word-aligned, compare them a word at a time. */ - a1 = (unsigned long*)s1; - a2 = (unsigned long*)s2; - while (n >= sizeof (long) && *a1 == *a2) - { - n -= sizeof (long); - - /* If we've run out of bytes or hit a null, return zero - since we already know *a1 == *a2. */ - if (n == 0 || DETECTNULL (*a1)) - return 0; - - a1++; - a2++; - } - - /* A difference was detected in last few bytes of s1, so search bytewise */ - s1 = (char*)a1; - s2 = (char*)a2; - } - - while (n-- > 0 && *s1 == *s2) - { - /* If we've run out of bytes or hit a null, return zero - since we already know *s1 == *s2. */ - if (n == 0 || *s1 == '\0') - return 0; - s1++; - s2++; - } - return (*(unsigned char *) s1) - (*(unsigned char *) s2); -#endif /* not PREFER_SIZE_OVER_SPEED */ -} - -/* -FUNCTION - <>---counted copy string -INDEX - strncpy -SYNOPSIS - #include - char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>, - size_t <[length]>); -DESCRIPTION - <> copies not more than <[length]> characters from the - the string pointed to by <[src]> (including the terminating - null character) to the array pointed to by <[dst]>. If the - string pointed to by <[src]> is shorter than <[length]> - characters, null characters are appended to the destination - array until a total of <[length]> characters have been - written. -RETURNS - This function returns the initial value of <[dst]>. -PORTABILITY -<> is ANSI C. -<> requires no supporting OS subroutines. -QUICKREF - strncpy ansi pure -*/ - -/*SUPPRESS 560*/ -/*SUPPRESS 530*/ - -#undef LBLOCKSIZE -#undef UNALIGNED -#undef TOO_SMALL - -#define UNALIGNED(X, Y) \ - (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) - -#define TOO_SMALL(LEN) ((LEN) < sizeof (long)) - -char * -strncpy (char *__restrict dst0, - const char *__restrict src0, - size_t count) -{ -#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - char *dscan; - const char *sscan; - - dscan = dst0; - sscan = src0; - while (count > 0) - { - --count; - if ((*dscan++ = *sscan++) == '\0') - break; - } - while (count-- > 0) - *dscan++ = '\0'; - - return dst0; -#else - char *dst = dst0; - const char *src = src0; - long *aligned_dst; - const long *aligned_src; - - /* If SRC and DEST is aligned and count large enough, then copy words. */ - if (!UNALIGNED (src, dst) && !TOO_SMALL (count)) - { - aligned_dst = (long*)dst; - aligned_src = (long*)src; - - /* SRC and DEST are both "long int" aligned, try to do "long int" - sized copies. */ - while (count >= sizeof (long int) && !DETECTNULL(*aligned_src)) - { - count -= sizeof (long int); - *aligned_dst++ = *aligned_src++; - } - - dst = (char*)aligned_dst; - src = (char*)aligned_src; - } - - while (count > 0) - { - --count; - if ((*dst++ = *src++) == '\0') - break; - } - - while (count-- > 0) - *dst++ = '\0'; - - return dst0; -#endif /* not PREFER_SIZE_OVER_SPEED */ -} - -/* -FUNCTION - <>---character string length - -INDEX - strnlen -SYNOPSIS - #include - size_t strnlen(const char *<[str]>, size_t <[n]>); -DESCRIPTION - The <> function works out the length of the string - starting at <<*<[str]>>> by counting chararacters until it - reaches a NUL character or the maximum: <[n]> number of - characters have been inspected. -RETURNS - <> returns the character count or <[n]>. -PORTABILITY -<> is a GNU extension. -<> requires no supporting OS subroutines. -*/ - -size_t -strnlen (const char *str, - size_t n) -{ - const char *start = str; - - while (n-- > 0 && *str) - str++; - - return str - start; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c deleted file mode 100644 index bee6a60f0..000000000 --- a/exosphere/src/package2.c +++ /dev/null @@ -1,637 +0,0 @@ -/* - * 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 "utils.h" -#include "memory_map.h" -#include "bootup.h" -#include "cpu_context.h" -#include "package2.h" -#include "configitem.h" -#include "se.h" -#include "interrupt.h" -#include "masterkey.h" -#include "arm.h" -#include "pmc.h" -#include "randomcache.h" -#include "timers.h" -#include "bootconfig.h" -#include "sysctr0.h" -#include "exocfg.h" -#include "smc_api.h" - -extern void *__start_cold_addr; -extern size_t __bin_size; - -static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ - {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ - {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.x New Device Key Source. */ - {0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17}, /* 6.2.0 New Device Key Source. */ - {0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, /* 7.0.0 New Device Key Source. */ - {0x67, 0x62, 0xD4, 0x8E, 0x55, 0xCF, 0xFF, 0x41, 0x31, 0x15, 0x3B, 0x24, 0x0C, 0x7C, 0x07, 0xAE}, /* 8.1.0 New Device Key Source. */ - {0x4A, 0xC3, 0x4E, 0x14, 0x8B, 0x96, 0x4A, 0xD5, 0xD4, 0x99, 0x73, 0xC4, 0x45, 0xAB, 0x8B, 0x49}, /* 9.0.0 New Device Key Source. */ - {0x14, 0xB8, 0x74, 0x12, 0xCB, 0xBD, 0x0B, 0x8F, 0x20, 0xFB, 0x30, 0xDA, 0x27, 0xE4, 0x58, 0x94}, /* 9.1.0 New Device Key Source. */ -}; - -static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ - {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */ - {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.x New Device Keygen Source. */ - {0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB}, /* 6.2.0 New Device Keygen Source. */ - {0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */ - {0xA6, 0x81, 0x71, 0xE7, 0xB5, 0x23, 0x74, 0xB0, 0x39, 0x8C, 0xB7, 0xFF, 0xA0, 0x62, 0x9F, 0x8D}, /* 8.1.0 New Device Keygen Source. */ - {0x03, 0xE7, 0xEB, 0x43, 0x1B, 0xCF, 0x5F, 0xB5, 0xED, 0xDC, 0x97, 0xAE, 0x21, 0x8D, 0x19, 0xED}, /* 9.0.0 New Device Keygen Source. */ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */ -}; - -static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */ - {0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */ - {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5}, /* 6.x New Device Keygen Source. */ - {0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38}, /* 6.2.0 New Device Keygen Source. */ - {0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 7.0.0 New Device Keygen Source. */ - {0x94, 0xD6, 0xA8, 0xC0, 0x95, 0xAF, 0xD0, 0xA6, 0x27, 0x53, 0x5E, 0xE5, 0x8E, 0x70, 0x1F, 0x87}, /* 8.1.0 New Device Keygen Source. */ - {0x61, 0x6A, 0x88, 0x21, 0xA3, 0x52, 0xB0, 0x19, 0x16, 0x25, 0xA4, 0xE3, 0x4C, 0x54, 0x02, 0x0F}, /* 9.0.0 New Device Keygen Source. */ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */ -}; - -static void derive_new_device_keys(unsigned int keygen_keyslot) { - uint8_t work_buffer[0x10]; - bool is_retail = configitem_is_retail(); - for (unsigned int revision = 0; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS; revision++) { - const unsigned int relative_revision = revision + MASTERKEY_REVISION_400_410; - - se_aes_ecb_decrypt_block(keygen_keyslot, work_buffer, 0x10, new_device_key_sources[revision], 0x10); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), is_retail ? new_device_keygen_sources[revision] : new_device_keygen_sources_dev[revision], 0x10); - if (relative_revision > mkey_get_revision()) { - break; - } else if (relative_revision == mkey_get_revision()) { - /* On 7.0.0, sept will have derived this key for us already. */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { - decrypt_data_into_keyslot(KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10); - } - } else { - se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10, work_buffer, 0x10); - set_old_devkey(relative_revision, work_buffer); - } - } - set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); - clear_aes_keyslot(keygen_keyslot); -} - -/* Hardware init, sets up the RNG and SESSION keyslots, derives new DEVICE key. */ -static void setup_se(void) { - uint8_t work_buffer[0x10]; - - /* Sanity check the Security Engine. */ - se_verify_flags_cleared(); - - /* Initialize interrupts. */ - intr_initialize_gic_nonsecure(); - - /* Perform some sanity initialization. */ - volatile tegra_se_t *se = se_get_regs(); - se->SE_SE_SECURITY &= 0xFFFEFFFF; /* Clear bit 16. */ - (void)(se->SE_STATUS); - __dsb_sy(); - - /* NOTE: On 8.1.0+, Nintendo does not make keyslots 0-5 unreadable. */ - se->SE_TZRAM_SECURITY = 0; - se->SE_CRYPTO_SECURITY_PERKEY = 0; - se->SE_RSA_SECURITY_PERKEY = 0; - se->SE_SE_SECURITY &= 0xFFFFFFFB; - - /* Currently unknown what each flag does. */ - for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - set_aes_keyslot_flags(i, 0x15); - } - - for (unsigned int i = 4; i < KEYSLOT_AES_MAX; i++) { - set_aes_keyslot_flags(i, 0x40); - } - - for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) { - set_rsa_keyslot_flags(i, 0x41); - } - - /* Detect Master Key revision. */ - mkey_detect_revision(); - - /* Derive new device keys. */ - { - const uint32_t target_fw = exosphere_get_target_firmware(); - if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - derive_new_device_keys(KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY); - } else { - /* No new keys to derive */ - } - } - - se_initialize_rng(KEYSLOT_SWITCH_DEVICEKEY); - - /* Generate random data, transform with device key to get RNG key. */ - se_generate_random(KEYSLOT_SWITCH_DEVICEKEY, work_buffer, 0x10); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_RNGKEY, KEYSLOT_SWITCH_DEVICEKEY, work_buffer, 0x10); - set_aes_keyslot_flags(KEYSLOT_SWITCH_RNGKEY, 0xFF); - - /* Repeat for Session key. */ - se_generate_random(KEYSLOT_SWITCH_DEVICEKEY, work_buffer, 0x10); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_SESSIONKEY, KEYSLOT_SWITCH_DEVICEKEY, work_buffer, 0x10); - set_aes_keyslot_flags(KEYSLOT_SWITCH_SESSIONKEY, 0xFF); - - /* Generate test vector for our keys. */ - se_generate_stored_vector(); -} - -static void setup_boot_config(void) { - /* Load boot config only if dev unit. */ - if (configitem_is_retail()) { - bootconfig_clear(); - } else { - void *bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER; - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER_6X; - } - flush_dcache_range((uint8_t *)bootconfig_ptr, (uint8_t *)bootconfig_ptr + sizeof(bootconfig_t)); - bootconfig_load_and_verify((bootconfig_t *)bootconfig_ptr); - } -} - -static void package2_crypt_ctr(unsigned int master_key_rev, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { - /* Derive package2 key. */ - static const uint8_t package2_key_source[0x10] = {0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7}; - flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size); - flush_dcache_range((uint8_t *)src, (uint8_t *)src + src_size); - unsigned int keyslot = mkey_get_keyslot(master_key_rev); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY, keyslot, package2_key_source, 0x10); - - /* Perform Encryption. */ - se_aes_ctr_crypt(KEYSLOT_SWITCH_PACKAGE2KEY, dst, dst_size, src, src_size, ctr, ctr_size); -} - -static void verify_header_signature(package2_header_t *header) { - const uint8_t *modulus; - - if (configitem_is_retail()) { - static const uint8_t package2_modulus_retail[0x100] = { - 0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, 0x20, 0x69, 0x59, - 0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE, - 0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5, - 0x6C, 0x39, 0x7F, 0x41, 0xF2, 0xFF, 0x24, 0x20, 0xC3, 0x95, 0xA6, 0xF7, 0x9D, 0x4A, 0x45, 0x74, - 0x8B, 0x5D, 0x28, 0x8A, 0xC6, 0x99, 0x35, 0x68, 0x85, 0xA5, 0x64, 0x32, 0x80, 0x9F, 0xD3, 0x48, - 0x39, 0xA2, 0x1D, 0x24, 0x67, 0x69, 0xDF, 0x75, 0xAC, 0x12, 0xB5, 0xBD, 0xC3, 0x29, 0x90, 0xBE, - 0x37, 0xE4, 0xA0, 0x80, 0x9A, 0xBE, 0x36, 0xBF, 0x1F, 0x2C, 0xAB, 0x2B, 0xAD, 0xF5, 0x97, 0x32, - 0x9A, 0x42, 0x9D, 0x09, 0x8B, 0x08, 0xF0, 0x63, 0x47, 0xA3, 0xE9, 0x1B, 0x36, 0xD8, 0x2D, 0x8A, - 0xD7, 0xE1, 0x54, 0x11, 0x95, 0xE4, 0x45, 0x88, 0x69, 0x8A, 0x2B, 0x35, 0xCE, 0xD0, 0xA5, 0x0B, - 0xD5, 0x5D, 0xAC, 0xDB, 0xAF, 0x11, 0x4D, 0xCA, 0xB8, 0x1E, 0xE7, 0x01, 0x9E, 0xF4, 0x46, 0xA3, - 0x8A, 0x94, 0x6D, 0x76, 0xBD, 0x8A, 0xC8, 0x3B, 0xD2, 0x31, 0x58, 0x0C, 0x79, 0xA8, 0x26, 0xE9, - 0xD1, 0x79, 0x9C, 0xCB, 0xD4, 0x2B, 0x6A, 0x4F, 0xC6, 0xCC, 0xCF, 0x90, 0xA7, 0xB9, 0x98, 0x47, - 0xFD, 0xFA, 0x4C, 0x6C, 0x6F, 0x81, 0x87, 0x3B, 0xCA, 0xB8, 0x50, 0xF6, 0x3E, 0x39, 0x5D, 0x4D, - 0x97, 0x3F, 0x0F, 0x35, 0x39, 0x53, 0xFB, 0xFA, 0xCD, 0xAB, 0xA8, 0x7A, 0x62, 0x9A, 0x3F, 0xF2, - 0x09, 0x27, 0x96, 0x3F, 0x07, 0x9A, 0x91, 0xF7, 0x16, 0xBF, 0xC6, 0x3A, 0x82, 0x5A, 0x4B, 0xCF, - 0x49, 0x50, 0x95, 0x8C, 0x55, 0x80, 0x7E, 0x39, 0xB1, 0x48, 0x05, 0x1E, 0x21, 0xC7, 0x24, 0x4F - }; - modulus = package2_modulus_retail; - } else { - static const uint8_t package2_modulus_dev[0x100] = { - 0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, 0xBA, 0x96, 0x99, - 0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7, - 0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6, - 0xF3, 0xBB, 0x77, 0x87, 0x46, 0x7A, 0xD6, 0x4E, 0x47, 0x4A, 0xD1, 0x41, 0xB7, 0x79, 0x4A, 0x38, - 0x06, 0x6E, 0xCF, 0x61, 0x8F, 0xCD, 0xC1, 0x40, 0x0B, 0xFA, 0x26, 0xDC, 0xC0, 0x34, 0x51, 0x83, - 0xD9, 0x3B, 0x11, 0x54, 0x3B, 0x96, 0x27, 0x32, 0x9A, 0x95, 0xBE, 0x1E, 0x68, 0x11, 0x50, 0xA0, - 0x6B, 0x10, 0xA8, 0x83, 0x8B, 0xF5, 0xFC, 0xBC, 0x90, 0x84, 0x7A, 0x5A, 0x5C, 0x43, 0x52, 0xE6, - 0xC8, 0x26, 0xE9, 0xFE, 0x06, 0xA0, 0x8B, 0x53, 0x0F, 0xAF, 0x1E, 0xC4, 0x1C, 0x0B, 0xCF, 0x50, - 0x1A, 0xA4, 0xF3, 0x5C, 0xFB, 0xF0, 0x97, 0xE4, 0xDE, 0x32, 0x0A, 0x9F, 0xE3, 0x5A, 0xAA, 0xB7, - 0x44, 0x7F, 0x5C, 0x33, 0x60, 0xB9, 0x0F, 0x22, 0x2D, 0x33, 0x2A, 0xE9, 0x69, 0x79, 0x31, 0x42, - 0x8F, 0xE4, 0x3A, 0x13, 0x8B, 0xE7, 0x26, 0xBD, 0x08, 0x87, 0x6C, 0xA6, 0xF2, 0x73, 0xF6, 0x8E, - 0xA7, 0xF2, 0xFE, 0xFB, 0x6C, 0x28, 0x66, 0x0D, 0xBD, 0xD7, 0xEB, 0x42, 0xA8, 0x78, 0xE6, 0xB8, - 0x6B, 0xAE, 0xC7, 0xA9, 0xE2, 0x40, 0x6E, 0x89, 0x20, 0x82, 0x25, 0x8E, 0x3C, 0x6A, 0x60, 0xD7, - 0xF3, 0x56, 0x8E, 0xEC, 0x8D, 0x51, 0x8A, 0x63, 0x3C, 0x04, 0x78, 0x23, 0x0E, 0x90, 0x0C, 0xB4, - 0xE7, 0x86, 0x3B, 0x4F, 0x8E, 0x13, 0x09, 0x47, 0x32, 0x0E, 0x04, 0xB8, 0x4D, 0x5B, 0xB0, 0x46, - 0x71, 0xB0, 0x5C, 0xF4, 0xAD, 0x63, 0x4F, 0xC5, 0xE2, 0xAC, 0x1E, 0xC4, 0x33, 0x96, 0x09, 0x7B - }; - modulus = package2_modulus_dev; - } - - /* This is normally only allowed on dev units, but we'll allow it anywhere. */ - bool is_unsigned = EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG || bootconfig_is_package2_unsigned(); - if (!is_unsigned && se_rsa2048_pss_verify(header->signature, 0x100, modulus, 0x100, header->encrypted_header, 0x100) == 0) { - panic(0xF0000001); /* Invalid PK21 signature. */ - } -} - -static uint32_t get_package2_size(package2_meta_t *metadata) { - return metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3]; -} - -static bool validate_package2_metadata(package2_meta_t *metadata) { - if (metadata->magic != MAGIC_PK21) { - return false; - } - - - /* Package2 size, version number is stored XORed in header CTR. */ - /* Nintendo, what the fuck? */ - uint32_t package_size = metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3]; - uint8_t header_version = (uint8_t)((metadata->ctr_dwords[1] ^ (metadata->ctr_dwords[1] >> 16) ^ (metadata->ctr_dwords[1] >> 24)) & 0xFF); - - /* Ensure package isn't too big or too small. */ - if (package_size <= sizeof(package2_header_t) || package_size > PACKAGE2_SIZE_MAX) { - return false; - } - - /* Validate that we're working with a header we know how to handle. */ - if (header_version > MASTERKEY_REVISION_MAX) { - return false; - } - - /* Require aligned entrypoint. */ - if (metadata->entrypoint & 3) { - return false; - } - - /* Validate section size sanity. */ - if (metadata->section_sizes[0] + metadata->section_sizes[1] + metadata->section_sizes[2] + sizeof(package2_header_t) != package_size) { - return false; - } - - bool entrypoint_found = false; - - /* Header has space for 4 sections, but only 3 are validated/potentially loaded on hardware. */ - size_t cur_section_offset = 0; - for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) { - /* Validate section size alignment. */ - if (metadata->section_sizes[section] & 3) { - return false; - } - - /* Validate section does not overflow. */ - if (check_32bit_additive_overflow(metadata->section_offsets[section], metadata->section_sizes[section])) { - return false; - } - - /* Check for entrypoint presence. */ - uint32_t section_end = metadata->section_offsets[section] + metadata->section_sizes[section]; - if (metadata->section_offsets[section] <= metadata->entrypoint && metadata->entrypoint < section_end) { - entrypoint_found = true; - } - - /* Ensure no overlap with later sections. */ - if (metadata->section_sizes[section] != 0) { - for (unsigned int later_section = section + 1; later_section < PACKAGE2_SECTION_MAX; later_section++) { - if (metadata->section_sizes[later_section] == 0) { - continue; - } - uint32_t later_section_end = metadata->section_offsets[later_section] + metadata->section_sizes[later_section]; - if (overlaps(metadata->section_offsets[section], section_end, metadata->section_offsets[later_section], later_section_end)) { - return false; - } - } - } - - bool check_hash = EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG == 0; - /* Validate section hashes. */ - if (metadata->section_sizes[section]) { - void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + cur_section_offset); - uint8_t calculated_hash[0x20]; - flush_dcache_range((uint8_t *)section_data, (uint8_t *)section_data + metadata->section_sizes[section]); - se_calculate_sha256(calculated_hash, section_data, metadata->section_sizes[section]); - if (check_hash && memcmp(calculated_hash, metadata->section_hashes[section], sizeof(metadata->section_hashes[section])) != 0) { - return false; - } - cur_section_offset += metadata->section_sizes[section]; - } - - } - - /* Ensure that entrypoint is present in one of our sections. */ - if (!entrypoint_found) { - return false; - } - - /* Perform version checks. */ - /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_1000_CURRENT) { - return true; - } - - return false; -} - -/* Decrypts package2 header, and returns the master key revision required. */ -static uint32_t decrypt_and_validate_header(package2_header_t *header) { - package2_meta_t metadata; - - if (bootconfig_is_package2_plaintext() == 0) { - uint32_t mkey_rev; - - /* Try to decrypt for all possible master keys. */ - for (mkey_rev = 0; mkey_rev <= mkey_get_revision(); mkey_rev++) { - package2_crypt_ctr(mkey_rev, &metadata, sizeof(package2_meta_t), &header->metadata, sizeof(package2_meta_t), header->metadata.ctr, sizeof(header->metadata.ctr)); - /* Copy the ctr (which stores information) into the decrypted metadata. */ - memcpy(metadata.ctr, header->metadata.ctr, sizeof(header->metadata.ctr)); - /* See if this is the correct key. */ - if (validate_package2_metadata(&metadata)) { - header->metadata = metadata; - return mkey_rev; - } - } - - /* Ensure we successfully decrypted the header. */ - if (mkey_rev > mkey_get_revision()) { - panic(0xFAF00003); - } - } else if (!validate_package2_metadata(&header->metadata)) { - panic(0xFAF0003); - } - return 0; -} - -static void load_package2_sections(package2_meta_t *metadata, uint32_t master_key_rev) { - /* By default, copy data directly from where NX_BOOTLOADER puts it. */ - void *load_buf = NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS; - - /* Check whether any of our sections overlap this region. If they do, we must relocate and copy from elsewhere. */ - bool needs_relocation = false; - for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) { - uint64_t section_start = DRAM_BASE_PHYSICAL + (uint64_t)metadata->section_offsets[section]; - uint64_t section_end = section_start + (uint64_t)metadata->section_sizes[section]; - if (overlaps(section_start, section_end, (uint64_t)(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS), (uint64_t)(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS) + PACKAGE2_SIZE_MAX)) { - needs_relocation = true; - } - } - if (needs_relocation) { - /* This code should *always* succeed in finding a carveout within seven loops, */ - /* due to the section size limit, and section number limit. */ - /* However, Nintendo tries panics after 8 loops if a safe section is not found. */ - /* This should never be the case, mathematically. */ - /* We will replicate this behavior. */ - bool found_safe_carveout = false; - uint64_t potential_base_start = DRAM_BASE_PHYSICAL; - uint64_t potential_base_end = potential_base_start + PACKAGE2_SIZE_MAX; - for (unsigned int i = 0; i < 8; i++) { - int is_safe = 1; - for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) { - uint64_t section_start = DRAM_BASE_PHYSICAL + (uint64_t)metadata->section_offsets[section]; - uint64_t section_end = section_start + (uint64_t)metadata->section_sizes[section]; - if (overlaps(section_start, section_end, potential_base_start, potential_base_end)) { - is_safe = 0; - } - } - found_safe_carveout |= is_safe; - if (found_safe_carveout) { - break; - } - potential_base_start += PACKAGE2_SIZE_MAX; - potential_base_end += PACKAGE2_SIZE_MAX; - } - if (!found_safe_carveout) { - generic_panic(); - } - /* Relocate to new carveout. */ - memcpy((void *)potential_base_start, load_buf, PACKAGE2_SIZE_MAX); - memset(load_buf, 0, PACKAGE2_SIZE_MAX); - load_buf = (void *)potential_base_start; - } - - size_t cur_section_offset = 0; - /* Copy each section to its appropriate location, decrypting if necessary. */ - for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) { - if (metadata->section_sizes[section] == 0) { - continue; - } - - void *dst_start = (void *)(DRAM_BASE_PHYSICAL + (uint64_t)metadata->section_offsets[section]); - void *src_start = load_buf + sizeof(package2_header_t) + cur_section_offset; - size_t size = (size_t)metadata->section_sizes[section]; - - if (bootconfig_is_package2_plaintext() && size != 0) { - memcpy(dst_start, src_start, size); - } else if (size != 0) { - package2_crypt_ctr(master_key_rev, dst_start, size, src_start, size, metadata->section_ctrs[section], 0x10); - } - cur_section_offset += size; - } - - /* Clear the encrypted package2 from memory. */ - memset(load_buf, 0, PACKAGE2_SIZE_MAX); -} - -static void copy_warmboot_bin_to_dram() { - uint8_t *warmboot_src; - - { - const uint32_t target_fw = exosphere_get_target_firmware(); - if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { - warmboot_src = (uint8_t *)0x4003E000; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - warmboot_src = (uint8_t *)0x4003D800; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - warmboot_src = (uint8_t *)0x4003B000; - } else { - return; - } - } - - uint8_t *warmboot_dst = (uint8_t *)0x8000D000; - const size_t warmboot_size = 0x2000; - - /* Flush cache, to ensure warmboot is where we need it to be. */ - flush_dcache_range(warmboot_src, warmboot_src + warmboot_size); - __dsb_sy(); - - /* Copy warmboot. */ - for (size_t i = 0; i < warmboot_size; i += sizeof(uint32_t)) { - write32le(warmboot_dst, i, read32le(warmboot_src, i)); - } - - /* Flush cache, to ensure warmboot is where we need it to be. */ - flush_dcache_range(warmboot_dst, warmboot_dst + warmboot_size); - __dsb_sy(); -} - -static void sync_with_nx_bootloader(int state) { - while (MAILBOX_NX_BOOTLOADER_SETUP_STATE(exosphere_get_target_firmware()) < state) { - wait(100); - } -} - -static void identity_unmap_dram(void) { - uintptr_t *mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - - mmu_unmap_range(1, mmu_l1_tbl, IDENTITY_GET_MAPPING_ADDRESS(IDENTITY_MAPPING_DRAM), IDENTITY_GET_MAPPING_SIZE(IDENTITY_MAPPING_DRAM)); - tlb_invalidate_all_inner_shareable(); -} - -uintptr_t get_pk2ldr_stack_address(void) { - return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_PK2LDR) + 0x2000; -} - -/* This function is called during coldboot init, and validates a package2. */ -/* This package2 is read into memory by a concurrent BPMP bootloader. */ -void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { - /* Load Exosphere-specific config. */ - exosphere_load_config(); - configitem_set_debugmode_override(exosphere_should_override_debugmode_user() != 0, exosphere_should_override_debugmode_priv() != 0); - if (exosphere_should_disable_usermode_exception_handlers() != 0) { - configitem_disable_usermode_exception_handlers(); - } - if (exosphere_should_enable_usermode_pmu_access()) { - configitem_enable_usermode_pmu_access(); - } - - /* Setup the Security Engine. */ - setup_se(); - - /* Perform initial PMC register writes, if relevant. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000; - MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF; - MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE; - MAKE_REG32(PMC_BASE + 0x334) |= 0x10; - - const uint32_t target_fw = exosphere_get_target_firmware(); - if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x105; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_9_1_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x18C; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x16B; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x14A; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x129; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x0A8; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x087; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x006; - } else if (target_fw >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - MAKE_REG32(PMC_BASE + 0x360) = 0x105; - } - } - - wait(1000); - - bootup_misc_mmio(); - - setup_current_core_state(); - - /* Save boot reason to global. */ - bootconfig_load_boot_reason((volatile boot_reason_t *)(MAILBOX_NX_BOOTLOADER_BOOT_REASON(exosphere_get_target_firmware()))); - - /* Initialize cache'd random bytes for kernel. */ - randomcache_init(); - - /* memclear the initial copy of Exosphere running in IRAM (relocated to TZRAM by earlier code). */ - /* memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); */ - - /* Let NX Bootloader know that we're running. */ - MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(exosphere_get_target_firmware()) = 1; - - /* Wait for 1 second, to allow time for NX_BOOTLOADER to draw to the screen. This is useful for debugging. */ - /* wait(1000000); */ - - /* Synchronize with NX BOOTLOADER. */ - sync_with_nx_bootloader(NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG); - - /* Load Boot Config into global. */ - setup_boot_config(); - - /* Set sysctr0 registers based on bootconfig. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - uint64_t sysctr0_val = bootconfig_get_value_for_sysctr0(); - MAKE_SYSCTR0_REG(0x8) = (uint32_t)((sysctr0_val >> 0) & 0xFFFFFFFFULL); - MAKE_SYSCTR0_REG(0xC) = (uint32_t)((sysctr0_val >> 32) & 0xFFFFFFFFULL); - MAKE_SYSCTR0_REG(0x0) = 3; - } - - /* Synchronize with NX BOOTLOADER. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X); - copy_warmboot_bin_to_dram(); - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - setup_dram_magic_numbers(); - } - sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X); - } else { - sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2); - } - - /* Make PMC (2.x+), MC (4.x+) registers secure-only */ - secure_additional_devices(); - - /* Remove the identity mapping for iRAM-C+D & TZRAM */ - /* For our crt0 to work, this doesn't actually unmap TZRAM */ - identity_unmap_iram_cd_tzram(); - - /* Load header from NX_BOOTLOADER-initialized DRAM. */ - package2_header_t header; - flush_dcache_range((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, (uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(header)); - memcpy(&header, NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, sizeof(header)); - flush_dcache_range((uint8_t *)&header, (uint8_t *)&header + sizeof(header)); - - /* Perform signature checks. */ - /* Special exosphere patching enable: All-zeroes signature + decrypted header implies unsigned and decrypted package2. */ - if (header.signature[0] == 0 && memcmp(header.signature, header.signature + 1, sizeof(header.signature) - 1) == 0 && header.metadata.magic == MAGIC_PK21) { - bootconfig_set_package2_plaintext_and_unsigned(); - } - - verify_header_signature(&header); - - /* Decrypt header, get key revision required. */ - uint32_t package2_mkey_rev = decrypt_and_validate_header(&header); - - /* Copy hash, if necessary. */ - if (bootconfig_is_recovery_boot()) { - bootconfig_set_package2_hash_for_recovery(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, get_package2_size(&header.metadata)); - } - - /* Load Package2 Sections. */ - load_package2_sections(&header.metadata, package2_mkey_rev); - - /* Clean up cache. */ - flush_dcache_all(); - invalidate_icache_all(); /* non-broadcasting */ - - /* Set CORE0 entrypoint for Package2. */ - set_core_entrypoint_and_argument(0, DRAM_BASE_PHYSICAL + header.metadata.entrypoint, 0); - - /* Remove the DRAM identity mapping. */ - if (0) { - identity_unmap_dram(); - } - - /* Synchronize with NX BOOTLOADER. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X); - setup_4x_mmio(); - } else { - sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED); - } - - /* Prepare the SMC API with version-dependent SMCs. */ - set_version_specific_smcs(); - - /* Update SCR_EL3 depending on value in Bootconfig. */ - set_extabt_serror_taken_to_el3(bootconfig_take_extabt_serror_to_el3()); -} diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h deleted file mode 100644 index ab2d9d01e..000000000 --- a/exosphere/src/package2.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_PACKAGE2_H -#define EXOSPHERE_PACKAGE2_H - -/* This is code responsible for validating a package2. Actual file reading is done by bootloader. */ - -#include "utils.h" -#include "bootconfig.h" -#include "exocfg.h" -#include "memory_map.h" - -/* Physaddr 0x40002EF8 */ -static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX) + ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) ? (0x000ull) : (0xE00ull)); -} - -#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (get_nx_bootloader_mailbox_base(targetfw)) - -#define MAILBOX_NX_SECMON_BOOT_TIME(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x08ull) - -#define MAILBOX_NX_BOOTLOADER_SETUP_STATE(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0xF8ull) - -#define NX_BOOTLOADER_STATE_INIT 0 -#define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 - -#define NX_BOOTLOADER_STATE_LOADED_PACKAGE2 2 -#define NX_BOOTLOADER_STATE_FINISHED 3 - -#define NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X 2 -#define NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X 3 -#define NX_BOOTLOADER_STATE_FINISHED_4X 4 - -/* Physaddr 0x40002EFC */ -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0xFCULL) - -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10ULL) - -#define NX_BOOTLOADER_BOOTCONFIG_POINTER ((void *)(0x4003D000ull)) -#define NX_BOOTLOADER_BOOTCONFIG_POINTER_6X ((void *)(0x4003F800ull)) - -#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) - -#define DRAM_BASE_PHYSICAL (0x80000000ull) - -#define MAGIC_PK21 (0x31324B50) -#define PACKAGE2_SIZE_MAX 0x7FC000 -#define PACKAGE2_SECTION_MAX 0x3 - -#define PACKAGE2_MINVER_THEORETICAL 0x0 -#define PACKAGE2_MAXVER_100 0x2 -#define PACKAGE2_MAXVER_200 0x3 -#define PACKAGE2_MAXVER_300 0x4 -#define PACKAGE2_MAXVER_302 0x5 -#define PACKAGE2_MAXVER_400_410 0x6 -#define PACKAGE2_MAXVER_500_510 0x7 -#define PACKAGE2_MAXVER_600_610 0x8 -#define PACKAGE2_MAXVER_620 0x9 -#define PACKAGE2_MAXVER_700_800 0xA -#define PACKAGE2_MAXVER_810 0xB -#define PACKAGE2_MAXVER_900 0xC -#define PACKAGE2_MAXVER_910_920 0xD -#define PACKAGE2_MAXVER_1000_CURRENT 0xE - -#define PACKAGE2_MINVER_100 0x3 -#define PACKAGE2_MINVER_200 0x4 -#define PACKAGE2_MINVER_300 0x5 -#define PACKAGE2_MINVER_302 0x6 -#define PACKAGE2_MINVER_400_410 0x7 -#define PACKAGE2_MINVER_500_510 0x8 -#define PACKAGE2_MINVER_600_610 0x9 -#define PACKAGE2_MINVER_620 0xA -#define PACKAGE2_MINVER_700_800 0xB -#define PACKAGE2_MINVER_810 0xC -#define PACKAGE2_MINVER_900 0xD -#define PACKAGE2_MINVER_910_920 0xE -#define PACKAGE2_MINVER_1000_CURRENT 0xF - -typedef struct { - union { - uint8_t ctr[0x10]; - uint32_t ctr_dwords[0x4]; - }; - uint8_t section_ctrs[4][0x10]; - uint32_t magic; - uint32_t entrypoint; - uint32_t _0x58; - uint8_t version_max; /* Must be > TZ value. */ - uint8_t version_min; /* Must be < TZ value. */ - uint16_t _0x5E; - uint32_t section_sizes[4]; - uint32_t section_offsets[4]; - uint8_t section_hashes[4][0x20]; -} package2_meta_t; - -typedef struct { - uint8_t signature[0x100]; - union { - package2_meta_t metadata; - uint8_t encrypted_header[0x100]; - }; - uint8_t data[]; -} package2_header_t; - -void load_package2(coldboot_crt0_reloc_list_t *reloc_list); - -#endif diff --git a/exosphere/src/panic_color.h b/exosphere/src/panic_color.h deleted file mode 100644 index 3dc0d5f79..000000000 --- a/exosphere/src/panic_color.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_PANIC_COLOR_H -#define EXOSPHERE_PANIC_COLOR_H - -#define COLOR_0 0x00F00003 -#define COLOR_1 0x0F000003 -#define COLOR_2 0xF0000003 -#define COLOR_3 0x0FF00003 -#define COLOR_4 0xF0F00003 -#define COLOR_5 0xFF000003 -#define COLOR_6 0xFFF00003 -#define COLOR_7 0xAAF00003 -#define COLOR_8 0xAFA00003 -#define COLOR_9 0xFAA00003 -#define COLOR_A 0x33300003 -#define COLOR_B 0x06F00003 -#define COLOR_C 0x14800003 -#define COLOR_D 0x00300003 -#define COLOR_E 0x03000003 -#define COLOR_F 0xB6000003 - -#define PANIC_REBOOT 0x20 - -#endif \ No newline at end of file diff --git a/exosphere/src/pinmux.h b/exosphere/src/pinmux.h deleted file mode 100644 index f5c402204..000000000 --- a/exosphere/src/pinmux.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_PINMUX_H -#define EXOSPHERE_PINMUX_H - -#include -#include "memory_map.h" - -#define PINMUX_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MISC) + 0x3000) -#define MAKE_PINMUX_REG(n) MAKE_REG32(PINMUX_BASE + n) - -#define PINMUX_TRISTATE (1 << 4) -#define PINMUX_PARKED (1 << 5) -#define PINMUX_INPUT (1 << 6) -#define PINMUX_PULL_NONE (0 << 2) -#define PINMUX_PULL_DOWN (1 << 2) -#define PINMUX_PULL_UP (2 << 2) -#define PINMUX_SELECT_FUNCTION0 0 -#define PINMUX_SELECT_FUNCTION1 1 -#define PINMUX_SELECT_FUNCTION2 2 -#define PINMUX_SELECT_FUNCTION3 3 -#define PINMUX_DRIVE_1X (0 << 13) -#define PINMUX_DRIVE_2X (1 << 13) -#define PINMUX_DRIVE_3X (2 << 13) -#define PINMUX_DRIVE_4X (3 << 13) - -typedef struct { - uint32_t sdmmc1_clk; - uint32_t sdmmc1_cmd; - uint32_t sdmmc1_dat3; - uint32_t sdmmc1_dat2; - uint32_t sdmmc1_dat1; - uint32_t sdmmc1_dat0; - uint32_t _r18; - uint32_t sdmmc3_clk; - uint32_t sdmmc3_cmd; - uint32_t sdmmc3_dat0; - uint32_t sdmmc3_dat1; - uint32_t sdmmc3_dat2; - uint32_t sdmmc3_dat3; - uint32_t _r34; - uint32_t pex_l0_rst_n; - uint32_t pex_l0_clkreq_n; - uint32_t pex_wake_n; - uint32_t pex_l1_rst_n; - uint32_t pex_l1_clkreq_n; - uint32_t sata_led_active; - uint32_t spi1_mosi; - uint32_t spi1_miso; - uint32_t spi1_sck; - uint32_t spi1_cs0; - uint32_t spi1_cs1; - uint32_t spi2_mosi; - uint32_t spi2_miso; - uint32_t spi2_sck; - uint32_t spi2_cs0; - uint32_t spi2_cs1; - uint32_t spi4_mosi; - uint32_t spi4_miso; - uint32_t spi4_sck; - uint32_t spi4_cs0; - uint32_t qspi_sck; - uint32_t qspi_cs_n; - uint32_t qspi_io0; - uint32_t qspi_io1; - uint32_t qspi_io2; - uint32_t qspi_io3; - uint32_t _ra0; - uint32_t dmic1_clk; - uint32_t dmic1_dat; - uint32_t dmic2_clk; - uint32_t dmic2_dat; - uint32_t dmic3_clk; - uint32_t dmic3_dat; - uint32_t gen1_i2c_scl; - uint32_t gen1_i2c_sda; - uint32_t gen2_i2c_scl; - uint32_t gen2_i2c_sda; - uint32_t gen3_i2c_scl; - uint32_t gen3_i2c_sda; - uint32_t cam_i2c_scl; - uint32_t cam_i2c_sda; - uint32_t pwr_i2c_scl; - uint32_t pwr_i2c_sda; - uint32_t uart1_tx; - uint32_t uart1_rx; - uint32_t uart1_rts; - uint32_t uart1_cts; - uint32_t uart2_tx; - uint32_t uart2_rx; - uint32_t uart2_rts; - uint32_t uart2_cts; - uint32_t uart3_tx; - uint32_t uart3_rx; - uint32_t uart3_rts; - uint32_t uart3_cts; - uint32_t uart4_tx; - uint32_t uart4_rx; - uint32_t uart4_rts; - uint32_t uart4_cts; - uint32_t dap1_fs; - uint32_t dap1_din; - uint32_t dap1_dout; - uint32_t dap1_sclk; - uint32_t dap2_fs; - uint32_t dap2_din; - uint32_t dap2_dout; - uint32_t dap2_sclk; - uint32_t dap4_fs; - uint32_t dap4_din; - uint32_t dap4_dout; - uint32_t dap4_sclk; - uint32_t cam1_mclk; - uint32_t cam2_mclk; - uint32_t jtag_rtck; - uint32_t clk_32k_in; - uint32_t clk_32k_out; - uint32_t batt_bcl; - uint32_t clk_req; - uint32_t cpu_pwr_req; - uint32_t pwr_int_n; - uint32_t shutdown; - uint32_t core_pwr_req; - uint32_t aud_mclk; - uint32_t dvfs_pwm; - uint32_t dvfs_clk; - uint32_t gpio_x1_aud; - uint32_t gpio_x3_aud; - uint32_t pcc7; - uint32_t hdmi_cec; - uint32_t hdmi_int_dp_hpd; - uint32_t spdif_out; - uint32_t spdif_in; - uint32_t usb_vbus_en0; - uint32_t usb_vbus_en1; - uint32_t dp_hpd0; - uint32_t wifi_en; - uint32_t wifi_rst; - uint32_t wifi_wake_ap; - uint32_t ap_wake_bt; - uint32_t bt_rst; - uint32_t bt_wake_ap; - uint32_t ap_wake_nfc; - uint32_t nfc_en; - uint32_t nfc_int; - uint32_t gps_en; - uint32_t gps_rst; - uint32_t cam_rst; - uint32_t cam_af_en; - uint32_t cam_flash_en; - uint32_t cam1_pwdn; - uint32_t cam2_pwdn; - uint32_t cam1_strobe; - uint32_t lcd_te; - uint32_t lcd_bl_pwm; - uint32_t lcd_bl_en; - uint32_t lcd_rst; - uint32_t lcd_gpio1; - uint32_t lcd_gpio2; - uint32_t ap_ready; - uint32_t touch_rst; - uint32_t touch_clk; - uint32_t modem_wake_ap; - uint32_t touch_int; - uint32_t motion_int; - uint32_t als_prox_int; - uint32_t temp_alert; - uint32_t button_power_on; - uint32_t button_vol_up; - uint32_t button_vol_down; - uint32_t button_slide_sw; - uint32_t button_home; - uint32_t pa6; - uint32_t pe6; - uint32_t pe7; - uint32_t ph6; - uint32_t pk0; - uint32_t pk1; - uint32_t pk2; - uint32_t pk3; - uint32_t pk4; - uint32_t pk5; - uint32_t pk6; - uint32_t pk7; - uint32_t pl0; - uint32_t pl1; - uint32_t pz0; - uint32_t pz1; - uint32_t pz2; - uint32_t pz3; - uint32_t pz4; - uint32_t pz5; -} tegra_pinmux_t; - -static inline volatile tegra_pinmux_t *pinmux_get_regs(void) -{ - return (volatile tegra_pinmux_t *)PINMUX_BASE; -} - -#endif diff --git a/exosphere/src/pmc.h b/exosphere/src/pmc.h deleted file mode 100644 index 24c851534..000000000 --- a/exosphere/src/pmc.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_PMC_H -#define EXOSPHERE_PMC_H - -#include -#include "memory_map.h" - -/* Exosphere register definitions for the Tegra X1 PMC. */ - -static inline uintptr_t get_pmc_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull; -} - -#define PMC_BASE (get_pmc_base()) - -#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24) -#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30) -#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38) -#define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50) -#define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4) -#define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14) -#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168) -#define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440) -#define APBDEV_PMC_FUSE_CTRL MAKE_REG32(PMC_BASE + 0x450) -#define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C) -#define APBDEV_PMC_SEC_DISABLE8_0 MAKE_REG32(PMC_BASE + 0x5C0) -#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_REG32(PMC_BASE + 0xB18) -#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_REG32(PMC_BASE + 0xB1C) -#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_REG32(PMC_BASE + 0xB20) -#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_REG32(PMC_BASE + 0xB24) -#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840) -#define APBDEV_PMC_SEC_DISABLE3_0 MAKE_REG32(PMC_BASE + 0x2D8) -#define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_REG32(PMC_BASE + 0x368) -#define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_REG32(PMC_BASE + 0x36C) -#define APBDEV_PMC_SECURE_SCRATCH16_0 MAKE_REG32(PMC_BASE + 0x320) -#define APBDEV_PMC_SECURE_SCRATCH51_0 MAKE_REG32(PMC_BASE + 0x3AC) -#define APBDEV_PMC_SECURE_SCRATCH55_0 MAKE_REG32(PMC_BASE + 0x3BC) -#define APBDEV_PMC_SECURE_SCRATCH74_0 MAKE_REG32(PMC_BASE + 0x408) -#define APBDEV_PMC_SECURE_SCRATCH75_0 MAKE_REG32(PMC_BASE + 0x40C) -#define APBDEV_PMC_SECURE_SCRATCH76_0 MAKE_REG32(PMC_BASE + 0x410) -#define APBDEV_PMC_SECURE_SCRATCH77_0 MAKE_REG32(PMC_BASE + 0x414) -#define APBDEV_PMC_SECURE_SCRATCH78_0 MAKE_REG32(PMC_BASE + 0x418) -#define APBDEV_PMC_SECURE_SCRATCH99_0 MAKE_REG32(PMC_BASE + 0xAE4) -#define APBDEV_PMC_SECURE_SCRATCH100_0 MAKE_REG32(PMC_BASE + 0xAE8) -#define APBDEV_PMC_SECURE_SCRATCH101_0 MAKE_REG32(PMC_BASE + 0xAEC) -#define APBDEV_PMC_SECURE_SCRATCH102_0 MAKE_REG32(PMC_BASE + 0xAF0) -#define APBDEV_PMC_SECURE_SCRATCH103_0 MAKE_REG32(PMC_BASE + 0xAF4) -#define APBDEV_PMC_SECURE_SCRATCH39_0 MAKE_REG32(PMC_BASE + 0x37C) - -#endif diff --git a/exosphere/src/preprocessor.h b/exosphere/src/preprocessor.h deleted file mode 100644 index 3710c8317..000000000 --- a/exosphere/src/preprocessor.h +++ /dev/null @@ -1,207 +0,0 @@ -/* TuxSH: I added INC/DEC_10 to INC/DEC_32; tuples */ - -#ifndef EXOSPHERE_PREPROCESSOR_H -#define EXOSPHERE_PREPROCESSOR_H - -/*============================================================================= - Copyright (c) 2015 Paul Fultz II - cloak.h - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ - -/*#ifndef CLOAK_GUARD_H -#define CLOAK_GUARD_H*/ - -#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) -#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ - -#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) -#define COMPL_0 1 -#define COMPL_1 0 - -#define BITAND(x) PRIMITIVE_CAT(BITAND_, x) -#define BITAND_0(y) 0 -#define BITAND_1(y) y - -#define INC(x) PRIMITIVE_CAT(INC_, x) -#define INC_0 1 -#define INC_1 2 -#define INC_2 3 -#define INC_3 4 -#define INC_4 5 -#define INC_5 6 -#define INC_6 7 -#define INC_7 8 -#define INC_8 9 -#define INC_9 10 -#define INC_10 11 -#define INC_11 12 -#define INC_12 13 -#define INC_13 14 -#define INC_14 15 -#define INC_15 16 -#define INC_16 17 -#define INC_17 18 -#define INC_18 19 -#define INC_19 20 -#define INC_20 21 -#define INC_21 22 -#define INC_22 23 -#define INC_23 24 -#define INC_24 25 -#define INC_25 26 -#define INC_26 27 -#define INC_27 28 -#define INC_28 29 -#define INC_29 30 -#define INC_30 31 -#define INC_31 32 -#define INC_32 32 -#define INC_33 33 - -#define DEC(x) PRIMITIVE_CAT(DEC_, x) -#define DEC_0 0 -#define DEC_1 0 -#define DEC_2 1 -#define DEC_3 2 -#define DEC_4 3 -#define DEC_5 4 -#define DEC_6 5 -#define DEC_7 6 -#define DEC_8 7 -#define DEC_9 8 -#define DEC_10 9 -#define DEC_11 10 -#define DEC_12 11 -#define DEC_13 12 -#define DEC_14 13 -#define DEC_15 14 -#define DEC_16 15 -#define DEC_17 16 -#define DEC_18 17 -#define DEC_19 18 -#define DEC_20 19 -#define DEC_21 20 -#define DEC_22 21 -#define DEC_23 22 -#define DEC_24 23 -#define DEC_25 24 -#define DEC_26 25 -#define DEC_27 26 -#define DEC_28 27 -#define DEC_29 28 -#define DEC_30 29 -#define DEC_31 30 -#define DEC_32 31 -#define DEC_33 32 - -#define CHECK_N(x, n, ...) n -#define CHECK(...) CHECK_N(__VA_ARGS__, 0,) -#define PROBE(x) x, 1, - -#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x) -#define IS_PAREN_PROBE(...) PROBE(~) - -#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) -#define NOT_0 PROBE(~) - -#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) -#define COMPL_0 1 -#define COMPL_1 0 - -#define BOOL(x) COMPL(NOT(x)) - -#define IIF(c) PRIMITIVE_CAT(IIF_, c) -#define IIF_0(t, ...) __VA_ARGS__ -#define IIF_1(t, ...) t - -#define IF(c) IIF(BOOL(c)) - -#define EAT(...) -#define EXPAND(...) __VA_ARGS__ -#define WHEN(c) IF(c)(EXPAND, EAT) - -#define EMPTY() -#define DEFER(id) id EMPTY() -#define OBSTRUCT(id) id DEFER(EMPTY)() - -#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) -#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) -#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) -#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) -#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) -#define EVAL5(...) __VA_ARGS__ - -#define REPEAT(count, macro, ...) \ - WHEN(count) \ - ( \ - OBSTRUCT(REPEAT_INDIRECT) () \ - ( \ - DEC(count), macro, __VA_ARGS__ \ - ) \ - OBSTRUCT(macro) \ - ( \ - DEC(count), __VA_ARGS__ \ - ) \ - ) -#define REPEAT_INDIRECT() REPEAT - -#define WHILE(pred, op, ...) \ - IF(pred(__VA_ARGS__)) \ - ( \ - OBSTRUCT(WHILE_INDIRECT) () \ - ( \ - pred, op, op(__VA_ARGS__) \ - ), \ - __VA_ARGS__ \ - ) -#define WHILE_INDIRECT() WHILE - -#define PRIMITIVE_COMPARE(x, y) IS_PAREN \ -( \ - COMPARE_ ## x ( COMPARE_ ## y) (()) \ -) - -#define IS_COMPARABLE(x) IS_PAREN( CAT(COMPARE_, x) (()) ) - -#define NOT_EQUAL(x, y) \ -IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y)) ) \ -( \ - PRIMITIVE_COMPARE, \ - 1 EAT \ -)(x, y) - -#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y)) - -#define COMMA() , - -#define COMMA_IF(n) IF(n)(COMMA, EAT)() - -#define PLUS() + - -#define _TUPLE_ELEM_0(a, ...) a -#define _TUPLE_ELEM_1(a, b, ...) b -#define _TUPLE_ELEM_2(a, b, c, ...) c -#define _TUPLE_ELEM_3(a, b, c, d, ...) d -#define _TUPLE_ELEM_4(a, b, c, d, e, ...) e - -#define TUPLE_ELEM_0(T) EVAL(_TUPLE_ELEM_0 T) -#define TUPLE_ELEM_1(T) EVAL(_TUPLE_ELEM_1 T) -#define TUPLE_ELEM_2(T) EVAL(_TUPLE_ELEM_2 T) -#define TUPLE_ELEM_3(T) EVAL(_TUPLE_ELEM_3 T) -#define TUPLE_ELEM_4(T) EVAL(_TUPLE_ELEM_4 T) - -#define _TUPLE_FOLD_LEFT_0(i, T, op) (_TUPLE_ELEM_0 CAT(T,i)) op() -#define _TUPLE_FOLD_LEFT_1(i, T, op) (_TUPLE_ELEM_1 CAT(T,i)) op() -#define _TUPLE_FOLD_LEFT_2(i, T, op) (_TUPLE_ELEM_2 CAT(T,i)) op() -#define _TUPLE_FOLD_LEFT_3(i, T, op) (_TUPLE_ELEM_3 CAT(T,i)) op() -#define _TUPLE_FOLD_LEFT_4(i, T, op) (_TUPLE_ELEM_4 CAT(T,i)) op() - -#define TUPLE_FOLD_LEFT_0(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_0, T, op)) -#define TUPLE_FOLD_LEFT_1(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_1, T, op)) -#define TUPLE_FOLD_LEFT_2(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_2, T, op)) -#define TUPLE_FOLD_LEFT_3(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_3, T, op)) -#define TUPLE_FOLD_LEFT_4(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_4, T, op)) - -#endif diff --git a/exosphere/src/randomcache.c b/exosphere/src/randomcache.c deleted file mode 100644 index 08e9f475c..000000000 --- a/exosphere/src/randomcache.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "randomcache.h" -#include "se.h" -#include "arm.h" - -/* TrustZone maintains a cache of random for the kernel. */ -/* So that requests can still be serviced even when a */ -/* usermode SMC is in progress. */ - -static uint8_t g_random_cache[0x400]; -static unsigned int g_random_cache_low = 0; -static unsigned int g_random_cache_high = 0x3FF; - - -void randomcache_refill_segment(unsigned int offset, unsigned int size) { - if (offset + size >= 0x400) { - size = 0x400 - offset; - } - - flush_dcache_range(&g_random_cache[offset], &g_random_cache[offset + size]); - se_generate_random(KEYSLOT_SWITCH_RNGKEY, &g_random_cache[offset], size); - flush_dcache_range(&g_random_cache[offset], &g_random_cache[offset + size]); - -} - -void randomcache_init(void) { - randomcache_refill_segment(0, 0x400); - g_random_cache_low = 0; - g_random_cache_high = 0x3FF; -} - -void randomcache_refill(void) { - unsigned int high_plus_one = (g_random_cache_high + 1) & 0x3FF; - if (g_random_cache_low != high_plus_one) { - /* Only refill if there's data to refill. */ - if (g_random_cache_low < high_plus_one) { - /* NOTE: There is a bug in official code that causes this to not work properly. */ - /* In particular, official code checks whether high_plus_one == 0x400. */ - /* However, because high_plus_one is &= 0x3FF'd, this can never be the case. */ - /* We will implement according to Nintendo's intention, and not include their bug. */ - /* This should have no impact on actual observable results, anyway, since this data is random anyway... */ - - if (g_random_cache_high != 0x3FF) { /* This is if (true) in Nintendo's code due to the above bug. */ - randomcache_refill_segment(high_plus_one, 0x400 - high_plus_one); - g_random_cache_high = (g_random_cache_high + 0x400 - high_plus_one) & 0x3FF; - } - - if (g_random_cache_low > 0) { - randomcache_refill_segment(0, g_random_cache_low); - g_random_cache_high = (g_random_cache_high + g_random_cache_low) & 0x3FF; - } - } else { /* g_random_cache_low > high_plus_one */ - randomcache_refill_segment(high_plus_one, g_random_cache_low - high_plus_one); - g_random_cache_high = g_random_cache_low - 1; - } - } -} - -void randomcache_getbytes(void *dst, size_t num_bytes) { - unsigned int low = g_random_cache_low; - if (num_bytes == 0) { - return; - } - memcpy(dst, &g_random_cache[low], num_bytes); - - unsigned int new_low = low + num_bytes; - if (new_low + 0x38 > 0x3FF) { - new_low = 0; - } - - g_random_cache_low = new_low; -} diff --git a/exosphere/src/randomcache.h b/exosphere/src/randomcache.h deleted file mode 100644 index a7ab89e5f..000000000 --- a/exosphere/src/randomcache.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_RANDOM_CACHE_H -#define EXOSPHERE_RANDOM_CACHE_H - -#include - -/* This method must be called on startup. */ -void randomcache_init(void); -void randomcache_refill(void); - -void randomcache_getbytes(void *dst, size_t num_bytes); - - -#endif \ No newline at end of file diff --git a/exosphere/src/rsa_common.c b/exosphere/src/rsa_common.c deleted file mode 100644 index 2dfbb3c1b..000000000 --- a/exosphere/src/rsa_common.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 "rsa_common.h" - -/* Instantiate the shared RSA data inside a single translation unit. */ -rsa_shared_data_t g_rsa_shared_data = {}; \ No newline at end of file diff --git a/exosphere/src/rsa_common.h b/exosphere/src/rsa_common.h deleted file mode 100644 index 41be75c30..000000000 --- a/exosphere/src/rsa_common.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_RSA_COMMON_H -#define EXOSPHERE_RSA_COMMON_H -#include - -typedef union { - struct { - uint8_t user_data[0x100]; - } storage_exp_mod; - struct { - uint32_t master_key_rev; - uint32_t type; - uint64_t expected_label_hash[4]; - } unwrap_titlekey; -} rsa_shared_data_t __attribute__((aligned(4))); - -_Static_assert(sizeof(rsa_shared_data_t) == 0x100); - -extern rsa_shared_data_t g_rsa_shared_data; - -#endif diff --git a/exosphere/src/sc7.c b/exosphere/src/sc7.c deleted file mode 100644 index 12e28a98c..000000000 --- a/exosphere/src/sc7.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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 -#include - -#include "utils.h" - -#include "car.h" -#include "bpmp.h" -#include "arm.h" -#include "configitem.h" -#include "cpu_context.h" -#include "flow.h" -#include "fuse.h" -#include "i2c.h" -#include "sc7.h" -#include "masterkey.h" -#include "pmc.h" -#include "se.h" -#include "smc_api.h" -#include "timers.h" -#include "misc.h" -#include "uart.h" -#include "exocfg.h" - -#define u8 uint8_t -#define u32 uint32_t -#include "sc7fw_bin.h" -#undef u8 -#undef u32 - -static void configure_battery_hiz_mode(void) { - clkrst_reboot(CARDEVICE_I2C1); - - if (configitem_is_hiz_mode_enabled() && !i2c_query_ti_charger_bit_7()) { - /* Configure HiZ mode. */ - i2c_set_ti_charger_bit_7(); - uint32_t start_time = get_time(); - bool should_wait = true; - /* TODO: This is GPIO-6 GPIO_IN_1 */ - while (MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_GPIO) + 0x634) & 1) { - if (get_time() - start_time > 50000) { - should_wait = false; - break; - } - } - if (should_wait) { - wait(0x100); - } - } - clkrst_disable(CARDEVICE_I2C1); -} - -static void enable_lp0_wake_events(void) { - wait(75); - APBDEV_PMC_CNTRL2_0 |= 0x200; /* Set WAKE_DET_EN. */ - wait(75); - APBDEV_PM_0 = 0xFFFFFFFF; /* Set all wake events. */ - APBDEV_PMC_WAKE2_STATUS_0 = 0xFFFFFFFF; /* Set all wake events. */ - wait(75); -} - -static void notify_pmic_shutdown(void) { - clkrst_reboot(CARDEVICE_I2C5); - i2c_init(I2C_5); - if (fuse_get_bootrom_patch_version() >= 0x7F) { - i2c_send_pmic_cpu_shutdown_cmd(); - } -} - -static void mitigate_jamais_vu(void) { - /* Jamais Vu mitigation #1: Ensure all other cores are off. */ - if (APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00) { - generic_panic(); - } - - /* For debugging, make this check always pass. */ - if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0 || (get_debug_authentication_status() & 3) == 3)) { - FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; - } else { - FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000; - } - - /* Jamais Vu mitigation #2: Ensure the BPMP is halted. */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0 || (get_debug_authentication_status() & 3) == 3) { - /* BPMP should just be plainly halted, in debugging conditions. */ - if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x50000000) { - generic_panic(); - } - } else { - /* BPMP must be in never-woken-up halt mode, under normal conditions. */ - if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x40000000) { - generic_panic(); - } - } - - /* Jamais Vu mitigation #3: Ensure all relevant DMA controllers are held in reset. */ - if ((CLK_RST_CONTROLLER_RST_DEVICES_H_0 & 0x4000006) != 0x4000006) { - generic_panic(); - } -} - -static void configure_pmc_for_deep_powerdown(void) { - APBDEV_PMC_SCRATCH0_0 = 1; - APBDEV_PMC_DPD_ENABLE_0 |= 2; -} - -static void setup_bpmp_sc7_firmware(void) { - /* Mark PMC registers as not secure-world only, so BPMP can access them. */ - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 &= 0xFFFFDFFF; - - /* Setup BPMP vectors. */ - BPMP_VECTOR_RESET = 0x40003000; /* lp0_entry_firmware_crt0 */ - BPMP_VECTOR_UNDEF = 0x40003004; /* Reboot. */ - BPMP_VECTOR_SWI = 0x40003004; /* Reboot. */ - BPMP_VECTOR_PREFETCH_ABORT = 0x40003004; /* Reboot. */ - BPMP_VECTOR_DATA_ABORT = 0x40003004; /* Reboot. */ - BPMP_VECTOR_UNK = 0x40003004; /* Reboot. */ - BPMP_VECTOR_IRQ = 0x40003004; /* Reboot. */ - BPMP_VECTOR_FIQ = 0x40003004; /* Reboot. */ - - /* Hold the BPMP in reset. */ - MAKE_CAR_REG(0x300) = 2; - - /* Copy BPMP firmware. */ - uint8_t *lp0_entry_code = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE)); - for (unsigned int i = 0; i < sc7fw_bin_size; i += 4) { - write32le(lp0_entry_code, i, read32le(sc7fw_bin, i)); - } - - flush_dcache_range(lp0_entry_code, lp0_entry_code + sc7fw_bin_size); - - /* Take the BPMP out of reset. */ - MAKE_CAR_REG(0x304) = 2; - - /* Start executing BPMP firmware. */ - FLOW_CTLR_HALT_COP_EVENTS_0 = 0; -} - -static void configure_flow_regs_for_sleep(void) { - unsigned int current_core = get_core_id(); - flow_set_cc4_ctrl(current_core, 0); - flow_set_halt_events(current_core, false); - FLOW_CTLR_L2FLUSH_CONTROL_0 = 0; - flow_set_csr(current_core, 2); -} - -static void save_tzram_state(void) { - /* TODO: Remove set suspend call once exo warmboots fully */ - set_suspend_for_debug(); - uint32_t tzram_cmac[0x4] = {0}; - - uint8_t *tzram_encryption_dst = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM)); - uint8_t *tzram_encryption_src = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM)); - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - tzram_encryption_src += 0x2000ull; - } - uint8_t *tzram_store_address = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_TZRAM)); - clear_priv_smc_in_progress(); - - /* Flush cache. */ - flush_dcache_all(); - - /* Encrypt and save TZRAM into DRAM using a random aes-256 key. */ - se_generate_random_key(KEYSLOT_SWITCH_LP0TZRAMKEY, KEYSLOT_SWITCH_RNGKEY); - - flush_dcache_range(tzram_encryption_dst, tzram_encryption_dst + LP0_TZRAM_SAVE_SIZE); - flush_dcache_range(tzram_encryption_src, tzram_encryption_src + LP0_TZRAM_SAVE_SIZE); - - /* Use the all-zero cmac buffer as an IV. */ - se_aes_256_cbc_encrypt(KEYSLOT_SWITCH_LP0TZRAMKEY, tzram_encryption_dst, LP0_TZRAM_SAVE_SIZE, tzram_encryption_src, LP0_TZRAM_SAVE_SIZE, tzram_cmac); - flush_dcache_range(tzram_encryption_dst, tzram_encryption_dst + LP0_TZRAM_SAVE_SIZE); - - /* Copy encrypted TZRAM from IRAM to DRAM. */ - for (unsigned int i = 0; i < LP0_TZRAM_SAVE_SIZE; i += 4) { - write32le(tzram_store_address, i, read32le(tzram_encryption_dst, i)); - } - - flush_dcache_range(tzram_store_address, tzram_store_address + LP0_TZRAM_SAVE_SIZE); - - /* Compute CMAC. */ - se_compute_aes_256_cmac(KEYSLOT_SWITCH_LP0TZRAMKEY, tzram_cmac, sizeof(tzram_cmac), tzram_encryption_src, LP0_TZRAM_SAVE_SIZE); - - /* Write CMAC, lock registers. */ - APBDEV_PMC_SECURE_SCRATCH112_0 = tzram_cmac[0]; - APBDEV_PMC_SECURE_SCRATCH113_0 = tzram_cmac[1]; - APBDEV_PMC_SECURE_SCRATCH114_0 = tzram_cmac[2]; - APBDEV_PMC_SECURE_SCRATCH115_0 = tzram_cmac[3]; - APBDEV_PMC_SEC_DISABLE8_0 = 0x550000; - - /* Perform pre-2.0.0 PMC writes. */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - /* TODO: Give these writes appropriate defines in pmc.h */ - - /* Save Encrypted context location + lock scratch register. */ - MAKE_REG32(PMC_BASE + 0x360) = WARMBOOT_GET_RAM_SEGMENT_PA(WARMBOOT_RAM_SEGMENT_ID_TZRAM); - MAKE_REG32(PMC_BASE + 0x2D8) = 0x10000; - - /* Save Encryption parameters (where to copy TZRAM to, source, destination, size) */ - MAKE_REG32(PMC_BASE + 0x340) = LP0_ENTRY_GET_RAM_SEGMENT_PA(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM); - MAKE_REG32(PMC_BASE + 0x344) = 0; - MAKE_REG32(PMC_BASE + 0x348) = LP0_ENTRY_GET_RAM_SEGMENT_PA(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM); - MAKE_REG32(PMC_BASE + 0x34C) = 0; - MAKE_REG32(PMC_BASE + 0x350) = LP0_ENTRY_GET_RAM_SEGMENT_PA(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM); - MAKE_REG32(PMC_BASE + 0x354) = LP0_TZRAM_SAVE_SIZE; - - /* Lock scratch registers. */ - MAKE_REG32(PMC_BASE + 0x2D8) = 0x555; - } -} - -static void save_se_state(void) { - /* Save security engine state. */ - uint8_t *se_state_dst = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_SE_STATE)); - se_check_error_status_reg(); - se_set_in_context_save_mode(true); - se_save_context(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY, se_state_dst); - flush_dcache_range(se_state_dst, se_state_dst + 0x840); - APBDEV_PMC_SCRATCH43_0 = (uint32_t)(WARMBOOT_GET_RAM_SEGMENT_PA(WARMBOOT_RAM_SEGMENT_ID_SE_STATE)); - se_set_in_context_save_mode(false); - se_check_error_status_reg(); -} - -/* Save security engine, and go to sleep. */ -void save_se_and_power_down_cpu(void) { - /* Save context for warmboot to restore. */ - save_tzram_state(); - save_se_state(); - - /* Patch the bootrom to disable warmboot signature checks. */ - MAKE_REG32(PMC_BASE + 0x118) = 0x2202E012; - MAKE_REG32(PMC_BASE + 0x11C) = 0x6001DC28; - - if (!configitem_is_retail()) { - uart_send(UART_A, "OYASUMI", 8); - } - - finalize_powerdown(); -} - -uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argument) { - /* TODO: 6.0.0 introduces heavy deja vu mitigations. */ - /* Exosphere may want to implement these. */ - - /* Ensure SMC call is to enter deep sleep. */ - if ((power_state & 0x17FFF) != 0x1001B) { - return 0xFFFFFFFD; - } - - /* Perform I2C comms with TI charger if required. */ - configure_battery_hiz_mode(); - - /* Enable LP0 Wake Event Detection. */ - enable_lp0_wake_events(); - - /* Alert the PMC of an iminent shutdown. */ - notify_pmic_shutdown(); - - /* Validate that the shutdown has correct context. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - mitigate_jamais_vu(); - } - - /* Signal to bootrom the next reset should be a warmboot. */ - configure_pmc_for_deep_powerdown(); - - /* Ensure that BPMP SC7 firmware is active. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - setup_bpmp_sc7_firmware(); - } - - /* Prepare the current core for sleep. */ - configure_flow_regs_for_sleep(); - - /* Save core context. */ - set_core_entrypoint_and_argument(get_core_id(), entrypoint, argument); - save_current_core_context(); - set_current_core_inactive(); - - /* Ensure that other cores are already asleep. */ - if (!(APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00)) { - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - call_with_stack_pointer(get_smc_core012_stack_address(), save_se_and_power_down_cpu); - } else { - save_se_and_power_down_cpu(); - } - } - - generic_panic(); -} diff --git a/exosphere/src/sc7.h b/exosphere/src/sc7.h deleted file mode 100644 index 055a4ac1b..000000000 --- a/exosphere/src/sc7.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SC7_H -#define EXOSPHERE_SC7_H - -#include - -/* Exosphere Deep Sleep Entry implementation. */ - -#define LP0_TZRAM_SAVE_SIZE 0xE000 - -uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argument); - -#endif \ No newline at end of file diff --git a/exosphere/src/se.c b/exosphere/src/se.c deleted file mode 100644 index dcc52f4ea..000000000 --- a/exosphere/src/se.c +++ /dev/null @@ -1,912 +0,0 @@ -/* - * 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 "utils.h" -#include "synchronization.h" -#include "interrupt.h" -#include "se.h" -#include "memory_map.h" -#include "arm.h" -#include "se.h" - -void trigger_se_rsa_op(void *buf, size_t size); -void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size); - -/* Globals for driver. */ -static unsigned int (*g_se_callback)(void); - -static unsigned int g_se_modulus_sizes[KEYSLOT_RSA_MAX]; -static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX]; - -static bool g_se_generated_vector = false; -static uint8_t g_se_stored_test_vector[0x10]; - -/* Initialize a SE linked list. */ -void ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { - ll->num_entries = 0; /* 1 Entry. */ - - if (buffer != NULL) { - ll->addr_info.address = (uint32_t) get_physical_address(buffer); - ll->addr_info.size = (uint32_t) size; - } else { - ll->addr_info.address = 0; - ll->addr_info.size = 0; - } - - flush_dcache_range((uint8_t *)ll, (uint8_t *)ll + sizeof(*ll)); -} - -void set_security_engine_callback(unsigned int (*callback)(void)) { - /* Set the callback. */ - g_se_callback = callback; - - /* Enable SE Interrupt firing for async op. */ - se_get_regs()->SE_INT_ENABLE = 0x10; -} - -/* Fires on Security Engine operation completion. */ -void se_operation_completed(void) { - se_get_regs()->SE_INT_ENABLE = 0; - unsigned int (*callback)(void) = g_se_callback; - if (callback != NULL) { - g_se_callback = NULL; - callback(); - } -} - -void se_check_error_status_reg(void) { - if (se_get_regs()->SE_ERR_STATUS) { - generic_panic(); - } -} - -void se_check_for_error(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) { - generic_panic(); - } -} - -void se_trigger_interrupt(void) { - intr_set_pending(INTERRUPT_ID_USER_SECURITY_ENGINE); -} - -void se_verify_flags_cleared(void) { - if (se_get_regs()->SE_STATUS & 3) { - generic_panic(); - } -} - -void se_generate_test_vector(void *vector) { - /* TODO: Implement real test vector generation. */ - memset(vector, 0, 0x10); -} - -void se_validate_stored_vector(void) { - if (!g_se_generated_vector) { - generic_panic(); - } - - uint8_t calc_vector[0x10]; - se_generate_test_vector(calc_vector); - - /* Ensure nobody's messed with the security engine while we slept. */ - if (memcmp(calc_vector, g_se_stored_test_vector, 0x10) != 0) { - generic_panic(); - } -} - -void se_generate_stored_vector(void) { - if (g_se_generated_vector) { - generic_panic(); - } - - se_generate_test_vector(g_se_stored_test_vector); - g_se_generated_vector = true; -} - -/* Set the flags for an AES keyslot. */ -void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - /* Misc flags. */ - if (flags & ~0x80) { - se->SE_CRYPTO_KEYTABLE_ACCESS[keyslot] = ~flags; - } - - /* Disable keyslot reads. */ - if (flags & 0x80) { - se->SE_CRYPTO_SECURITY_PERKEY &= ~(1 << keyslot); - } -} - -/* Set the flags for an RSA keyslot. */ -void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_RSA_MAX) { - generic_panic(); - } - - /* Misc flags. */ - if (flags & ~0x80) { - /* TODO: Why are flags assigned this way? */ - se->SE_RSA_KEYTABLE_ACCESS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; - } - - /* Disable keyslot reads. */ - if (flags & 0x80) { - se->SE_RSA_SECURITY_PERKEY &= ~(1 << keyslot); - } -} - -void clear_aes_keyslot(unsigned int keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - /* Zero out the whole keyslot and IV. */ - for (unsigned int i = 0; i < 0x10; i++) { - se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i; - se->SE_CRYPTO_KEYTABLE_DATA = 0; - } -} - -void clear_rsa_keyslot(unsigned int keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_RSA_MAX) { - generic_panic(); - } - - /* Zero out the whole keyslot. */ - for (unsigned int i = 0; i < 0x40; i++) { - /* Select Keyslot Modulus[i] */ - se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; - se->SE_RSA_KEYTABLE_DATA = 0; - } - for (unsigned int i = 0; i < 0x40; i++) { - /* Select Keyslot Expontent[i] */ - se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - se->SE_RSA_KEYTABLE_DATA = 0; - } -} - -void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { - generic_panic(); - } - - for (size_t i = 0; i < (key_size >> 2); i++) { - se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i; - se->SE_CRYPTO_KEYTABLE_DATA = read32le(key, 4 * i); - } -} - -void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { - generic_panic(); - } - - for (size_t i = 0; i < (modulus_size >> 2); i++) { - se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; - se->SE_RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); - } - - for (size_t i = 0; i < (exp_size >> 2); i++) { - se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - se->SE_RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); - } - - g_se_modulus_sizes[keyslot] = modulus_size; - g_se_exp_sizes[keyslot] = exp_size; -} - -void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { - generic_panic(); - } - - for (size_t i = 0; i < (iv_size >> 2); i++) { - se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - se->SE_CRYPTO_KEYTABLE_DATA = read32le(iv, 4 * i); - } -} - -void clear_aes_keyslot_iv(unsigned int keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - for (size_t i = 0; i < (0x10 >> 2); i++) { - se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - se->SE_CRYPTO_KEYTABLE_DATA = 0; - } -} - -void set_se_ctr(const void *ctr) { - for (unsigned int i = 0; i < 4; i++) { - se_get_regs()->SE_CRYPTO_LINEAR_CTR[i] = read32le(ctr, i * 4); - } -} - -void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSIZE_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { - generic_panic(); - } - - se->SE_CONFIG = (ALG_AES_DEC | DST_KEYTAB); - se->SE_CRYPTO_CONFIG = keyslot_src << 24; - se->SE_CRYPTO_LAST_BLOCK = 0; - se->SE_CRYPTO_KEYTABLE_DST = keyslot_dst << 8; - - flush_dcache_range(wrapped_key, (const uint8_t *)wrapped_key + wrapped_key_size); - trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); -} - -void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, bool encrypt, unsigned int (*callback)(void)) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - if (size == 0) { - return; - } - - /* Setup Config register. */ - if (encrypt) { - se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY); - } else { - se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY); - } - - /* Setup Crypto register. */ - se->SE_CRYPTO_CONFIG = crypt_config | (keyslot << 24) | (encrypt << 8); - - /* Mark this encryption as insecure -- this makes the SE not a secure busmaster. */ - se->SE_CRYPTO_CONFIG |= 0x80000000; - - /* Appropriate number of blocks. */ - se->SE_CRYPTO_LAST_BLOCK = (size >> 4) - 1; - - /* Set the callback, for after the async operation. */ - set_security_engine_callback(callback); - - /* Setup Input/Output lists */ - se->SE_IN_LL_ADDR = in_ll_paddr; - se->SE_OUT_LL_ADDR = out_ll_paddr; - - /* Set registers for operation. */ - se->SE_ERR_STATUS = se->SE_ERR_STATUS; - se->SE_INT_STATUS = se->SE_INT_STATUS; - se->SE_OPERATION = 1; - (void)(se->SE_OPERATION); - - /* Ensure writes go through. */ - __dsb_ish(); -} - -void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *ctr, unsigned int (*callback)(void)) { - /* Unknown what this write does, but official code writes it for CTR mode. */ - se_get_regs()->SE_SPARE = 1; - set_se_ctr(ctr); - se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x81E, true, callback); -} - -void se_aes_cbc_encrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) { - set_aes_keyslot_iv(keyslot, iv, 0x10); - se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x44, true, callback); -} - -void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) { - set_aes_keyslot_iv(keyslot, iv, 0x10); - se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, false, callback); -} - -void se_exp_mod(unsigned int keyslot, const void *buf, size_t size, unsigned int (*callback)(void)) { - volatile tegra_se_t *se = se_get_regs(); - uint8_t stack_buf[KEYSIZE_RSA_MAX]; - - if (keyslot >= KEYSLOT_RSA_MAX || size > KEYSIZE_RSA_MAX) { - generic_panic(); - } - - /* Endian swap the input. */ - for (size_t i = 0; i < size; i++) { - stack_buf[i] = *((const uint8_t *)buf + size - i - 1); - } - - se->SE_CONFIG = (ALG_RSA | DST_RSAREG); - se->SE_RSA_CONFIG = keyslot << 24; - se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1; - se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2; - - set_security_engine_callback(callback); - - flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX); - trigger_se_rsa_op(stack_buf, size); - - while (!(se->SE_INT_STATUS & 2)) { /* Wait a while */ } -} - -void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); - uint8_t stack_buf[KEYSIZE_RSA_MAX]; - - if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) { - generic_panic(); - } - - /* Endian swap the input. */ - for (size_t i = 0; i < src_size; i++) { - stack_buf[i] = *((uint8_t *)src + src_size - i - 1); - } - - se->SE_CONFIG = (ALG_RSA | DST_RSAREG); - se->SE_RSA_CONFIG = keyslot << 24; - se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1; - se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2; - - flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX); - trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size); - se_get_exp_mod_output(dst, dst_size); -} - -void se_get_exp_mod_output(void *buf, size_t size) { - size_t num_dwords = (size >> 2); - if (num_dwords < 1) { - return; - } - - uint32_t *p_out = ((uint32_t *)buf) + num_dwords - 1; - uint32_t offset = 0; - - /* Copy endian swapped output. */ - while (num_dwords) { - *p_out = read32be(se_get_regs()->SE_RSA_OUTPUT, offset); - offset += 4; - p_out--; - num_dwords--; - } -} - -bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) { - uint8_t message[RSA_2048_BYTES]; - uint8_t h_buf[0x24]; - - /* Hardcode RSA with keyslot 0. */ - const uint8_t public_exponent[4] = {0x00, 0x01, 0x00, 0x01}; - set_rsa_keyslot(0, modulus, modulus_size, public_exponent, sizeof(public_exponent)); - se_synchronous_exp_mod(0, message, sizeof(message), signature, signature_size); - - /* Validate sanity byte. */ - if (message[RSA_2048_BYTES - 1] != 0xBC) { - return false; - } - - /* Copy Salt into MGF1 Hash Buffer. */ - memset(h_buf, 0, sizeof(h_buf)); - memcpy(h_buf, message + RSA_2048_BYTES - 0x20 - 0x1, 0x20); - - /* Decrypt maskedDB (via inline MGF1). */ - uint8_t seed = 0; - uint8_t mgf1_buf[0x20]; - for (unsigned int ofs = 0; ofs < RSA_2048_BYTES - 0x20 - 1; ofs += 0x20) { - h_buf[sizeof(h_buf) - 1] = seed++; - flush_dcache_range(h_buf, h_buf + sizeof(h_buf)); - se_calculate_sha256(mgf1_buf, h_buf, sizeof(h_buf)); - for (unsigned int i = ofs; i < ofs + 0x20 && i < RSA_2048_BYTES - 0x20 - 1; i++) { - message[i] ^= mgf1_buf[i - ofs]; - } - } - - /* Constant lmask for rsa-2048-pss. */ - message[0] &= 0x7F; - - /* Validate DB is of the form 0000...0001. */ - for (unsigned int i = 0; i < RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1; i++) { - if (message[i] != 0) { - return false; - } - } - if (message[RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1] != 1) { - return false; - } - - /* Check hash correctness. */ - uint8_t validate_buf[8 + 0x20 + 0x20]; - uint8_t validate_hash[0x20]; - - memset(validate_buf, 0, sizeof(validate_buf)); - flush_dcache_range((uint8_t *)data, (uint8_t *)data + data_size); - se_calculate_sha256(&validate_buf[8], data, data_size); - memcpy(&validate_buf[0x28], &message[RSA_2048_BYTES - 0x20 - 0x20 - 1], 0x20); - flush_dcache_range(validate_buf, validate_buf + sizeof(validate_buf)); - se_calculate_sha256(validate_hash, validate_buf, sizeof(validate_buf)); - return memcmp(h_buf, validate_hash, 0x20) == 0; -} - - -void trigger_se_rsa_op(void *buf, size_t size) { - volatile tegra_se_t *se = se_get_regs(); - se_ll_t in_ll; - - ll_init(&in_ll, (void *)buf, size); - - /* Set the input LL. */ - se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll); - - /* Set registers for operation. */ - se->SE_ERR_STATUS = se->SE_ERR_STATUS; - se->SE_INT_STATUS = se->SE_INT_STATUS; - se->SE_OPERATION = 1; - (void)(se->SE_OPERATION); - - /* Ensure writes go through. */ - __dsb_ish(); -} - -void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); - se_ll_t in_ll; - se_ll_t out_ll; - - ll_init(&in_ll, (void *)src, src_size); - ll_init(&out_ll, dst, dst_size); - - __dsb_sy(); - - /* Set the LLs. */ - se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll); - se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll); - - /* Set registers for operation. */ - se->SE_ERR_STATUS = se->SE_ERR_STATUS; - se->SE_INT_STATUS = se->SE_INT_STATUS; - se->SE_OPERATION = op; - (void)(se->SE_OPERATION); - - __dsb_ish(); - - while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ } - - se_check_for_error(); -} - -/* Secure AES Functionality. */ -void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { - uint8_t block[0x10] = {0}; - - if (src_size > sizeof(block) || dst_size > sizeof(block)) { - generic_panic(); - } - - /* Load src data into block. */ - if (src_size != 0) { - memcpy(block, src, src_size); - } - flush_dcache_range(block, block + sizeof(block)); - - /* Trigger AES operation. */ - se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0; - trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); - - /* Copy output data into dst. */ - flush_dcache_range(block, block + sizeof(block)); - if (dst_size != 0) { - memcpy(dst, block, dst_size); - } -} - -void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { - generic_panic(); - } - - if (src_size) { - flush_dcache_range((uint8_t *)src, (uint8_t *)src + src_size); - } - if (dst_size) { - flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size); - } - - unsigned int num_blocks = src_size >> 4; - - /* Unknown what this write does, but official code writes it for CTR mode. */ - se->SE_SPARE = 1; - se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY); - se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x91E; - set_se_ctr(ctr); - - /* Handle any aligned blocks. */ - size_t aligned_size = (size_t)num_blocks << 4; - if (aligned_size) { - se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1; - trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size); - } - - /* Handle final, unaligned block. */ - if (aligned_size < dst_size && aligned_size < src_size) { - size_t last_block_size = dst_size - aligned_size; - if (src_size < dst_size) { - last_block_size = src_size - aligned_size; - } - se_perform_aes_block_operation(dst + aligned_size, last_block_size, (uint8_t *)src + aligned_size, src_size - aligned_size); - } - - if (dst_size) { - flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size); - } -} - -void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { - generic_panic(); - } - - /* Set configuration high (256-bit vs 128-bit) based on parameter. */ - se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); - se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100; - flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10); - se_perform_aes_block_operation(dst, 0x10, src, 0x10); - flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10); - -} - -void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { - se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0); -} - -void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { - se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202); -} - - -void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { - generic_panic(); - } - - se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY); - se->SE_CRYPTO_CONFIG = keyslot << 24; - flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10); - se_perform_aes_block_operation(dst, 0x10, src, 0x10); - flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10); -} - -void shift_left_xor_rb(uint8_t *key) { - uint8_t prev_high_bit = 0; - for (unsigned int i = 0; i < 0x10; i++) { - uint8_t cur_byte = key[0xF - i]; - key[0xF - i] = (cur_byte << 1) | (prev_high_bit); - prev_high_bit = cur_byte >> 7; - } - if (prev_high_bit) { - key[0xF] ^= 0x87; - } -} - -void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - if (data_size) { - flush_dcache_range((uint8_t *)data, (uint8_t *)data + data_size); - } - - /* Generate the derived key, to be XOR'd with final output block. */ - uint8_t derived_key[0x10] = {0}; - se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high); - shift_left_xor_rb(derived_key); - if (data_size & 0xF) { - shift_left_xor_rb(derived_key); - } - - se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); - se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145); - clear_aes_keyslot_iv(keyslot); - - unsigned int num_blocks = (data_size + 0xF) >> 4; - /* Handle aligned blocks. */ - if (num_blocks > 1) { - se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2; - trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); - se->SE_CRYPTO_CONFIG |= 0x80; - } - - /* Create final block. */ - uint8_t last_block[0x10] = {0}; - if (data_size & 0xF) { - memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF); - last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */ - } else if (data_size >= 0x10) { - memcpy(last_block, data + data_size - 0x10, 0x10); - } - - for (unsigned int i = 0; i < 0x10; i++) { - last_block[i] ^= derived_key[i]; - } - - /* Perform last operation. */ - se->SE_CRYPTO_LAST_BLOCK = 0; - flush_dcache_range(last_block, last_block + sizeof(last_block)); - trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); - - /* Copy output CMAC. */ - for (unsigned int i = 0; i < (cmac_size >> 2); i++) { - ((uint32_t *)cmac)[i] = read32le(se->SE_HASH_RESULT, i << 2); - } -} - -void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { - se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0); -} -void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { - se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202); -} - -void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { - generic_panic(); - } - - se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); - se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144; - set_aes_keyslot_iv(keyslot, iv, 0x10); - se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1; - trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); -} - -/* SHA256 Implementation. */ -void se_calculate_sha256(void *dst, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); - - /* Setup config for SHA256, size = BITS(src_size) */ - se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); - se->SE_SHA_CONFIG = 1; - se->SE_SHA_MSG_LENGTH[0] = (uint32_t)(src_size << 3); - se->SE_SHA_MSG_LENGTH[1] = 0; - se->SE_SHA_MSG_LENGTH[2] = 0; - se->SE_SHA_MSG_LENGTH[3] = 0; - se->SE_SHA_MSG_LEFT[0] = (uint32_t)(src_size << 3); - se->SE_SHA_MSG_LEFT[1] = 0; - se->SE_SHA_MSG_LEFT[2] = 0; - se->SE_SHA_MSG_LEFT[3] = 0; - - /* Trigger the operation. */ - trigger_se_blocking_op(OP_START, NULL, 0, src, src_size); - - /* Copy output hash. */ - for (unsigned int i = 0; i < (0x20 >> 2); i++) { - ((uint32_t *)dst)[i] = read32be(se->SE_HASH_RESULT, i << 2); - } -} - -/* RNG API */ -void se_initialize_rng(unsigned int keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - /* To initialize the RNG, we'll perform an RNG operation into an output buffer. */ - /* This will be discarded, when done. */ - uint8_t output_buf[0x10]; - - se->SE_RNG_SRC_CONFIG = 3; /* Entropy enable + Entropy lock enable */ - se->SE_RNG_RESEED_INTERVAL = 70001; - se->SE_CONFIG = (ALG_RNG | DST_MEMORY); - se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108; - se->SE_RNG_CONFIG = 5; - se->SE_CRYPTO_LAST_BLOCK = 0; - trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0); -} - -void se_generate_random(unsigned int keyslot, void *dst, size_t size) { - volatile tegra_se_t *se = se_get_regs(); - - if (keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - uint32_t num_blocks = size >> 4; - size_t aligned_size = num_blocks << 4; - se->SE_CONFIG = (ALG_RNG | DST_MEMORY); - se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108; - se->SE_RNG_CONFIG = 4; - - if (num_blocks >= 1) { - se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1; - trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0); - } - if (size > aligned_size) { - se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); - } -} - -/* SE context save API. */ -void se_set_in_context_save_mode(bool is_context_save_mode) { - volatile tegra_se_t *se = se_get_regs(); - - uint32_t val = se->SE_SE_SECURITY; - if (is_context_save_mode) { - val |= 0x10000; - } else { - val &= 0xFFFEFFFF; - } - se->SE_SE_SECURITY = val; - /* Perform a useless read from flags reg. */ - (void)(se->SE_STATUS); -} - -void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - if (dst_keyslot >= KEYSLOT_AES_MAX || rng_keyslot >= KEYSLOT_AES_MAX) { - generic_panic(); - } - - /* Setup Config. */ - se->SE_CONFIG = (ALG_RNG | DST_KEYTAB); - se->SE_CRYPTO_CONFIG = (rng_keyslot << 24) | 0x108; - se->SE_RNG_CONFIG = 4; - se->SE_CRYPTO_LAST_BLOCK = 0; - - /* Generate low part of key. */ - se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8); - trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); - /* Generate high part of key. */ - se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8) | 1; - trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); -} - -void se_generate_srk(unsigned int srkgen_keyslot) { - volatile tegra_se_t *se = se_get_regs(); - - se->SE_CONFIG = (ALG_RNG | DST_SRK); - se->SE_CRYPTO_CONFIG = (srkgen_keyslot << 24) | 0x108; - se->SE_RNG_CONFIG = 6; - se->SE_CRYPTO_LAST_BLOCK = 0; - trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); -} - -void se_encrypt_with_srk(void *dst, size_t dst_size, const void *src, size_t src_size) { - uint8_t output[0x80]; - uint8_t *aligned_out = (uint8_t *)(((uintptr_t)output + 0x7F) & ~0x3F); - if (dst_size > 0x10) { - generic_panic(); - } - if (src_size) { - flush_dcache_range((uint8_t *)src, (uint8_t *)src + src_size); - } - if (dst_size) { - flush_dcache_range(aligned_out, aligned_out + 0x10); - trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, dst_size, src, src_size); - flush_dcache_range(aligned_out, aligned_out + 0x10); - memcpy(dst, aligned_out, dst_size); - } else { - trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, 0, src, src_size); - } -} - -void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void *dst) { - volatile tegra_se_t *se = se_get_regs(); - uint8_t _work_buf[0x80]; - uint8_t *work_buf = (uint8_t *)(((uintptr_t)_work_buf + 0x7F) & ~0x3F); - - /* Generate the SRK (context save encryption key). */ - se_generate_random_key(srkgen_keyslot, rng_keyslot); - se_generate_srk(srkgen_keyslot); - - flush_dcache_range(work_buf, work_buf + 0x10); - se_generate_random(rng_keyslot, work_buf, 0x10); - flush_dcache_range(work_buf, work_buf + 0x10); - - /* Save random initial block. */ - se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY); - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(dst, 0x10, work_buf, 0x10); - - /* Save Sticky Bits. */ - for (unsigned int i = 0; i < 0x2; i++) { - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0); - } - - /* Save AES Key Table. */ - for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(dst + 0x30 + (i * 0x20), 0x10, NULL, 0); - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0); - } - - /* Save AES Original IVs. */ - for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0); - } - - /* Save AES Updated IVs */ - for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0); - } - - /* Save RSA Keytable. */ - uint8_t *rsa_ctx_out = (uint8_t *)dst + 0x430; - for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) { - for (unsigned int mod_exp = 0; mod_exp < 2; mod_exp++) { - for (unsigned int sub_block = 0; sub_block < 0x10; sub_block++) { - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(rsa_ctx_out, 0x10, NULL, 0); - rsa_ctx_out += 0x10; - } - } - } - - /* Save "Known Pattern. " */ - static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10); - - /* Save SRK into PMC registers. */ - se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_SRK); - se->SE_CRYPTO_LAST_BLOCK = 0; - se_encrypt_with_srk(work_buf, 0, NULL, 0); - se->SE_CONFIG = 0; - se_encrypt_with_srk(work_buf, 0, NULL, 0); -} diff --git a/exosphere/src/se.h b/exosphere/src/se.h deleted file mode 100644 index a429caef7..000000000 --- a/exosphere/src/se.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SE_H -#define EXOSPHERE_SE_H - -#include -#include -#include -#include - -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 security engine. */ - -#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2 -#define KEYSLOT_SWITCH_SRKGENKEY 0x8 -#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8 -#define KEYSLOT_SWITCH_TEMPKEY 0x9 -#define KEYSLOT_SWITCH_SESSIONKEY 0xA -#define KEYSLOT_SWITCH_RNGKEY 0xB -#define KEYSLOT_SWITCH_MASTERKEY 0xC -#define KEYSLOT_SWITCH_DEVICEKEY 0xD - -/* This keyslot was added in 4.0.0. */ -#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD -#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE -#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF - -/* This keyslot was added in 5.0.0. */ -#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA - -/* This keyslot was added in 6.00. */ -#define KEYSLOT_SWITCH_6XTSECKEY 0xC -#define KEYSLOT_SWITCH_6XTSECROOTKEY 0xD -#define KEYSLOT_SWITCH_6XSBK 0xE - -#define KEYSLOT_AES_MAX 0x10 -#define KEYSLOT_RSA_MAX 0x2 - -#define KEYSIZE_AES_MAX 0x20 -#define KEYSIZE_RSA_MAX 0x100 - -#define ALG_SHIFT (12) -#define ALG_DEC_SHIFT (8) -#define ALG_NOP (0 << ALG_SHIFT) -#define ALG_AES_ENC (1 << ALG_SHIFT) -#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP) -#define ALG_RNG (2 << ALG_SHIFT) -#define ALG_SHA (3 << ALG_SHIFT) -#define ALG_RSA (4 << ALG_SHIFT) - -#define DST_SHIFT (2) -#define DST_MEMORY (0 << DST_SHIFT) -#define DST_HASHREG (1 << DST_SHIFT) -#define DST_KEYTAB (2 << DST_SHIFT) -#define DST_SRK (3 << DST_SHIFT) -#define DST_RSAREG (4 << DST_SHIFT) - -#define ENCMODE_SHIFT (24) -#define DECMODE_SHIFT (16) -#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT) - -#define HASH_DISABLE (0x0) -#define HASH_ENABLE (0x1) - -#define OP_ABORT 0 -#define OP_START 1 -#define OP_RESTART 2 -#define OP_CTX_SAVE 3 -#define OP_RESTART_IN 4 - -#define CTX_SAVE_SRC_SHIFT 29 -#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT) -#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT) - -#define CTX_SAVE_KEY_LOW_BITS 0 -#define CTX_SAVE_KEY_HIGH_BITS 1 -#define CTX_SAVE_KEY_ORIGINAL_IV 2 -#define CTX_SAVE_KEY_UPDATED_IV 3 - -#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24 -#define CTX_SAVE_KEY_INDEX_SHIFT 8 -#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16 -#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12 - -#define RSA_2048_BYTES 0x100 - -typedef struct { - uint32_t SE_SE_SECURITY; - uint32_t SE_TZRAM_SECURITY; - uint32_t SE_OPERATION; - uint32_t SE_INT_ENABLE; - uint32_t SE_INT_STATUS; - uint32_t SE_CONFIG; - uint32_t SE_IN_LL_ADDR; - uint32_t SE_IN_CUR_BYTE_ADDR; - uint32_t SE_IN_CUR_LL_ID; - uint32_t SE_OUT_LL_ADDR; - uint32_t SE_OUT_CUR_BYTE_ADDR; - uint32_t SE_OUT_CUR_LL_ID; - uint32_t SE_HASH_RESULT[0x10]; - uint32_t SE_CTX_SAVE_CONFIG; - uint32_t _0x74[0x63]; - uint32_t SE_SHA_CONFIG; - uint32_t SE_SHA_MSG_LENGTH[0x4]; - uint32_t SE_SHA_MSG_LEFT[0x4]; - uint32_t _0x224[0x17]; - uint32_t SE_CRYPTO_SECURITY_PERKEY; - uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10]; - uint32_t _0x2C4[0x10]; - uint32_t SE_CRYPTO_CONFIG; - uint32_t SE_CRYPTO_LINEAR_CTR[0x4]; - uint32_t SE_CRYPTO_LAST_BLOCK; - uint32_t SE_CRYPTO_KEYTABLE_ADDR; - uint32_t SE_CRYPTO_KEYTABLE_DATA; - uint32_t _0x324[0x3]; - uint32_t SE_CRYPTO_KEYTABLE_DST; - uint32_t _0x334[0x3]; - uint32_t SE_RNG_CONFIG; - uint32_t SE_RNG_SRC_CONFIG; - uint32_t SE_RNG_RESEED_INTERVAL; - uint32_t _0x34C[0x2D]; - uint32_t SE_RSA_CONFIG; - uint32_t SE_RSA_KEY_SIZE; - uint32_t SE_RSA_EXP_SIZE; - uint32_t SE_RSA_SECURITY_PERKEY; - uint32_t SE_RSA_KEYTABLE_ACCESS[0x2]; - uint32_t _0x418[0x2]; - uint32_t SE_RSA_KEYTABLE_ADDR; - uint32_t SE_RSA_KEYTABLE_DATA; - uint32_t SE_RSA_OUTPUT[0x40]; - uint32_t _0x528[0xB6]; - uint32_t SE_STATUS; - uint32_t SE_ERR_STATUS; - uint32_t SE_MISC; - uint32_t SE_SPARE; - uint32_t SE_ENTROPY_DEBUG_COUNTER; - uint32_t _0x814; - uint32_t _0x818; - uint32_t _0x81C; - uint32_t _0x820[0x5F8]; -} tegra_se_t; - -typedef struct { - uint32_t address; - uint32_t size; -} se_addr_info_t; - -typedef struct { - uint32_t num_entries; /* Set to total entries - 1 */ - se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ -} se_ll_t; - -static inline volatile tegra_se_t *se_get_regs(void) { - return (volatile tegra_se_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SE)); -} - -/* This function MUST be registered to fire on the appropriate interrupt. */ -void se_operation_completed(void); - -void se_check_error_status_reg(void); -void se_check_for_error(void); -void se_trigger_interrupt(void); - -void se_validate_stored_vector(void); -void se_generate_stored_vector(void); - -void se_verify_flags_cleared(void); - -void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags); -void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags); -void clear_aes_keyslot(unsigned int keyslot); -void clear_rsa_keyslot(unsigned int keyslot); - -void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size); -void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size); -void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size); -void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size); -void set_se_ctr(const void *ctr); - -/* Insecure AES API */ -void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *ctr, unsigned int (*callback)(void)); -void se_aes_cbc_encrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)); -void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)); - -/* Secure AES API */ -void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); -void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); -void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); -void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); -void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size); -void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); -void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv); - -/* Hash API */ -void se_calculate_sha256(void *dst, const void *src, size_t src_size); - -/* RSA API */ -void se_exp_mod(unsigned int keyslot, const void *buf, size_t size, unsigned int (*callback)(void)); -void se_get_exp_mod_output(void *buf, size_t size); -void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); -bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size); - -/* RNG API */ -void se_initialize_rng(unsigned int keyslot); -void se_generate_random(unsigned int keyslot, void *dst, size_t size); - -/* SE context save API. */ -void se_generate_srk(unsigned int srkgen_keyslot); -void se_set_in_context_save_mode(bool is_context_save_mode); -void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot); -void se_save_context(unsigned int srk_keyslot, unsigned int rng_keyslot, void *dst); - -#endif /* EXOSPHERE_SE_H */ diff --git a/exosphere/src/sealedkeys.c b/exosphere/src/sealedkeys.c deleted file mode 100644 index dd4e7f835..000000000 --- a/exosphere/src/sealedkeys.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "exocfg.h" -#include "sealedkeys.h" -#include "se.h" - -static const uint8_t g_titlekey_seal_key_source[0x10] = { - 0xCB, 0xB7, 0x6E, 0x38, 0xA1, 0xCB, 0x77, 0x0F, 0xB2, 0xA5, 0xB2, 0x9D, 0xD8, 0x56, 0x9F, 0x76 -}; - -static const uint8_t g_seal_key_sources[CRYPTOUSECASE_MAX_5X][0x10] = { - {0xF4, 0x0C, 0x16, 0x26, 0x0D, 0x46, 0x3B, 0xE0, 0x8C, 0x6A, 0x56, 0xE5, 0x82, 0xD4, 0x1B, 0xF6}, - {0x7F, 0x54, 0x2C, 0x98, 0x1E, 0x54, 0x18, 0x3B, 0xBA, 0x63, 0xBD, 0x4C, 0x13, 0x5B, 0xF1, 0x06}, - {0xC7, 0x3F, 0x73, 0x60, 0xB7, 0xB9, 0x9D, 0x74, 0x0A, 0xF8, 0x35, 0x60, 0x1A, 0x18, 0x74, 0x63}, - {0x0E, 0xE0, 0xC4, 0x33, 0x82, 0x66, 0xE8, 0x08, 0x39, 0x13, 0x41, 0x7D, 0x04, 0x64, 0x2B, 0x6D}, - {0xE1, 0xA8, 0xAA, 0x6A, 0x2D, 0x9C, 0xDE, 0x43, 0x0C, 0xDE, 0xC6, 0x17, 0xF6, 0xC7, 0xF1, 0xDE}, - {0x74, 0x20, 0xF6, 0x46, 0x77, 0xB0, 0x59, 0x2C, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9}, - {0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE6, 0xD8, 0x9A, 0xCF, 0xE5, 0x3F, 0xB3, 0x4B} -}; - -bool usecase_is_invalid(unsigned int usecase) { - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - return usecase >= CRYPTOUSECASE_MAX_5X; - } else { - return usecase >= CRYPTOUSECASE_MAX; - } -} - -void seal_key_internal(void *dst, const void *src, const uint8_t *seal_key_source) { - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, KEYSLOT_SWITCH_SESSIONKEY, seal_key_source, 0x10); - se_aes_128_ecb_encrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10); -} - -void unseal_key_internal(unsigned int keyslot, const void *src, const uint8_t *seal_key_source) { - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, KEYSLOT_SWITCH_SESSIONKEY, seal_key_source, 0x10); - decrypt_data_into_keyslot(keyslot, KEYSLOT_SWITCH_TEMPKEY, src, 0x10); -} - - -void seal_titlekey(void *dst, size_t dst_size, const void *src, size_t src_size) { - if (dst_size != 0x10 || src_size != 0x10) { - generic_panic(); - } - - seal_key_internal(dst, src, g_titlekey_seal_key_source); - -} - -void unseal_titlekey(unsigned int keyslot, const void *src, size_t src_size) { - if (src_size != 0x10) { - generic_panic(); - } - - unseal_key_internal(keyslot, src, g_titlekey_seal_key_source); -} - - -void seal_key(void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int usecase) { - if (usecase_is_invalid(usecase) || dst_size != 0x10 || src_size != 0x10) { - generic_panic(); - } - - - seal_key_internal(dst, src, g_seal_key_sources[usecase]); -} - -void unseal_key(unsigned int keyslot, const void *src, size_t src_size, unsigned int usecase) { - if (usecase_is_invalid(usecase) || src_size != 0x10) { - generic_panic(); - } - - unseal_key_internal(keyslot, src, g_seal_key_sources[usecase]); -} \ No newline at end of file diff --git a/exosphere/src/sealedkeys.h b/exosphere/src/sealedkeys.h deleted file mode 100644 index 67e311620..000000000 --- a/exosphere/src/sealedkeys.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SEALED_KEYS_H -#define EXOSPHERE_SEALED_KEYS_H - -#include - -/* Key sealing/unsealing functionality. */ - -#define CRYPTOUSECASE_AES 0 -#define CRYPTOUSECASE_RSAPRIVATE 1 -#define CRYPTOUSECASE_SECUREEXPMOD 2 -#define CRYPTOUSECASE_RSAOAEP 3 -#define CRYPTOUSECASE_RSAIMPORT 4 -#define CRYPTOUSECASE_UNK5 5 -#define CRYPTOUSECASE_UNK6 6 - -#define CRYPTOUSECASE_MAX 4 -#define CRYPTOUSECASE_MAX_5X 7 - -void seal_titlekey(void *dst, size_t dst_size, const void *src, size_t src_size); -void unseal_titlekey(unsigned int keyslot, const void *src, size_t src_size); - -void seal_key(void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int usecase); -void unseal_key(unsigned int keyslot, const void *src, size_t src_size, unsigned int usecase); - -#endif \ No newline at end of file diff --git a/exosphere/src/smc_ams.c b/exosphere/src/smc_ams.c deleted file mode 100644 index 235dda460..000000000 --- a/exosphere/src/smc_ams.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * 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 -#include -#include - -#include "utils.h" -#include "smc_ams.h" -#include "arm.h" -#include "synchronization.h" -#include "memory_map.h" -#include "mmu.h" -#include "userpage.h" -#include "exocfg.h" - -static atomic_flag g_ams_userpage_mapped = ATOMIC_FLAG_INIT; -static atomic_flag g_ams_iram_page_mapped = ATOMIC_FLAG_INIT; - -static inline uintptr_t get_ams_user_page_secure_monitor_addr(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_USER_PAGE); -} - -static inline uintptr_t get_ams_iram_page_secure_monitor_addr(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE); -} - -#define AMS_USER_PAGE_SECURE_MONITOR_ADDR (get_ams_user_page_secure_monitor_addr()) -#define AMS_IRAM_PAGE_SECURE_MONITOR_ADDR (get_ams_iram_page_secure_monitor_addr()) - - -static inline uintptr_t get_page_for_address(void *address) { - return ((uintptr_t)(address)) & ~0xFFFULL; -} - -static bool ams_is_user_addr_valid(uintptr_t user_address) { - /* Check that the address is in dram. */ - uintptr_t page_address = get_page_for_address((void *)user_address); - return (page_address - 0x80000000ull) < (6ull << 30); -} - -static bool ams_is_iram_addr_valid(uintptr_t iram_address) { - /* Check that the address is in iram. */ - return 0x40000000ULL <= iram_address && iram_address <= 0x4003FFFFULL; -} - -static void ams_map_userpage(uintptr_t user_address) { - lock_acquire(&g_ams_userpage_mapped); - static const uint64_t userpage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_NORMAL; - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - mmu_map_page(mmu_l3_tbl, AMS_USER_PAGE_SECURE_MONITOR_ADDR, get_page_for_address((void *)user_address), userpage_attributes); - tlb_invalidate_page_inner_shareable((void *)AMS_USER_PAGE_SECURE_MONITOR_ADDR); -} - -static void ams_unmap_userpage(void) { - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - mmu_unmap_page(mmu_l3_tbl, AMS_USER_PAGE_SECURE_MONITOR_ADDR); - tlb_invalidate_page_inner_shareable((void *)AMS_USER_PAGE_SECURE_MONITOR_ADDR); - lock_release(&g_ams_userpage_mapped); -} - -void ams_map_irampage(uintptr_t iram_address) { - lock_acquire(&g_ams_iram_page_mapped); - static const uint64_t irampage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_DEVICE; - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - mmu_map_page(mmu_l3_tbl, AMS_IRAM_PAGE_SECURE_MONITOR_ADDR, get_page_for_address((void *)iram_address), irampage_attributes); - tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); -} - -void ams_unmap_irampage(void) { - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - mmu_unmap_page(mmu_l3_tbl, AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); - tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); - lock_release(&g_ams_iram_page_mapped); -} - -uint32_t ams_iram_copy(smc_args_t *args) { - /* Implements a DRAM <-> IRAM copy of up to one page. */ - /* This operation is necessary to implement reboot-to-payload. */ - /* args->X[1] = DRAM address (translated by kernel), must be 4-byte aligned. */ - /* args->X[2] = IRAM address, must be 4-byte aligned. */ - /* args->X[3] = size (must be <= 0x1000 and 4-byte aligned). */ - /* args->X[4] = 0 for read, 1 for write. */ - - const uintptr_t dram_address = (uintptr_t)args->X[1]; - const uintptr_t iram_address = (uintptr_t)args->X[2]; - const uintptr_t dram_page_offset = (dram_address & 0xFFFULL); - const uintptr_t iram_page_offset = (iram_address & 0xFFFULL); - const size_t size = args->X[3]; - const uint32_t option = (uint32_t)args->X[4]; - - /* Validate addresses. */ - if (!ams_is_user_addr_valid(dram_address) || !ams_is_iram_addr_valid(iram_address)) { - return 2; - } - - /* Validate size. */ - if (size > 0x1000 || (size + dram_page_offset) > 0x1000 || (size + iram_page_offset) > 0x1000) { - return 2; - } - - /* Validate alignment. */ - if (size % sizeof(uint32_t) || dram_page_offset % sizeof(uint32_t) || iram_page_offset % sizeof(uint32_t)) { - return 2; - } - - /* Validate argument. */ - if (option != 0 && option != 1) { - return 2; - } - - /* Map pages. */ - ams_map_userpage(dram_address); - ams_map_irampage(iram_address); - - /* Set source/destination for copy. */ - volatile uint32_t *dram_ptr = (volatile uint32_t *)(AMS_USER_PAGE_SECURE_MONITOR_ADDR + dram_page_offset); - volatile uint32_t *iram_ptr = (volatile uint32_t *)(AMS_IRAM_PAGE_SECURE_MONITOR_ADDR + iram_page_offset); - - volatile uint32_t *dst; - volatile uint32_t *src; - const size_t num_dwords = size / sizeof(uint32_t); - if (option == 0) { - dst = dram_ptr; - src = iram_ptr; - } else { - dst = iram_ptr; - src = dram_ptr; - } - - /* Actually copy data. */ - for (size_t i = 0; i < num_dwords; i++) { - dst[i] = src[i]; - } - - /* Flush! */ - flush_dcache_range((void *)dst, (void *)(dst + num_dwords)); - - /* Unmap pages. */ - ams_unmap_irampage(); - ams_unmap_userpage(); - - return 0; -} - -uint32_t ams_write_address(smc_args_t *args) { - /* Implements a write to a DRAM page. */ - /* This operation can be used to write to read-only pages. */ - /* args->X[1] = Virtual address, must be size-bytes aligned and readable by EL0. */ - /* args->X[2] = Value. */ - /* args->X[3] = size (must be 1, 2, 4, or 8). */ - - const uintptr_t el0_virtual_address = (uintptr_t)args->X[1]; - const uintptr_t dram_address = get_physical_address_el0(el0_virtual_address); - const uintptr_t dram_page_offset = (dram_address & 0xFFFULL); - const size_t size = (size_t)(args->X[3]); - - /* Validate addresses. */ - if (!ams_is_user_addr_valid(dram_address)) { - return 2; - } - - /* Validate size. */ - switch (size) { - case 1: - case 2: - case 4: - case 8: - if ((size + dram_page_offset) > 0x1000) { - return 2; - } - break; - default: - return 2; - } - - /* Validate alignment. */ - if (dram_page_offset % size) { - return 2; - } - - /* Map pages. */ - ams_map_userpage(dram_address); - - /* Write data. */ - uintptr_t dram_ptr = (uintptr_t)(AMS_USER_PAGE_SECURE_MONITOR_ADDR + dram_page_offset); - switch (size) { - case 1: - *((volatile uint8_t *)dram_ptr) = (uint8_t)(args->X[2]); - break; - case 2: - *((volatile uint16_t *)dram_ptr) = (uint16_t)(args->X[2]); - break; - case 4: - *((volatile uint32_t *)dram_ptr) = (uint32_t)(args->X[2]); - break; - case 8: - *((volatile uint64_t *)dram_ptr) = args->X[2]; - break; - default: - generic_panic(); - } - - /* Flush! */ - flush_dcache_range((void *)dram_ptr, (void *)(dram_ptr + size)); - - /* Unmap pages. */ - ams_unmap_userpage(); - - return 0; -} - -uint32_t ams_get_emummc_config(smc_args_t *args) { - /* This retrieves configuration for the current emummc context. */ - /* args->X[1] = MMC id, must be size-bytes aligned and readable by EL0. */ - /* args->X[2] = Pointer to output (for paths for filebased + nintendo dir), must be at least 0x100 bytes. */ - const uint32_t mmc_id = (uint32_t)args->X[1]; - const uintptr_t dram_address = args->X[2]; - const uintptr_t dram_page_offset = (dram_address & 0xFFFULL); - const exo_emummc_config_t *emummc_cfg = exosphere_get_emummc_config(); - - if (mmc_id != EMUMMC_MMC_NAND) { - /* Emummc config for non-NAND storage is not yet implemented. */ - return 1; - } - - /* Require page alignment for input address. */ - if (!ams_is_user_addr_valid(dram_address) || dram_page_offset > 0x1000 - 0x100) { - return 2; - } - - /* Map pages. */ - ams_map_userpage(dram_address); - - void *user_address = (void *)(AMS_USER_PAGE_SECURE_MONITOR_ADDR + dram_page_offset); - - /* Copy redirection dir out to user. */ - memcpy((void *)((uintptr_t)user_address + sizeof(emummc_cfg->file_cfg)), emummc_cfg->emu_dir_path, sizeof(emummc_cfg->emu_dir_path)); - - if (emummc_cfg->base_cfg.type == EMUMMC_TYPE_NONE) { - /* Just copy base config. */ - memset(args, 0, sizeof(*args)); - memcpy(&args->X[1], emummc_cfg, sizeof(emummc_cfg->base_cfg)); - _Static_assert(sizeof(emummc_cfg->base_cfg) <= sizeof(*args) - sizeof(args->X[0]), "Emunand base config too big!"); - - /* Unmap pages. */ - ams_unmap_userpage(); - return 0; - } else if (emummc_cfg->base_cfg.type == EMUMMC_TYPE_PARTITION) { - /* Copy base config and partition config. */ - memset(args, 0, sizeof(*args)); - memcpy(&args->X[1], emummc_cfg, sizeof(emummc_cfg->base_cfg) + sizeof(emummc_cfg->partition_cfg)); - _Static_assert(sizeof(emummc_cfg->base_cfg) + sizeof(emummc_cfg->partition_cfg) <= sizeof(*args) - sizeof(args->X[0]), "Emunand partition config too big!"); - - /* Unmap pages. */ - ams_unmap_userpage(); - return 0; - } else if (emummc_cfg->base_cfg.type == EMUMMC_TYPE_FILES) { - /* Copy file dir path output to user. */ - memcpy(user_address, &emummc_cfg->file_cfg, sizeof(emummc_cfg->file_cfg)); - - /* Copy base config afterwards, since this can't fail. */ - memset(args, 0, sizeof(*args)); - memcpy(&args->X[1], emummc_cfg, sizeof(emummc_cfg->base_cfg)); - _Static_assert(sizeof(emummc_cfg->base_cfg) <= sizeof(*args) - sizeof(args->X[0]), "Emunand base config too big!"); - - /* Unmap pages. */ - ams_unmap_userpage(); - return 0; - } else { - /* Unmap pages. */ - ams_unmap_userpage(); - return 2; - } -} \ No newline at end of file diff --git a/exosphere/src/smc_ams.h b/exosphere/src/smc_ams.h deleted file mode 100644 index 7235f6125..000000000 --- a/exosphere/src/smc_ams.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SMC_AMS_H -#define EXOSPHERE_SMC_AMS_H - -#include "smc_api.h" - -uint32_t ams_iram_copy(smc_args_t *args); -uint32_t ams_write_address(smc_args_t *args); - -uint32_t ams_get_emummc_config(smc_args_t *args); - -void ams_map_irampage(uintptr_t iram_address); -void ams_unmap_irampage(void); - -#endif \ No newline at end of file diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c deleted file mode 100644 index 4b3673f6c..000000000 --- a/exosphere/src/smc_api.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "memory_map.h" - -#include "configitem.h" -#include "cpu_context.h" -#include "synchronization.h" -#include "masterkey.h" -#include "mc.h" -#include "mc0.h" -#include "mc1.h" -#include "memory_map.h" -#include "pmc.h" -#include "randomcache.h" -#include "sealedkeys.h" -#include "smc_api.h" -#include "smc_user.h" -#include "smc_ams.h" -#include "se.h" -#include "userpage.h" -#include "titlekey.h" -#include "sc7.h" -#include "exocfg.h" - -#define DEBUG_LOG_SMCS 0 -#define DEBUG_PANIC_ON_FAILURE 0 - -/* User SMC prototypes */ -uint32_t smc_set_config_user(smc_args_t *args); -uint32_t smc_get_config_user(smc_args_t *args); -uint32_t smc_check_status(smc_args_t *args); -uint32_t smc_get_result(smc_args_t *args); -uint32_t smc_exp_mod(smc_args_t *args); -uint32_t smc_get_random_bytes_for_user(smc_args_t *args); -uint32_t smc_generate_aes_kek(smc_args_t *args); -uint32_t smc_load_aes_key(smc_args_t *args); -uint32_t smc_crypt_aes(smc_args_t *args); -uint32_t smc_generate_specific_aes_key(smc_args_t *args); -uint32_t smc_compute_cmac(smc_args_t *args); -uint32_t smc_load_rsa_oaep_key(smc_args_t *args); -uint32_t smc_decrypt_rsa_private_key(smc_args_t *args); -uint32_t smc_load_secure_exp_mod_key(smc_args_t *args); -uint32_t smc_secure_exp_mod(smc_args_t *args); -uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args); -uint32_t smc_load_titlekey(smc_args_t *args); -uint32_t smc_unwrap_aes_wrapped_titlekey(smc_args_t *args); - -/* 5.x SMC prototypes. */ -uint32_t smc_encrypt_rsa_key_for_import(smc_args_t *args); -uint32_t smc_decrypt_or_import_rsa_key(smc_args_t *args); - -/* Privileged SMC prototypes */ -uint32_t smc_cpu_suspend(smc_args_t *args); -uint32_t smc_cpu_off(smc_args_t *args); -uint32_t smc_cpu_on(smc_args_t *args); -uint32_t smc_get_config_priv(smc_args_t *args); -uint32_t smc_get_random_bytes_for_priv(smc_args_t *args); -uint32_t smc_panic(smc_args_t *args); -uint32_t smc_configure_carveout(smc_args_t *args); -uint32_t smc_read_write_register(smc_args_t *args); - -/* Atmosphere SMC prototypes */ -uint32_t smc_ams_iram_copy(smc_args_t *args); -uint32_t smc_ams_write_address(smc_args_t *args); -uint32_t smc_ams_get_emummc_config(smc_args_t *args); - -/* TODO: Provide a way to set this. It's 0 on non-recovery boot anyway... */ -static uint32_t g_smc_blacklist_mask = 0; - -typedef struct { - uint32_t id; - uint32_t blacklist_mask; - uint32_t (*handler)(smc_args_t *args); -} smc_table_entry_t; - -typedef struct { - smc_table_entry_t *handlers; - uint32_t num_handlers; -} smc_table_t; - -static smc_table_entry_t g_smc_user_table[] = { - {0, 4, NULL}, - {0xC3000401, 4, smc_set_config_user}, - {0xC3000002, 1, smc_get_config_user}, - {0xC3000003, 1, smc_check_status}, - {0xC3000404, 1, smc_get_result}, - {0xC3000E05, 4, smc_exp_mod}, - {0xC3000006, 1, smc_get_random_bytes_for_user}, - {0xC3000007, 1, smc_generate_aes_kek}, - {0xC3000008, 1, smc_load_aes_key}, - {0xC3000009, 1, smc_crypt_aes}, - {0xC300000A, 1, smc_generate_specific_aes_key}, - {0xC300040B, 1, smc_compute_cmac}, - {0xC300100C, 1, smc_load_rsa_oaep_key}, - {0xC300100D, 2, smc_decrypt_rsa_private_key}, - {0xC300100E, 4, smc_load_secure_exp_mod_key}, - {0xC300060F, 2, smc_secure_exp_mod}, - {0xC3000610, 4, smc_unwrap_rsa_oaep_wrapped_titlekey}, - {0xC3000011, 4, smc_load_titlekey}, - {0xC3000012, 4, smc_unwrap_aes_wrapped_titlekey} -}; -#define SMC_USER_HANDLERS (sizeof(g_smc_user_table) / sizeof(g_smc_user_table[0])) - -static smc_table_entry_t g_smc_priv_table[] = { - {0, 4, NULL}, - {0xC4000001, 4, smc_cpu_suspend}, - {0x84000002, 4, smc_cpu_off}, - {0xC4000003, 1, smc_cpu_on}, - {0xC3000004, 1, smc_get_config_priv}, - {0xC3000005, 1, smc_get_random_bytes_for_priv}, - {0xC3000006, 1, smc_panic}, - {0xC3000007, 1, smc_configure_carveout}, - {0xC3000008, 1, smc_read_write_register} -}; -#define SMC_PRIV_HANDLERS (sizeof(g_smc_priv_table) / sizeof(g_smc_priv_table[0])) - -/* This is a table used for atmosphere-specific SMCs. */ -static smc_table_entry_t g_smc_ams_table[] = { - {0, 4, NULL}, - {0xF0000201, 0, smc_ams_iram_copy}, - {0xF0000002, 0, smc_read_write_register}, - {0xF0000003, 0, smc_ams_write_address}, - {0xF0000404, 0, smc_ams_get_emummc_config}, -}; -#define SMC_AMS_HANDLERS (sizeof(g_smc_ams_table) / sizeof(g_smc_ams_table[0])) - -static smc_table_t g_smc_tables[SMC_HANDLER_COUNT + 1] = { - { /* SMC_HANDLER_USER */ - g_smc_user_table, - SMC_USER_HANDLERS - }, - { /* SMC_HANDLER_PRIV */ - g_smc_priv_table, - SMC_PRIV_HANDLERS - }, - { /* SMC_HANDLER_AMS */ - g_smc_ams_table, - SMC_AMS_HANDLERS - } -}; - -static atomic_flag g_is_user_smc_in_progress = ATOMIC_FLAG_INIT; -static atomic_flag g_is_priv_smc_in_progress = ATOMIC_FLAG_INIT; - -/* Global for smc_configure_carveout. */ -static bool g_configured_carveouts[2] = {false, false}; - -static bool g_has_suspended = false; -void set_suspend_for_debug(void) { - g_has_suspended = true; -} - -void set_version_specific_smcs(void) { - const uint32_t target_firmware = exosphere_get_target_firmware(); - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - /* No more LoadSecureExpModKey. */ - g_smc_user_table[0xE].handler = NULL; - g_smc_user_table[0xC].id = 0xC300D60C; - g_smc_user_table[0xC].handler = smc_encrypt_rsa_key_for_import; - g_smc_user_table[0xD].handler = smc_decrypt_or_import_rsa_key; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_2_0_0) { - /* Nothing to do. */ - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_1_0_0) { - /* 1.0.0 doesn't have ConfigureCarveout or ReadWriteRegister. */ - g_smc_priv_table[7].handler = NULL; - g_smc_priv_table[8].handler = NULL; - /* 1.0.0 doesn't have UnwrapAesWrappedTitlekey. */ - g_smc_user_table[0x12].handler = NULL; - } else { - panic_predefined(0xA); - } -} - - -uintptr_t get_smc_core012_stack_address(void) { - return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_CORE012_STACK) + 0x1000; -} - -uintptr_t get_exception_entry_stack_address(unsigned int core_id) { - /* For core3, this is also the smc stack */ - if (core_id == 3) { - return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000; - } - else { - return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x80 * (core_id + 1); - } -} - -bool try_set_user_smc_in_progress(void) { - return lock_try_acquire(&g_is_user_smc_in_progress); -} -void set_user_smc_in_progress(void) { - lock_acquire(&g_is_user_smc_in_progress); -} -void clear_user_smc_in_progress(void) { - lock_release(&g_is_user_smc_in_progress); -} - -/* Privileged SMC lock must be available to exceptions.s. */ -void set_priv_smc_in_progress(void) { - lock_acquire(&g_is_priv_smc_in_progress); -} -void clear_priv_smc_in_progress(void) { - lock_release(&g_is_priv_smc_in_progress); -} - -uint32_t (*g_smc_callback)(void *, uint64_t) = NULL; -uint64_t g_smc_callback_key = 0; - -uint64_t try_set_smc_callback(uint32_t (*callback)(void *, uint64_t)) { - uint64_t key; - if (g_smc_callback_key) { - return 0; - } - - se_generate_random(KEYSLOT_SWITCH_RNGKEY, &key, sizeof(uint64_t)); - g_smc_callback_key = key; - g_smc_callback = callback; - return key; -} - -void clear_smc_callback(uint64_t key) { - if (g_smc_callback_key == key) { - g_smc_callback_key = 0; - } -} - -_Atomic uint64_t num_smcs_called = 0; - -void call_smc_handler(uint32_t handler_id, smc_args_t *args) { - unsigned char smc_id, call_range; - unsigned int result; - unsigned int (*smc_handler)(smc_args_t *args); - - /* Validate top-level handler. */ - if (handler_id >= SMC_HANDLER_COUNT) { - generic_panic(); - } - - /* If user-handler, detect if talking to Atmosphere/validate calling core. */ - if (handler_id == SMC_HANDLER_USER) { - if ((call_range = (unsigned char)((args->X[0] >> 24) & 0x3F)) == SMC_CALL_RANGE_TRUSTED_APP) { - /* Nintendo's SMCs are all OEM-specific. */ - /* Pending a reason not to, we will treat Trusted Application SMCs as intended to talk to Atmosphere. */ - handler_id = SMC_HANDLER_AMS; - } else if (get_core_id() != 3) { - /* USER SMCs must be called via svcCallSecureMonitor on core 3 (where spl runs) */ - generic_panic(); - } - } - - /* Validate sub-handler index */ - if ((smc_id = (unsigned char)args->X[0]) >= g_smc_tables[handler_id].num_handlers) { - generic_panic(); - } - - /* Validate sub-handler */ - if (g_smc_tables[handler_id].handlers[smc_id].id != args->X[0]) { - generic_panic(); - } - - /* Validate handler. */ - if ((smc_handler = g_smc_tables[handler_id].handlers[smc_id].handler) == NULL) { - generic_panic(); - } - - bool is_aes_kek = handler_id == SMC_HANDLER_USER && args->X[0] == 0xC3000007; - -#if DEBUG_LOG_SMCS - uint64_t num; - if (handler_id == SMC_HANDLER_USER) { - num = atomic_fetch_add(&num_smcs_called, 1); - *(volatile smc_args_t *)(get_iram_address_for_debug() + 0x100 + ((0x80 * num) & 0x3FFF)) = *args; - } -#endif - - /* Call function. */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_8_0_0 || - (g_smc_tables[handler_id].handlers[smc_id].blacklist_mask & g_smc_blacklist_mask) == 0) { - args->X[0] = smc_handler(args); - } else { - /* Call not allowed due to current boot conditions. */ - args->X[0] = 6; - } - -#if DEBUG_LOG_SMCS - if (handler_id == SMC_HANDLER_USER) { - *(volatile smc_args_t *)(get_iram_address_for_debug() + 0x100 + ((0x80 * num + 0x40) & 0x3FFF)) = *args; - } -#endif - -#if DEBUG_PANIC_ON_FAILURE - if (args->X[0] && (!is_aes_kek || args->X[3] <= ATMOSPHERE_TARGET_FIRMWARE_CURRENT)) - { - MAKE_REG32(get_iram_address_for_debug() + 0x4FF0) = handler_id; - MAKE_REG32(get_iram_address_for_debug() + 0x4FF4) = smc_id; - MAKE_REG32(get_iram_address_for_debug() + 0x4FF8) = get_core_id(); - *(volatile smc_args_t *)(get_iram_address_for_debug() + 0x4F00) = *args; - panic(PANIC_REBOOT); - } -#else - (void)(is_aes_kek); -#endif - (void)result; /* FIXME: result unused */ -} - -uint32_t smc_wrapper_sync(smc_args_t *args, uint32_t (*handler)(smc_args_t *)) { - uint32_t result; - if (!try_set_user_smc_in_progress()) { - return 3; - } - result = handler(args); - clear_user_smc_in_progress(); - return result; -} - -uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), uint32_t (*callback)(void *, uint64_t)) { - uint32_t result; - uint64_t key; - if (!try_set_user_smc_in_progress()) { - return 3; - } - if ((key = try_set_smc_callback(callback)) != 0) { - result = handler(args); - if (result == 0) { - /* Pass the status check key back to userland. */ - args->X[1] = key; - /* Early return, leaving g_is_user_smc_in_progress locked */ - return result; - } else { - /* No status to check. */ - clear_smc_callback(key); - } - } else { - /* smcCheckStatus needs to be called. */ - result = 3; - } - clear_user_smc_in_progress(); - return result; -} - -uint32_t smc_set_config_user(smc_args_t *args) { - /* Actual value presumed in X3 on hardware. */ - return configitem_set(false, (ConfigItem)args->X[1], args->X[3]); -} - -uint32_t smc_get_config_user(smc_args_t *args) { - uint64_t out_item = 0; - uint32_t result; - result = configitem_get(false, (ConfigItem)args->X[1], &out_item); - args->X[1] = out_item; - return result; -} - -uint32_t smc_check_status(smc_args_t *args) { - if (g_smc_callback_key == 0) { - return 4; - } - - if (args->X[1] != g_smc_callback_key) { - return 5; - } - - args->X[1] = g_smc_callback(NULL, 0); - - g_smc_callback_key = 0; - return 0; -} - -uint32_t smc_get_result(smc_args_t *args) { - uint32_t status; - unsigned char result_buf[0x400]; - upage_ref_t page_ref; - - void *user_address = (void *)args->X[2]; - - if (g_smc_callback_key == 0) { - return 4; - } - - if (args->X[1] != g_smc_callback_key) { - return 5; - } - - /* Check result size */ - if (args->X[3] > 0x400) { - return 2; - } - - args->X[1] = g_smc_callback(result_buf, args->X[3]); - g_smc_callback_key = 0; - - /* Initialize page reference. */ - if (upage_init(&page_ref, user_address) == 0) { - return 2; - } - - /* Copy result output back to user. */ - if (secure_copy_to_user(&page_ref, user_address, result_buf, (size_t)args->X[3]) == 0) { - return 2; - } - - return 0; - (void)status; /* FIXME: status unused */ -} - -uint32_t smc_exp_mod_get_result(void *buf, uint64_t size) { - uint32_t res = get_exp_mod_result(); - if (res == 0) { - if (size == 0x100) { - se_get_exp_mod_output(buf, 0x100); - /* smc_exp_mod is done now. */ - clear_user_smc_in_progress(); - res = 0; - } else { - res = 2; - } - } - return res; -} - -uint32_t smc_exp_mod(smc_args_t *args) { - return smc_wrapper_async(args, user_exp_mod, smc_exp_mod_get_result); -} - -uint32_t smc_get_random_bytes_for_user(smc_args_t *args) { - return smc_wrapper_sync(args, user_get_random_bytes); -} - -uint32_t smc_generate_aes_kek(smc_args_t *args) { - return smc_wrapper_sync(args, user_generate_aes_kek); -} - -uint32_t smc_load_aes_key(smc_args_t *args) { - return smc_wrapper_sync(args, user_load_aes_key); -} - -uint32_t smc_crypt_aes_status_check(void *buf, uint64_t size) { - /* Buf and size are unused. */ - if (get_crypt_aes_done() != 1) { - return 3; - } - /* smc_crypt_aes is done now. */ - clear_user_smc_in_progress(); - return 0; -} - -uint32_t smc_crypt_aes(smc_args_t *args) { - return smc_wrapper_async(args, user_crypt_aes, smc_crypt_aes_status_check); -} - -uint32_t smc_generate_specific_aes_key(smc_args_t *args) { - return smc_wrapper_sync(args, user_generate_specific_aes_key); -} - -uint32_t smc_compute_cmac(smc_args_t *args) { - return smc_wrapper_sync(args, user_compute_cmac); -} - -uint32_t smc_load_rsa_oaep_key(smc_args_t *args) { - return smc_wrapper_sync(args, user_load_rsa_oaep_key); -} - -uint32_t smc_decrypt_rsa_private_key(smc_args_t *args) { - return smc_wrapper_sync(args, user_decrypt_rsa_private_key); -} - -uint32_t smc_load_secure_exp_mod_key(smc_args_t *args) { - return smc_wrapper_sync(args, user_load_secure_exp_mod_key); -} - -uint32_t smc_secure_exp_mod(smc_args_t *args) { - return smc_wrapper_async(args, user_secure_exp_mod, smc_exp_mod_get_result); -} - -uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey_get_result(void *buf, uint64_t size) { - uint64_t *p_sealed_key = (uint64_t *)buf; - uint8_t rsa_wrapped_titlekey[0x100]; - uint8_t aes_wrapped_titlekey[0x10]; - uint8_t titlekey[0x10]; - uint64_t sealed_titlekey[2]; - uint32_t res = get_exp_mod_result(); - if (res == 0) { - if (size == 0x10) { - se_get_exp_mod_output(rsa_wrapped_titlekey, 0x100); - if (tkey_rsa_oaep_unwrap(aes_wrapped_titlekey, 0x10, rsa_wrapped_titlekey, 0x100) == 0x10) { - tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10); - seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10); - - p_sealed_key[0] = sealed_titlekey[0]; - p_sealed_key[1] = sealed_titlekey[1]; - - res = 0; - } else { - /* Failed to extract RSA OAEP wrapped key. */ - res = 2; - } - - /* smc_unwrap_rsa_oaep_wrapped_titlekey is done now. */ - clear_user_smc_in_progress(); - } else { - res = 2; - } - } - - return res; -} - -uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { - return smc_wrapper_async(args, user_unwrap_rsa_oaep_wrapped_titlekey, smc_unwrap_rsa_oaep_wrapped_titlekey_get_result); -} - -uint32_t smc_load_titlekey(smc_args_t *args) { - return smc_wrapper_sync(args, user_load_titlekey); -} - -uint32_t smc_unwrap_aes_wrapped_titlekey(smc_args_t *args) { - return smc_wrapper_sync(args, user_unwrap_aes_wrapped_titlekey); -} - -uint32_t smc_encrypt_rsa_key_for_import(smc_args_t *args) { - return smc_wrapper_sync(args, user_encrypt_rsa_key_for_import); -} - -uint32_t smc_decrypt_or_import_rsa_key(smc_args_t *args) { - return smc_wrapper_sync(args, user_decrypt_or_import_rsa_key); -} - - -uint32_t smc_cpu_on(smc_args_t *args) { - return cpu_on((uint32_t)args->X[1], args->X[2], args->X[3]); -} - -uint32_t smc_cpu_off(smc_args_t *args) { - return cpu_off(); -} - -/* Wrapper for cpu_suspend */ -uint32_t cpu_suspend_wrapper(smc_args_t *args) { - return cpu_suspend(args->X[1], args->X[2], args->X[3]); -} - -uint32_t smc_cpu_suspend(smc_args_t *args) { - return smc_wrapper_sync(args, cpu_suspend_wrapper); -} - -uint32_t smc_get_config_priv(smc_args_t *args) { - uint64_t out_item = 0; - uint32_t result; - result = configitem_get(true, (ConfigItem)args->X[1], &out_item); - args->X[1] = out_item; - return result; -} - -uint32_t smc_get_random_bytes_for_priv(smc_args_t *args) { - /* This is an interesting SMC. */ - /* The kernel must NEVER be unable to get random bytes, if it needs them */ - /* As such: */ - - uint32_t result; - - if (!try_set_user_smc_in_progress()) { - if (args->X[1] > 0x38) { - return 2; - } - /* Retrieve bytes from the cache. */ - size_t num_bytes = (size_t)args->X[1]; - randomcache_getbytes(&args->X[1], num_bytes); - result = 0; - } else { - /* If the kernel isn't denied service by a usermode SMC, generate fresh random bytes. */ - result = user_get_random_bytes(args); - /* Also, refill our cache while we have the chance in case we get denied later. */ - randomcache_refill(); - clear_user_smc_in_progress(); - } - return result; -} - -uint32_t smc_read_write_register(smc_args_t *args) { - uint64_t address = args->X[1]; - uint32_t mask = (uint32_t)(args->X[2]); - uint32_t value = (uint32_t)(args->X[3]); - volatile uint32_t *p_mmio = NULL; - /* Address must be aligned. */ - if (address & 3) { - return 2; - } - /* Check for PMC registers. */ - if (0x7000E400 <= address && address <= 0x7000EFFF) { - static const uint8_t pmc_whitelist[0x28] = { - 0xB9, 0xF9, 0x07, 0x00, 0x00, 0x00, 0x80, 0x03, - 0x00, 0x00, 0x00, 0x17, 0x00, 0xC4, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00 - }; - /* Offset = Address - PMC_BASE */ - uint32_t offset = (uint32_t)(address - 0x7000E400); - uint32_t wl_ind = (offset >> 5); - /* If address is whitelisted, allow write. */ - if (wl_ind < sizeof(pmc_whitelist) && (pmc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7)))) { - p_mmio = (volatile uint32_t *)(PMC_BASE + offset); - } else { - return 2; - } - } else { - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - static const uint8_t mc_whitelist_5x[0xD00/(sizeof(uint32_t) * 8)] = { - 0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E, - 0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04, - 0x80, 0xFF, 0x08, 0x80, 0x03, 0x38, 0x8E, 0x1F, - 0xC8, 0xFF, 0xFF, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0xF0, 0x1F, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, - 0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00 - }; - static const uint8_t mc01_whitelist_5x[0xC00/(sizeof(uint32_t) * 8)] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, - }; - static const struct { - uint32_t phys_addr; - uint32_t size; - uint64_t virt_addr; - const uint8_t *whitelist; - } register_whitelists[3] = { - { MMIO_GET_DEVICE_PA(MMIO_DEVID_MC), sizeof(mc_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC), mc_whitelist_5x }, - { MMIO_GET_DEVICE_PA(MMIO_DEVID_MC0), sizeof(mc01_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC0), mc01_whitelist_5x }, - { MMIO_GET_DEVICE_PA(MMIO_DEVID_MC1), sizeof(mc01_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC1), mc01_whitelist_5x }, - }; - for (unsigned int which = 0; which < 3; which++) { - if (register_whitelists[which].phys_addr <= address && address < register_whitelists[which].phys_addr + register_whitelists[which].size) { - uint32_t offset = (uint32_t)(address - register_whitelists[which].phys_addr); - uint32_t wl_ind = (offset >> 5); - /* If address is whitelisted, allow write. */ - if (register_whitelists[which].whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7))) { - p_mmio = (volatile uint32_t *)(register_whitelists[which].virt_addr + offset); - } - break; - } - } - } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - if (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address && address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + 0xD00) { - /* Memory Controller RW supported only on 4.0.0+ */ - static const uint8_t mc_whitelist[0x68] = { - 0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01, - 0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E, - 0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04, - 0x80, 0x1F, 0x08, 0x80, 0x03, 0x00, 0x0E, 0x00, - 0x08, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F, - 0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00 - }; - uint32_t offset = (uint32_t)(address - MMIO_GET_DEVICE_PA(MMIO_DEVID_MC)); - uint32_t wl_ind = (offset >> 5); - /* If address is whitelisted, allow write. */ - if (mc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7))) { - p_mmio = (volatile uint32_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC) + offset); - } - } - } - } - - /* Perform actual write. */ - if (p_mmio != NULL) { - uint32_t old_value; - /* Write whole value. */ - if (mask == 0xFFFFFFFF) { - old_value = 0; - } else { - old_value = *p_mmio; - } - if (mask) { - *p_mmio = (old_value & ~mask) | (value & mask); - } - /* Return old value. */ - args->X[1] = old_value; - return 0; - } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0 && (address == 0x7001923C || address == 0x70019298)) { - /* These addresses are not allowed by the whitelist. */ - /* They correspond to SMMU DISABLE for the BPMP, and for APB-DMA. */ - /* However, smcReadWriteRegister returns 0 for these addresses despite not actually performing the write. */ - /* This is "probably" to fuck with hackers who got access to smcReadWriteRegister and are trying to get */ - /* control of the BPMP for jamais vu etc., since there's no other reason to return 0 despite failure. */ - return 0; - } else { - return 2; - } -} - - -uint32_t smc_configure_carveout(smc_args_t *args) { - unsigned int carveout_id = (unsigned int)args->X[1]; - uint64_t address = args->X[2]; - uint64_t size = args->X[3]; - - /* Ensure carveout isn't too big. */ - if (size > KERNEL_CARVEOUT_SIZE_MAX) { - return 2; - } - - /* Ensure validity of carveout index. */ - if (carveout_id > 1) { - return 2; - } - - /* Configuration is one-shot, and cannot be done multiple times. */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { - if (g_configured_carveouts[carveout_id]) { - return 2; - } - } - - configure_kernel_carveout(carveout_id + 4, address, size); - g_configured_carveouts[carveout_id] = true; - return 0; -} - -uint32_t smc_panic(smc_args_t *args) { - /* Swap RGB values from args. */ - uint32_t color = ((args->X[1] & 0xF) << 8) | ((args->X[1] & 0xF0)) | ((args->X[1] & 0xF00) >> 8); - panic((color << 20) | 0x40); -} - -uint32_t smc_ams_iram_copy(smc_args_t *args) { - return smc_wrapper_sync(args, ams_iram_copy); -} - -uint32_t smc_ams_write_address(smc_args_t *args) { - return smc_wrapper_sync(args, ams_write_address); -} - -uint32_t smc_ams_get_emummc_config(smc_args_t *args) { - return smc_wrapper_sync(args, ams_get_emummc_config); -} diff --git a/exosphere/src/smc_api.h b/exosphere/src/smc_api.h deleted file mode 100644 index 862a28f5d..000000000 --- a/exosphere/src/smc_api.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SMC_API_H -#define EXOSPHERE_SMC_API_H - -#include - -#define SMC_HANDLER_USER 0 -#define SMC_HANDLER_PRIV 1 -#define SMC_HANDLER_COUNT 2 - -#define SMC_HANDLER_AMS (SMC_HANDLER_COUNT) - -#define SMC_CALL_RANGE_ARM_ARCH 0 -#define SMC_CALL_RANGE_CPU 1 -#define SMC_CALL_RANGE_SIP 2 -#define SMC_CALL_RANGE_OEM 3 -#define SMC_CALL_RANGE_STANDARD 4 - -#define SMC_CALL_RANGE_TRUSTED_APP 0x30 - -typedef struct { - uint64_t X[8]; -} smc_args_t; - -bool try_set_user_smc_in_progress(void); -void set_user_smc_in_progress(void); -void clear_user_smc_in_progress(void); - -void set_priv_smc_in_progress(void); -void clear_priv_smc_in_progress(void); - -uintptr_t get_smc_core012_stack_address(void); -uintptr_t get_exception_entry_stack_address(unsigned int core_id); - -void set_version_specific_smcs(void); - - -void set_suspend_for_debug(void); - -void call_smc_handler(unsigned int handler_id, smc_args_t *args); - -#endif diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c deleted file mode 100644 index 8c0fba6d6..000000000 --- a/exosphere/src/smc_user.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * 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 -#include - -#include "utils.h" -#include "arm.h" -#include "configitem.h" -#include "gcm.h" -#include "masterkey.h" -#include "smc_api.h" -#include "smc_user.h" -#include "se.h" -#include "fuse.h" -#include "sealedkeys.h" -#include "userpage.h" -#include "titlekey.h" -#include "exocfg.h" - -/* Globals. */ -static bool g_crypt_aes_done = false; -static uint32_t g_exp_mod_result = 0; - -static __attribute__((aligned(4))) uint8_t g_imported_exponents[4][0x100]; -static __attribute__((aligned(4))) uint8_t g_imported_moduli[4][0x100]; -static bool g_is_modulus_verified[4]; - -static __attribute__((aligned(4))) const uint8_t g_rsa_public_key[4] = { 0x00, 0x01, 0x00, 0x01 }; - -static __attribute__((aligned(4))) const uint8_t g_rsa_test_vector[0x100] = { - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', - 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D' -}; - -static uint32_t g_test_exp_mod_keyslot = 0; -static uint32_t g_test_exp_mod_usecase = 0; -static bool g_test_exp_mod_in_progress = false; - -static uint8_t g_rsausecase_to_cryptousecase[5] = {1, 2, 3, 5, 6}; - -static void import_rsa_exponent(unsigned int which, const uint8_t *exponent, uint64_t size) { - g_is_modulus_verified[which] = false; - for (unsigned int i = 0; i < 0x100; i++) { - g_imported_exponents[which][i] = exponent[i]; - g_imported_moduli[which][i] = 0; - } -} - -static void import_rsa_modulus(unsigned int which, const uint8_t *modulus, uint64_t size) { - uint64_t clamped_size = 0x100; - if (size <= 0x100) { - clamped_size = size; - } - if (clamped_size != 0) { - /* The official secure monitor implements this via bit-fiddling, */ - /* and to prevent accidental inaccuracy we will too. */ - /* It's probably done to prevent errors on negative sizes. */ - uint64_t remaining = 0x100; - if (size != 0x100 && (~size >= ~0xFFFFFFFFFFFFFEFFULL)) { - remaining = size; - } - memcpy(&g_imported_moduli[which][0], modulus, remaining); - } -} - -static bool load_imported_rsa_keypair(unsigned int keyslot, unsigned int which) { - if (!g_is_modulus_verified[which]) { - return false; - } - set_rsa_keyslot(keyslot, g_imported_moduli[which], 0x100, g_imported_exponents[which], 0x100); - return true; -} - -static void test_rsa_modulus_public(unsigned int which, unsigned int keyslot, const uint8_t *modulus, uint64_t modulus_size, unsigned int (*callback)(void)) { - import_rsa_modulus(which, modulus, modulus_size); - set_rsa_keyslot(keyslot, modulus, modulus_size, g_rsa_public_key, 0x4); - se_exp_mod(keyslot, g_rsa_test_vector, 0x100, callback); -} - -static void test_rsa_modulus_private(unsigned int which, unsigned int keyslot, unsigned int (*callback)(void)) { - uint8_t exponentiated_data[0x100]; - se_get_exp_mod_output(exponentiated_data, sizeof(exponentiated_data)); - set_rsa_keyslot(keyslot, g_imported_moduli[which], 0x100, g_imported_exponents[which], 0x100); - se_exp_mod(keyslot, exponentiated_data, 0x100, callback); -} - -static void validate_rsa_result(unsigned int which) { - char result[0x100]; - se_get_exp_mod_output(result, sizeof(result)); - if (memcmp(result, g_rsa_test_vector, sizeof(result)) == 0) { - g_is_modulus_verified[which] = true; - } -} - -static bool is_user_keyslot_valid(unsigned int keyslot) { - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - return keyslot <= 5; - } else { - return keyslot <= 3; - } -} - -void set_exp_mod_result(uint32_t result) { - g_exp_mod_result = result; -} - -uint32_t get_exp_mod_result(void) { - return g_exp_mod_result; -} - -uint32_t exp_mod_done_handler(void) { - set_exp_mod_result(0); - - se_trigger_interrupt(); - - return 0; -} - -static uint32_t test_exp_mod_done_handler(void) { - if (g_test_exp_mod_in_progress) { - g_test_exp_mod_in_progress = false; - test_rsa_modulus_private(g_test_exp_mod_usecase, g_test_exp_mod_keyslot, test_exp_mod_done_handler); - } else { - validate_rsa_result(g_test_exp_mod_usecase); - if (load_imported_rsa_keypair(g_test_exp_mod_keyslot, g_test_exp_mod_usecase)) { - se_exp_mod(g_test_exp_mod_keyslot, g_rsa_shared_data.storage_exp_mod.user_data, 0x100, exp_mod_done_handler); - } else { - set_exp_mod_result(2); - se_trigger_interrupt(); - } - } - - return 0; -} - -uint32_t user_exp_mod(smc_args_t *args) { - uint8_t modulus[0x100]; - uint8_t exponent[0x100]; - uint8_t input[0x100]; - - upage_ref_t page_ref; - - /* Validate size. */ - if (args->X[4] == 0 || args->X[4] > 0x100 || (args->X[4] & 3) != 0) { - return 2; - } - - size_t exponent_size = (size_t)args->X[4]; - - void *user_input = (void *)args->X[1]; - void *user_exponent = (void *)args->X[2]; - void *user_modulus = (void *)args->X[3]; - - /* Copy user data into secure memory. */ - if (upage_init(&page_ref, user_input) == 0) { - return 2; - } - if (user_copy_to_secure(&page_ref, input, user_input, 0x100) == 0) { - return 2; - } - if (user_copy_to_secure(&page_ref, exponent, user_exponent, exponent_size) == 0) { - return 2; - } - if (user_copy_to_secure(&page_ref, modulus, user_modulus, 0x100) == 0) { - return 2; - } - - set_exp_mod_result(3); - - /* Hardcode RSA keyslot 0. */ - set_rsa_keyslot(0, modulus, 0x100, exponent, exponent_size); - se_exp_mod(0, input, 0x100, exp_mod_done_handler); - - return 0; -} - -uint32_t user_get_random_bytes(smc_args_t *args) { - uint8_t random_bytes[0x40]; - if (args->X[1] > 0x38) { - return 2; - } - - size_t size = (size_t)args->X[1]; - - flush_dcache_range(random_bytes, random_bytes + size); - se_generate_random(KEYSLOT_SWITCH_RNGKEY, random_bytes, size); - flush_dcache_range(random_bytes, random_bytes + size); - - if (size != 0) { - memcpy(&args->X[1], random_bytes, size); - } - return 0; -} - -uint32_t user_generate_aes_kek(smc_args_t *args) { - uint64_t wrapped_kek[2]; - uint8_t kek_source[0x10]; - uint64_t kek[2]; - uint64_t sealed_kek[2]; - - wrapped_kek[0] = args->X[1]; - wrapped_kek[1] = args->X[2]; - - unsigned int master_key_rev = (unsigned int)args->X[3]; - - if (master_key_rev > 0) { - master_key_rev -= 1; /* GenerateAesKek offsets by one. */ - } - - if (master_key_rev >= MASTERKEY_REVISION_MAX || master_key_rev > mkey_get_revision()) { - return 2; - } - - uint64_t packed_options = args->X[4]; - if (packed_options > 0xFF) { - return 2; - } - - /* Switched the output based on how the system was booted. */ - uint8_t mask_id = (uint8_t)((packed_options >> 1) & 3); - - /* Switches the output based on how it will be used. */ - uint8_t usecase = (uint8_t)((packed_options >> 5) & (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ? 7 : 3)); - - /* Switched the output based on whether it should be console unique. */ - bool is_personalized = (int)(packed_options & 1); - - bool is_recovery_boot = configitem_is_recovery_boot(); - - /* 5.0.0+ Bounds checking. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - if (is_personalized) { - if (master_key_rev >= MASTERKEY_REVISION_MAX || (MASTERKEY_REVISION_300 <= master_key_rev && master_key_rev < MASTERKEY_REVISION_400_410)) { - return 2; - } - if (mask_id > 3 || usecase >= CRYPTOUSECASE_MAX_5X) { - return 2; - } - } else { - if (usecase >= CRYPTOUSECASE_UNK6) { - return 2; - } - if (usecase == CRYPTOUSECASE_UNK5 && mask_id >= 4) { - return 2; - } - } - } - - /* Mask 2 is only allowed when booted from recovery. */ - if (mask_id == 2 && !is_recovery_boot) { - return 2; - } - /* Mask 1 is only allowed when booted normally. */ - if (mask_id == 1 && is_recovery_boot) { - return 2; - } - - /* Masks 0, 3 are allowed all the time. */ - - const uint8_t kek_seeds[7][0x10] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xA2, 0xAB, 0xBF, 0x9C, 0x92, 0x2F, 0xBB, 0xE3, 0x78, 0x79, 0x9B, 0xC0, 0xCC, 0xEA, 0xA5, 0x74}, - {0x57, 0xE2, 0xD9, 0x45, 0xE4, 0x92, 0xF4, 0xFD, 0xC3, 0xF9, 0x86, 0x38, 0x89, 0x78, 0x9F, 0x3C}, - {0xE5, 0x4D, 0x9A, 0x02, 0xF0, 0x4F, 0x5F, 0xA8, 0xAD, 0x76, 0x0A, 0xF6, 0x32, 0x95, 0x59, 0xBB}, - /* 5.0.0+ KEK seeds. */ - {0x59, 0xD9, 0x31, 0xF4, 0xA7, 0x97, 0xB8, 0x14, 0x40, 0xD6, 0xA2, 0x60, 0x2B, 0xED, 0x15, 0x31}, - {0xFD, 0x6A, 0x25, 0xE5, 0xD8, 0x38, 0x7F, 0x91, 0x49, 0xDA, 0xF8, 0x59, 0xA8, 0x28, 0xE6, 0x75}, - {0x89, 0x96, 0x43, 0x9A, 0x7C, 0xD5, 0x59, 0x55, 0x24, 0xD5, 0x24, 0x18, 0xAB, 0x6C, 0x04, 0x61} - }; - const uint8_t kek_masks[4][0x10] = { - {0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9}, - {0x25, 0x03, 0x31, 0xFB, 0x25, 0x26, 0x0B, 0x79, 0x8C, 0x80, 0xD2, 0x69, 0x98, 0xE2, 0x22, 0x77}, - {0x76, 0x14, 0x1D, 0x34, 0x93, 0x2D, 0xE1, 0x84, 0x24, 0x7B, 0x66, 0x65, 0x55, 0x04, 0x65, 0x81}, - {0xAF, 0x3D, 0xB7, 0xF3, 0x08, 0xA2, 0xD8, 0xA2, 0x08, 0xCA, 0x18, 0xA8, 0x69, 0x46, 0xC9, 0x0B} - }; - - /* Create kek source. */ - for (unsigned int i = 0; i < 0x10; i++) { - kek_source[i] = kek_seeds[usecase][i] ^ kek_masks[mask_id][i]; - } - - unsigned int keyslot; - if (is_personalized) { - /* Behavior changed in 4.0.0, and in 5.0.0. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - keyslot = devkey_get_keyslot(master_key_rev); - } else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - if (master_key_rev >= 1) { - keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */ - } else { - keyslot = KEYSLOT_SWITCH_4XOLDDEVICEKEY; /* Old device key, 4.x. */ - } - } else { - keyslot = KEYSLOT_SWITCH_DEVICEKEY; - } - } else { - keyslot = mkey_get_keyslot(master_key_rev); - } - - /* Derive kek. */ - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, keyslot, kek_source, 0x10); - se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, kek, 0x10, wrapped_kek, 0x10); - - - /* Seal kek. */ - seal_key(sealed_kek, 0x10, kek, 0x10, usecase); - - args->X[1] = sealed_kek[0]; - args->X[2] = sealed_kek[1]; - - return 0; -} - -uint32_t user_load_aes_key(smc_args_t *args) { - uint64_t sealed_kek[2]; - uint64_t wrapped_key[2]; - - uint32_t keyslot = (uint32_t)args->X[1]; - if (!is_user_keyslot_valid(keyslot)) { - return 2; - } - - /* Copy keydata */ - sealed_kek[0] = args->X[2]; - sealed_kek[1] = args->X[3]; - wrapped_key[0] = args->X[4]; - wrapped_key[1] = args->X[5]; - - /* Unseal the kek. */ - unseal_key(KEYSLOT_SWITCH_TEMPKEY, sealed_kek, 0x10, CRYPTOUSECASE_AES); - - /* Unwrap the key. */ - decrypt_data_into_keyslot(keyslot, KEYSLOT_SWITCH_TEMPKEY, wrapped_key, 0x10); - return 0; -} - - -void set_crypt_aes_done(bool done) { - g_crypt_aes_done = done; -} - -bool get_crypt_aes_done(void) { - return g_crypt_aes_done; -} - -uint32_t crypt_aes_done_handler(void) { - se_check_for_error(); - - set_crypt_aes_done(true); - - se_trigger_interrupt(); - - return 0; -} - -uint32_t user_crypt_aes(smc_args_t *args) { - uint32_t keyslot = args->X[1] & 3; - uint32_t mode = (args->X[1] >> 4) & 3; - - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - keyslot = args->X[1] & 7; - } - - uint64_t iv_ctr[2]; - iv_ctr[0] = args->X[2]; - iv_ctr[1] = args->X[3]; - - uint32_t in_ll_paddr = (uint32_t)(args->X[4]); - uint32_t out_ll_paddr = (uint32_t)(args->X[5]); - - size_t size = args->X[6]; - if (!is_user_keyslot_valid(keyslot) || size & 0xF) { - return 2; - } - - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - /* Disallow dma lists outside of safe range. */ - if (in_ll_paddr - 0x80000000 >= 0x3FF7F5) { - return 2; - } - if (out_ll_paddr - 0x80000000 >= 0x3FF7F5) { - return 2; - } - } - - set_crypt_aes_done(false); - - uint64_t result = 0; - switch (mode) { - case 0: /* CBC Encryption */ - se_aes_cbc_encrypt_insecure(keyslot, out_ll_paddr, in_ll_paddr, size, iv_ctr, crypt_aes_done_handler); - result = 0; - break; - case 1: /* CBC Decryption */ - se_aes_cbc_decrypt_insecure(keyslot, out_ll_paddr, in_ll_paddr, size, iv_ctr, crypt_aes_done_handler); - result = 0; - break; - case 2: /* CTR "Encryption" */ - se_aes_ctr_crypt_insecure(keyslot, out_ll_paddr, in_ll_paddr, size, iv_ctr, crypt_aes_done_handler); - result = 0; - break; - case 3: - default: - result = 1; - break; - } - - return result; -} - -uint32_t user_generate_specific_aes_key(smc_args_t *args) { - uint64_t wrapped_key[2]; - uint8_t key[0x10]; - unsigned int master_key_rev; - bool should_mask; - - wrapped_key[0] = args->X[1]; - wrapped_key[1] = args->X[2]; - - master_key_rev = (unsigned int)args->X[3]; - if (master_key_rev > 0) { - master_key_rev -= 1; - } - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - master_key_rev = 0; - } - - if (master_key_rev >= MASTERKEY_REVISION_MAX) { - return 2; - } - - if (args->X[4] > 1) { - return 2; - } - should_mask = args->X[4] != 0; - - unsigned int keyslot; - - /* Behavior changed in 5.0.0. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - keyslot = devkey_get_keyslot(master_key_rev); - } else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - if (master_key_rev >= 1) { - keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */ - } else { - keyslot = KEYSLOT_SWITCH_4XOLDDEVICEKEY; /* Old device key, 4.x. */ - } - } else { - keyslot = KEYSLOT_SWITCH_DEVICEKEY; - } - - if (fuse_get_bootrom_patch_version() < 0x7F) { - /* On dev units, use a fixed "all-zeroes" seed. */ - /* Yes, this data really is all-zero in actual TrustZone .rodata. */ - uint8_t dev_specific_aes_key_source[0x10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t dev_specific_aes_key_ctr[0x10] = {0x3C, 0xD5, 0x92, 0xEC, 0x68, 0x31, 0x4A, 0x06, 0xD4, 0x1B, 0x0C, 0xD9, 0xF6, 0x2E, 0xD9, 0xE9}; - uint8_t dev_specific_aes_key_mask[0x10] = {0xAC, 0xCA, 0x9A, 0xCA, 0xFF, 0x2E, 0xB9, 0x22, 0xCC, 0x1F, 0x4F, 0xAD, 0xDD, 0x77, 0x21, 0x1E}; - - flush_dcache_range(key, key + 0x10); - se_aes_ctr_crypt(keyslot, key, 0x10, dev_specific_aes_key_source, 0x10, dev_specific_aes_key_ctr, 0x10); - flush_dcache_range(key, key + 0x10); - - if (should_mask) { - for (unsigned int i = 0; i < 0x10; i++) { - key[i] ^= dev_specific_aes_key_mask[i]; - } - } - } else { - /* On retail, standard kek->key decryption. */ - uint8_t retail_specific_aes_key_source[0x10] = {0xE2, 0xD6, 0xB8, 0x7A, 0x11, 0x9C, 0xB8, 0x80, 0xE8, 0x22, 0x88, 0x8A, 0x46, 0xFB, 0xA1, 0x95}; - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, keyslot, retail_specific_aes_key_source, 0x10); - se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, key, 0x10, wrapped_key, 0x10); - } - - - args->X[1] = read64le(key, 0); - args->X[2] = read64le(key, 8); - return 0; -} - -uint32_t user_compute_cmac(smc_args_t *args) { - uint32_t keyslot = (uint32_t)args->X[1]; - void *user_address = (void *)args->X[2]; - size_t size = (size_t)args->X[3]; - - uint8_t user_data[0x400]; - uint64_t result_cmac[2]; - upage_ref_t page_ref; - - /* Validate keyslot and size. */ - if (!is_user_keyslot_valid(keyslot) || args->X[3] > 0x400) { - return 2; - } - - if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) { - return 2; - } - - flush_dcache_range(user_data, user_data + size); - - se_compute_aes_128_cmac(keyslot, result_cmac, 0x10, user_data, size); - - /* Copy CMAC out. */ - args->X[1] = result_cmac[0]; - args->X[2] = result_cmac[1]; - - return 0; -} - -uint32_t user_load_rsa_oaep_key(smc_args_t *args) { - uint64_t sealed_kek[2]; - uint64_t wrapped_key[2]; - bool is_personalized; - - uint8_t user_data[0x400]; - void *user_address; - size_t size; - upage_ref_t page_ref; - - /* This function no longer exists in 5.x+. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - generic_panic(); - } - - /* Copy keydata */ - sealed_kek[0] = args->X[1]; - sealed_kek[1] = args->X[2]; - if (args->X[3] > 1) { - return 2; - } - is_personalized = args->X[3] != 0; - user_address = (void *)args->X[4]; - size = (size_t)args->X[5]; - wrapped_key[0] = args->X[6]; - wrapped_key[1] = args->X[7]; - - if (is_personalized && size != 0x240) { - return 2; - } - if (!is_personalized && (size != 0x220 || fuse_get_bootrom_patch_version() >= 0x7F)) { - return 2; - } - - if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) { - return 2; - } - - flush_dcache_range(user_data, user_data + size); - - /* Ensure that our private key is 0x100 bytes. */ - if (gcm_decrypt_key(user_data, size, user_data, size, sealed_kek, 0x10, wrapped_key, 0x10, CRYPTOUSECASE_RSAOAEP, is_personalized, NULL) < 0x100) { - return 2; - } - - memcpy(g_imported_exponents[0], user_data, 0x100); - return 0; -} - -uint32_t user_decrypt_rsa_private_key(smc_args_t *args) { - uint64_t sealed_kek[2]; - uint64_t wrapped_key[2]; - bool is_personalized; - - uint8_t user_data[0x400]; - void *user_address; - size_t size; - upage_ref_t page_ref; - - /* This function no longer exists in 5.x+. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - generic_panic(); - } - - /* Copy keydata */ - sealed_kek[0] = args->X[1]; - sealed_kek[1] = args->X[2]; - if (args->X[3] > 1) { - return 2; - } - is_personalized = args->X[3] != 0; - user_address = (void *)args->X[4]; - size = (size_t)args->X[5]; - wrapped_key[0] = args->X[6]; - wrapped_key[1] = args->X[7]; - - if (size > 0x240) { - return 2; - } - - if (is_personalized && size < 0x31) { - return 2; - } - if (!is_personalized && (size < 0x11 || fuse_get_bootrom_patch_version() >= 0x7F)) { - return 2; - } - - if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) { - return 2; - } - - flush_dcache_range(user_data, user_data + size); - - size_t out_size; - - if ((out_size = gcm_decrypt_key(user_data, size, user_data, size, sealed_kek, 0x10, wrapped_key, 0x10, CRYPTOUSECASE_RSAPRIVATE, is_personalized, NULL)) == 0) { - return 2; - } - - if (secure_copy_to_user(&page_ref, user_address, user_data, size) == 0) { - return 2; - } - - args->X[1] = out_size; - return 0; -} - -uint32_t user_load_secure_exp_mod_key(smc_args_t *args) { - uint64_t sealed_kek[2]; - uint64_t wrapped_key[2]; - bool is_personalized; - - uint8_t user_data[0x400]; - void *user_address; - size_t size; - upage_ref_t page_ref; - - /* This function no longer exists in 5.x+. */ - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - generic_panic(); - } - - /* Copy keydata */ - sealed_kek[0] = args->X[1]; - sealed_kek[1] = args->X[2]; - if (args->X[3] > 1) { - return 2; - } - is_personalized = args->X[3] != 0; - user_address = (void *)args->X[4]; - size = (size_t)args->X[5]; - wrapped_key[0] = args->X[6]; - wrapped_key[1] = args->X[7]; - - if (is_personalized && size != 0x130) { - return 2; - } - if (!is_personalized && (size != 0x110 || fuse_get_bootrom_patch_version() >= 0x7F)) { - return 2; - } - - if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) { - return 2; - } - - flush_dcache_range(user_data, user_data + size); - - size_t out_size; - - /* Ensure that our key is non-zero bytes. */ - if ((out_size = gcm_decrypt_key(user_data, size, user_data, size, sealed_kek, 0x10, wrapped_key, 0x10, CRYPTOUSECASE_SECUREEXPMOD, is_personalized, NULL)) == 0) { - return 2; - } - - /* Copy key to global. */ - if (out_size <= 0x100) { - memcpy(g_imported_exponents[1], user_data, out_size); - } else { - memcpy(g_imported_exponents[1], user_data, 0x100); - } - - return 0; -} - -uint32_t user_secure_exp_mod(smc_args_t *args) { - uint8_t modulus[0x100]; - uint8_t input[0x100]; - - upage_ref_t page_ref; - - void *user_input = (void *)args->X[1]; - void *user_modulus = (void *)args->X[2]; - - unsigned int exponent_id = 1; - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - switch (args->X[3]) { - case 0: - exponent_id = 1; - break; - case 1: - exponent_id = 2; - break; - case 2: - exponent_id = 3; - break; - default: - return 2; - } - } - - /* Copy user data into secure memory. */ - if (upage_init(&page_ref, user_input) == 0) { - return 2; - } - if (user_copy_to_secure(&page_ref, input, user_input, 0x100) == 0) { - return 2; - } - if (user_copy_to_secure(&page_ref, modulus, user_modulus, 0x100) == 0) { - return 2; - } - - set_exp_mod_result(3); - - /* Hardcode RSA keyslot 0. */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_10_0_0) { - set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[exponent_id], 0x100); - se_exp_mod(0, input, 0x100, exp_mod_done_handler); - } else if (load_imported_rsa_keypair(0, exponent_id)) { - se_exp_mod(0, input, 0x100, exp_mod_done_handler); - } else { - memcpy(g_rsa_shared_data.storage_exp_mod.user_data, input, 0x100); - g_test_exp_mod_keyslot = 0; - g_test_exp_mod_usecase = exponent_id; - g_test_exp_mod_in_progress = true; - test_rsa_modulus_public(exponent_id, 0, modulus, 0x100, test_exp_mod_done_handler); - } - - return 0; -} - -uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { - uint8_t modulus[0x100]; - uint8_t wrapped_key[0x100]; - - upage_ref_t page_ref; - - void *user_wrapped_key = (void *)args->X[1]; - void *user_modulus = (void *)args->X[2]; - unsigned int option = (unsigned int)args->X[7]; - unsigned int master_key_rev; - unsigned int titlekey_type; - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_6_0_0) { - master_key_rev = option & 0x3F; - titlekey_type = (option >> 6) & 1; - } else { - master_key_rev = option; - titlekey_type = 0; - } - - if(master_key_rev > 0) { - master_key_rev -= 1; - } - - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { - if (master_key_rev >= MASTERKEY_REVISION_MAX) { - return 2; - } - } else { - master_key_rev = 0; - } - - /* Copy user data into secure memory. */ - if (upage_init(&page_ref, user_wrapped_key) == 0) { - return 2; - } - if (user_copy_to_secure(&page_ref, wrapped_key, user_wrapped_key, 0x100) == 0) { - return 2; - } - if (user_copy_to_secure(&page_ref, modulus, user_modulus, 0x100) == 0) { - return 2; - } - - set_exp_mod_result(3); - - /* Expected label_hash occupies args->X[3] to args->X[6]. */ - tkey_set_expected_label_hash(&args->X[3]); - - tkey_set_master_key_rev(master_key_rev); - tkey_set_type(titlekey_type); - - /* Hardcode RSA keyslot 0. */ - set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[0], 0x100); - se_exp_mod(0, wrapped_key, 0x100, exp_mod_done_handler); - - return 0; - -} - -uint32_t user_load_titlekey(smc_args_t *args) { - uint64_t sealed_titlekey[2]; - - uint32_t keyslot = (uint32_t)args->X[1]; - if (!is_user_keyslot_valid(keyslot)) { - return 2; - } - - /* Copy keydata */ - sealed_titlekey[0] = args->X[2]; - sealed_titlekey[1] = args->X[3]; - - /* Unseal the key. */ - unseal_titlekey(keyslot, sealed_titlekey, 0x10); - return 0; - -} - -uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) { - uint64_t aes_wrapped_titlekey[2]; - uint8_t titlekey[0x10]; - uint64_t sealed_titlekey[2]; - - aes_wrapped_titlekey[0] = args->X[1]; - aes_wrapped_titlekey[1] = args->X[2]; - unsigned int master_key_rev = (unsigned int)args->X[3]; - - if (master_key_rev > 0) { - master_key_rev -= 1; - } - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { - if (master_key_rev >= MASTERKEY_REVISION_MAX) { - return 2; - } - } else { - master_key_rev = 0; - } - - tkey_set_master_key_rev(master_key_rev); - tkey_set_type(0); - - tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10); - seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10); - - args->X[1] = sealed_titlekey[0]; - args->X[2] = sealed_titlekey[1]; - - return 0; /* FIXME: what should we return there */ -} - - -uint32_t user_encrypt_rsa_key_for_import(smc_args_t *args) { - uint64_t in_sealed_kek[2]; - uint64_t out_sealed_kek[2]; - uint64_t in_wrapped_key[2]; - uint64_t out_wrapped_key[2]; - uint8_t usecase; - - uint8_t user_data[0x400]; - void *user_address; - void *user_in_kek; - void *user_out_kek; - void *user_in_key; - void *user_out_key; - size_t size; - upage_ref_t page_ref; - - /* Copy keydata */ - user_in_kek = (void *)args->X[1]; - user_out_kek = (void *)args->X[2]; - usecase = args->X[3] & 7; - user_address = (void *)args->X[4]; - size = (size_t)args->X[5]; - user_in_key = (void *)args->X[6]; - user_out_key = (void *)args->X[7]; - - if (usecase > CRYPTOUSECASE_RSAIMPORT) { - return 2; - } - if (usecase == 0) { - if (size < 0x31 || size > 0x240) { - return 2; - } - } else if (size < 0x130 || size > 0x240) { - return 2; - } - - if (upage_init(&page_ref, user_address) == 0 - || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0 - || user_copy_to_secure(&page_ref, in_sealed_kek, user_in_kek, 0x10) == 0 - || user_copy_to_secure(&page_ref, out_sealed_kek, user_out_kek, 0x10) == 0 - || user_copy_to_secure(&page_ref, in_wrapped_key, user_in_key, 0x10) == 0 - || user_copy_to_secure(&page_ref, out_wrapped_key, user_out_key, 0x10) == 0) { - return 2; - } - - flush_dcache_range(user_data, user_data + size); - - size_t out_size; - - uint8_t device_id_high; - - if ((out_size = gcm_decrypt_key(user_data, size, user_data, size, in_sealed_kek, 0x10, in_wrapped_key, 0x10, CRYPTOUSECASE_RSAIMPORT, true, &device_id_high)) == 0) { - return 2; - } - - gcm_encrypt_key(user_data, size, user_data, size - 0x30, out_sealed_kek, 0x10, out_wrapped_key, 0x10, g_rsausecase_to_cryptousecase[usecase], device_id_high); - - if (secure_copy_to_user(&page_ref, user_address, user_data, size) == 0) { - return 2; - } - - return 0; -} - -uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args) { - uint64_t sealed_kek[2]; - uint64_t wrapped_key[2]; - uint8_t usecase; - - uint8_t user_data[0x400]; - void *user_address; - size_t size; - upage_ref_t page_ref; - - /* This function only exists in 5.x+. */ - if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - generic_panic(); - } - - /* Copy keydata */ - sealed_kek[0] = args->X[1]; - sealed_kek[1] = args->X[2]; - usecase = args->X[3] & 7; - user_address = (void *)args->X[4]; - size = (size_t)args->X[5]; - wrapped_key[0] = args->X[6]; - wrapped_key[1] = args->X[7]; - - if (usecase > CRYPTOUSECASE_RSAIMPORT) { - return 2; - } - if (usecase == 0) { - if (size < 0x31 || size > 0x240) { - return 2; - } - } else if (size < 0x130 || size > 0x240) { - return 2; - } - - if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) { - return 2; - } - - flush_dcache_range(user_data, user_data + size); - - size_t out_size; - - if ((out_size = gcm_decrypt_key(user_data, size, user_data, size, sealed_kek, 0x10, wrapped_key, 0x10, g_rsausecase_to_cryptousecase[usecase], true, NULL)) == 0) { - return 2; - } - - unsigned int exponent_id; - bool import_modulus; - - switch (usecase) { - case 0: - if (secure_copy_to_user(&page_ref, user_address, user_data, size) == 0) { - return 2; - } - return 0; - case 1: - exponent_id = 1; - import_modulus = false; - break; - case 2: - exponent_id = 0; - import_modulus = true; - break; - case 3: - exponent_id = 2; - import_modulus = false; - break; - case 4: - exponent_id = 3; - import_modulus = true; - break; - default: - generic_panic(); - } - - /* Modulus import isn't implemented on < 10.0.0. */ - import_modulus &= (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0); - - /* Import the key. */ - import_rsa_exponent(exponent_id, user_data, 0x100); - if (import_modulus) { - import_rsa_modulus(exponent_id, user_data + 0x100, 0x100); - g_is_modulus_verified[exponent_id] = true; - } - return 0; - -} diff --git a/exosphere/src/smc_user.h b/exosphere/src/smc_user.h deleted file mode 100644 index b100f6618..000000000 --- a/exosphere/src/smc_user.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SMC_USER_H -#define EXOSPHERE_SMC_USER_H - -#include "smc_api.h" - -uint32_t user_exp_mod(smc_args_t *args); -uint32_t user_get_random_bytes(smc_args_t *args); -uint32_t user_generate_aes_kek(smc_args_t *args); -uint32_t user_load_aes_key(smc_args_t *args); -uint32_t user_crypt_aes(smc_args_t *args); -uint32_t user_generate_specific_aes_key(smc_args_t *args); -uint32_t user_compute_cmac(smc_args_t *args); -uint32_t user_load_rsa_oaep_key(smc_args_t *args); -uint32_t user_decrypt_rsa_private_key(smc_args_t *args); -uint32_t user_load_secure_exp_mod_key(smc_args_t *args); -uint32_t user_secure_exp_mod(smc_args_t *args); -uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args); -uint32_t user_load_titlekey(smc_args_t *args); -uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args); - -uint32_t user_encrypt_rsa_key_for_import(smc_args_t *args); -uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args); - - -void set_crypt_aes_done(bool done); -bool get_crypt_aes_done(void); - -void set_exp_mod_result(uint32_t result); -uint32_t get_exp_mod_result(void); - -#endif \ No newline at end of file diff --git a/exosphere/src/start.s b/exosphere/src/start.s deleted file mode 100644 index 84eb1c2cd..000000000 --- a/exosphere/src/start.s +++ /dev/null @@ -1,300 +0,0 @@ -/* - * 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 . - */ - -/* For some reason GAS doesn't know about it, even with .cpu cortex-a57 */ -#define cpuactlr_el1 s3_1_c15_c2_0 -#define cpuectlr_el1 s3_1_c15_c2_1 - -.macro RESET_CORE - mov x0, #(1 << 63) - msr cpuactlr_el1, x0 /* disable regional clock gating */ - isb - mov x0, #3 - msr rmr_el3, x0 - isb - dsb sy - /* Nintendo forgot to copy-paste the branch instruction below. */ - 1: - wfi - b 1b -.endm - -.macro ERRATUM_INVALIDATE_BTB_AT_BOOT -/* Nintendo copy-pasted https://github.com/ARM-software/arm-trusted-firmware/blob/master/plat/nvidia/tegra/common/aarch64/tegra_helpers.S#L312 */ - /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - /* The following comments are mine. */ - /* mask all interrupts */ - msr daifset, 0b1111 - - /* - Enable invalidates of branch target buffer, then flush - the entire instruction cache at the local level, and - with the reg change, the branch target buffer, then disable - invalidates of the branch target buffer again. - */ - mrs x0, cpuactlr_el1 - orr x0, x0, #1 - msr cpuactlr_el1, x0 - - dsb sy - isb - ic iallu - dsb sy - isb - - mrs x0, cpuactlr_el1 - bic x0, x0, #1 - msr cpuactlr_el1, x0 - -.rept 7 - nop /* wait long enough for the write to cpuactlr_el1 to have completed */ -.endr - - /* if the OS lock is set, disable it and request a warm reset */ - mrs x0, oslsr_el1 - ands x0, x0, #2 - b.eq 2f - mov x0, xzr - msr oslar_el1, x0 - - RESET_CORE - -.rept 65 - nop /* guard against speculative excecution */ -.endr - - 2: - /* set the OS lock */ - mov x0, #1 - msr oslar_el1, x0 -.endm - -.section .cold_crt0.text.start, "ax", %progbits -.align 6 -.global __start_cold -__start_cold: - ERRATUM_INVALIDATE_BTB_AT_BOOT - - /* - This coldboot crt0 doesn't enter the boot critical section in the official monitor. - However we'll initialize g_boot_critical_section so that it acts like core0 has entered it, - for it to be in .data and for safety. - */ - - /* Relocate the crt0. Nintendo doesn't do it. */ - ldr x0, =__cold_crt0_start__ - adr x1, __start_cold - ldr x2, =__cold_crt0_end__ - cmp x0, x1 - beq _post_cold_crt0_reloc - 1: - ldp x3, x4, [x1], #0x10 - stp x3, x4, [x0], #0x10 - cmp x0, x2 - blo 1b - - adr x19, __start_cold - adr x20, g_coldboot_crt0_relocation_list - sub x20, x20, x19 - ldr x16, =_post_cold_crt0_reloc - br x16 - -_post_cold_crt0_reloc: - /* Setup stack for coldboot crt0. */ - msr spsel, #0 - bl get_coldboot_crt0_temp_stack_address - mov sp, x0 - mov fp, #0 - bl get_coldboot_crt0_stack_address - mov sp, x0 - mov fp, #0 - - /* Relocate Exosphere image to free DRAM, clearing the image in IRAM. */ - ldr x0, =0x80010000 - add x20, x20, x0 - ldr x2, =__loaded_end_lma__ - ldr x3, =__glob_origin__ - sub x21, x2, x3 - mov x1, x19 - mov x2, x21 - add x2, x2, x0 - 2: - ldp x3, x4, [x1] - stp x3, x4, [x0], #0x10 - stp xzr, xzr, [x1], #0x10 - cmp x0, x2 - blo 2b - - /* X0 = TZ-in-DRAM, X1 = relocation-list-in-DRAM. */ - mov x0, x20 - ldr x1, =0x80010000 - /* Set size in coldboot relocation list. */ - str x21, [x0, #0x8] - - bl coldboot_init - - ldr x16, =__jump_to_main_cold - br x16 - -.section .warm_crt0.text.start, "ax", %progbits -.align 6 -.global __start_warm -__start_warm: - ERRATUM_INVALIDATE_BTB_AT_BOOT - - /* For some reasons, Nintendo uses spsel, #1 around here, causing issues if an exception occurs */ - msr spsel, #0 - - /* Nintendo doesn't use anything like the following two lines, but their critical section algo is borked */ - /* FWIW this function doesn't use a stack atm, with latest GCC, but that might change. */ - bl get_warmboot_crt0_stack_address_critsec_enter - mov sp, x0 - - /* PA(__main_start__) = __warmboot_crt0_start__ + 0x800 (refer to the linker script) */ - ldr x0, =g_boot_critical_section - bl warmboot_crt0_critical_section_enter - - bl get_warmboot_crt0_stack_address - mov sp, x0 - mov fp, #0 - - bl warmboot_init - ldr x16, =__jump_to_main_warm - br x16 - -/* Used by coldboot as well */ -.section .warm_crt0.text.__set_memory_registers, "ax", %progbits -.align 4 -.global __set_memory_registers -.type __set_memory_registers, %function -__set_memory_registers: - msr cpuectlr_el1, x2 - isb - msr scr_el3, x3 - msr ttbr0_el3, x0 - msr tcr_el3, x4 - msr cptr_el3, x5 - msr mair_el3, x6 - msr vbar_el3, x1 - - /* Invalidate the entire TLB on the Inner Shareable domain */ - isb - dsb ish - tlbi alle3is - dsb ish - isb - - msr sctlr_el3, x7 - isb - ret - -.section .text.__jump_to_main_cold, "ax", %progbits -.align 4 -__jump_to_main_cold: - /* This is inspired by Nintendo's code but significantly different */ - bl __set_exception_entry_stack_pointer - /* - Normally Nintendo calls it in crt0, but it's fine to do that here. - Please note that package2.c shouldn't have constructed objects, because we - call __libc_fini_array after load_package2 has been cleared, on EL3 - to EL3 chainload. - */ - bl __libc_init_array - - bl get_pk2ldr_stack_address - mov sp, x0 - - mov x0, x20 - bl load_package2 - - mov w0, #3 /* use core3 stack temporarily */ - bl get_exception_entry_stack_address - mov sp, x0 - bl coldboot_main - /* If we ever return, it's to chainload an EL3 payload */ - bl __libc_fini_array - /* Reset the core (only one is running on coldboot) */ - RESET_CORE - -.section .text.__jump_to_main_warm, "ax", %progbits -__jump_to_main_warm: - /* Nintendo doesn't do that here, causing issues if an exception occurs */ - bl __set_exception_entry_stack_pointer - - mov w0, #0 /* use core0,1,2 stack bottom + 0x800 (VA of warmboot crt0 sp) temporarily */ - bl get_warmboot_main_stack_address - mov sp, x0 - bl warmboot_main - -.section .text.__set_exception_entry_stack, "ax", %progbits -.type __set_exception_entry_stack, %function -.global __set_exception_entry_stack -__set_exception_entry_stack_pointer: - /* If SPSel == 1 on entry, make sure your function doesn't use stack variables! */ - mov x16, lr - mrs x17, spsel - mrs x0, mpidr_el1 - and w0, w0, #3 - bl get_exception_entry_stack_address - msr spsel, #1 - mov sp, x0 - msr spsel, x17 - mov lr, x16 - ret - -.section .text.__jump_to_lower_el, "ax", %progbits -.global __jump_to_lower_el -.type __jump_to_lower_el, %function -__jump_to_lower_el: - /* x0: arg (context ID), x1: entrypoint, w2: spsr */ - mov x19, x0 - mov w2, w2 - - msr elr_el3, x1 - msr spsr_el3, x2 - - bl __set_exception_entry_stack_pointer - mov x0, x19 - - isb - eret - -/* Custom stuff */ -.section .cold_crt0.data.g_coldboot_crt0_relocation_list, "aw", %progbits -.align 3 -.global g_coldboot_crt0_relocation_list -g_coldboot_crt0_relocation_list: - .quad 0, 0 /* __start_cold, to be set & loaded size */ - .quad 1, 5 /* number of sections to relocate/clear before & after mmu init */ - /* Relocations */ - .quad __warmboot_crt0_start__, __warmboot_crt0_end__, __warmboot_crt0_lma__ - .quad __main_start__, __main_bss_start__, __main_lma__ - .quad __pk2ldr_start__, __pk2ldr_bss_start__, __pk2ldr_lma__ - .quad __vectors_start__, __vectors_end__, __vectors_lma__ - /* BSS clears */ - .quad __main_bss_start__, __main_end__, 0 - .quad __pk2ldr_bss_start__, __pk2ldr_end__, 0 - -/* Critical section */ -.section .warm_crt0.data.g_boot_critical_section, "aw", %progbits -.align 2 -.global g_boot_critical_section -g_boot_critical_section: - .word 1 /* Core0 entered, by default. */ diff --git a/exosphere/src/synchronization.h b/exosphere/src/synchronization.h deleted file mode 100644 index 602bbccf7..000000000 --- a/exosphere/src/synchronization.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SYNCHRONIZATION_H -#define EXOSPHERE_SYNCHRONIZATION_H - -#include -#include "utils.h" - -/* Simple atomics driver for Exosphere. */ - -typedef struct { - struct { - uint8_t ticket_number : 7; - uint8_t is_entering : 1; - } customers[4]; -} critical_section_t; - -static inline void __dsb_sy(void) { - __asm__ __volatile__ ("dsb sy" ::: "memory"); -} - -static inline void __dsb_ish(void) { - __asm__ __volatile__ ("dsb ish" ::: "memory"); -} - -static inline void __dmb_sy(void) { - __asm__ __volatile__ ("dmb sy" ::: "memory"); -} - -static inline void __isb(void) { - __asm__ __volatile__ ("isb" ::: "memory"); -} - -static inline void __sev(void) { - __asm__ __volatile__ ("sev"); -} - -static inline void __sevl(void) { - __asm__ __volatile__ ("sevl"); -} - -static inline void __wfe(void) { - __asm__ __volatile__ ("wfe"); -} - -/* Acquire a lock. */ -static inline void lock_acquire(atomic_flag *flag) { - while (atomic_flag_test_and_set_explicit(flag, memory_order_acquire)) { - /* Wait to acquire lock. */ - } -} - -/* Release a lock. */ -static inline void lock_release(atomic_flag *flag) { - atomic_flag_clear_explicit(flag, memory_order_release); -} - -/* Try to acquire a lock. */ -static inline bool lock_try_acquire(atomic_flag *flag) { - return !atomic_flag_test_and_set_explicit(flag, memory_order_acquire); -} - -/* - Enter a critical section, using the Lamport's bakery algorithm. - https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm - - This is invoked on warmboot before the MMU is turned on, therefore - exclusive load/store instructions can't be used. - - Note: Nintendo has tried to implement that algorithm, but it seems that - they didn't understand how it works, and their implementation - is therefore a complete failure: in particular, the "ticket number" is - always the same (core0 will always enter the critical section before all the cores, - and so on...), and thus there can be starvation, etc. - - Nintendo, wtf. -*/ -ALINLINE static inline unsigned int critical_section_enter(volatile critical_section_t *critical_section) { - unsigned int id = get_core_id(); - uint8_t my_ticket_number = 0; - uint8_t tmp; - - critical_section->customers[id].is_entering = 1; - for (unsigned int i = 0; i < 4; i++) { - tmp = critical_section->customers[id].ticket_number; - my_ticket_number = tmp > my_ticket_number ? tmp : my_ticket_number; - } - - critical_section->customers[id].ticket_number = ++my_ticket_number; - critical_section->customers[id].is_entering = 0; - __dsb_sy(); - __sev(); - - for (unsigned int i = 0; i < 4; i++) { - __sevl(); - do { - __wfe(); - } while (critical_section->customers[i].is_entering); - - __sevl(); - do { - __wfe(); - tmp = critical_section->customers[i].ticket_number; - } while (tmp && (tmp < my_ticket_number || (tmp == my_ticket_number && i < id))); - } - - __dmb_sy(); - return id; -} - -/* - Leaves a critical section, using the Lamport's bakery algorithm (see above). - - Note: Nintendo failed even that: they're clearing the entire critical section state - instead of just the counter associated to the current core. - - Nintendo, wtf. -*/ -ALINLINE static inline void critical_section_leave(volatile critical_section_t *critical_section) { - critical_section->customers[get_core_id()].ticket_number = 0; - __dsb_sy(); - __sev(); -} - -#endif diff --git a/exosphere/src/sysctr0.h b/exosphere/src/sysctr0.h deleted file mode 100644 index c8e78568e..000000000 --- a/exosphere/src/sysctr0.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SYSCTR0_H -#define EXOSPHERE_SYSCTR0_H - -#include - -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 SYSCTR0 Registers. */ - -#define SYSCTR0_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SYSCTR0)) - -#define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) - -#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00) -#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04) -#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08) -#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C) -#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) -#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24) -#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0) -#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4) -#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8) -#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC) -#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0) -#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4) -#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8) -#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC) -#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0) -#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4) -#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8) -#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC) - -#endif diff --git a/exosphere/src/sysreg.h b/exosphere/src/sysreg.h deleted file mode 100644 index 760ccc01d..000000000 --- a/exosphere/src/sysreg.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_SYSREG_H -#define EXOSPHERE_SYSREG_H - -#include - -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 System Registers. */ - -#define SYSREG_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SYSREGS)) - -#define SB_BASE (SYSREG_BASE + 0x200) - -#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n) -#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n) - -#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004) - -#define SB_CSR_0 MAKE_SB_REG(0x00) -#define SB_PIROM_START_0 MAKE_SB_REG(0x04) -#define SB_PFCFG_0 MAKE_SB_REG(0x08) -#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C) -#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10) -#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14) -#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18) -#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C) -#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20) -#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24) -#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28) -#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30) -#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34) - -#endif diff --git a/exosphere/src/timers.c b/exosphere/src/timers.c deleted file mode 100644 index b8884ad84..000000000 --- a/exosphere/src/timers.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "timers.h" - -void wait(uint32_t microseconds) { - uint32_t old_time = TIMERUS_CNTR_1US_0; - while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { - /* Spin-lock. */ - } -} - -__attribute__ ((noreturn)) void watchdog_reboot(void) { - unsigned int current_core = get_core_id(); - volatile watchdog_timers_t *wdt = GET_WDT(current_core); - wdt->PATTERN = WDT_REBOOT_PATTERN; - wdt->COMMAND = 2; /* Disable Counter. */ - GET_WDT_REBOOT_CFG_REG(current_core) = 0xC0000000; - wdt->CONFIG = 0x8015 + current_core; /* Full System Reset after Fourth Counter expires, using TIMER(5+core_id). */ - wdt->COMMAND = 1; /* Enable Counter. */ - while (true) { - /* Wait for reboot. */ - } -} \ No newline at end of file diff --git a/exosphere/src/timers.h b/exosphere/src/timers.h deleted file mode 100644 index f98f9f7b5..000000000 --- a/exosphere/src/timers.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_TIMERS_H -#define EXOSPHERE_TIMERS_H - -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 Timers. */ - -static inline uintptr_t get_timers_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_TMRs_WDTs); -} - -static inline uintptr_t get_rtc_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC); -} - -#define TIMERS_BASE (get_timers_base()) -#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) - -#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) -#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14) -#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0) -#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4) - -#define RTC_BASE (get_rtc_base()) -#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) - -#define RTC_SECONDS MAKE_RTC_REG(0x08) -#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C) -#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10) - -typedef struct { - uint32_t CONFIG; - uint32_t STATUS; - uint32_t COMMAND; - uint32_t PATTERN; -} watchdog_timers_t; - -#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) -#define WDT_REBOOT_PATTERN 0xC45A -#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n) - -void wait(uint32_t microseconds); - -static inline uint32_t get_time_s(void) { - return RTC_SECONDS; -} - -static inline uint32_t get_time_ms(void) { - return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10)); -} - -static inline uint32_t get_time_us(void) { - return TIMERUS_CNTR_1US_0; -} - -/** - * Returns the time in microseconds. - */ -static inline uint32_t get_time(void) { - return get_time_us(); -} - -/** - * Returns the number of microseconds that have passed since a given get_time(). - */ -static inline uint32_t get_time_since(uint32_t base) { - return get_time_us() - base; -} - -/** - * Delays for a given number of microseconds. - */ -static inline void udelay(uint32_t usecs) { - uint32_t start = get_time_us(); - while (get_time_us() - start < usecs); -} - -/** - * Delays until a number of usecs have passed since an absolute start time. - */ -static inline void udelay_absolute(uint32_t start, uint32_t usecs) { - while (get_time_us() - start < usecs); -} - -/** - * Delays for a given number of milliseconds. - */ -static inline void mdelay(uint32_t msecs) { - uint32_t start = get_time_ms(); - while (get_time_ms() - start < msecs); -} - -__attribute__ ((noreturn)) void watchdog_reboot(void); -#endif diff --git a/exosphere/src/titlekey.c b/exosphere/src/titlekey.c deleted file mode 100644 index 991123572..000000000 --- a/exosphere/src/titlekey.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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 - -#include "utils.h" -#include "arm.h" -#include "exocfg.h" - -#include "titlekey.h" -#include "masterkey.h" -#include "se.h" - -/* Set the expected db prefix. */ -void tkey_set_expected_label_hash(uint64_t *label_hash) { - for (unsigned int i = 0; i < 4; i++) { - g_rsa_shared_data.unwrap_titlekey.expected_label_hash[i] = label_hash[i]; - } -} - -void tkey_set_master_key_rev(unsigned int master_key_rev) { - if (master_key_rev >= MASTERKEY_REVISION_MAX) { - generic_panic(); - } - g_rsa_shared_data.unwrap_titlekey.master_key_rev = master_key_rev; -} - -static void tkey_validate_type(unsigned int type) { - if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_6_0_0)) { - generic_panic(); - } -} - -void tkey_set_type(unsigned int type) { - tkey_validate_type(type); - g_rsa_shared_data.unwrap_titlekey.type = type; -} - -/* Reference for MGF1 can be found here: https://en.wikipedia.org/wiki/Mask_generation_function#MGF1 */ -void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed, size_t seed_size) { - uint8_t cur_hash[0x20]; - uint8_t hash_buf[0xE4]; - if (seed_size >= 0xE0) { - generic_panic(); - } - - size_t hash_buf_size = seed_size + 4; - if (seed_size != 0) { - memcpy(hash_buf, seed, seed_size); - } - uint32_t round_num = 0; - - uint8_t *p_out = (uint8_t *)masked; - - while (masked_size) { - size_t cur_size = masked_size; - if (cur_size > 0x20) { - cur_size = 0x20; - } - - write32be(hash_buf, seed_size, round_num++); - - flush_dcache_range(hash_buf, hash_buf + hash_buf_size); - se_calculate_sha256(cur_hash, hash_buf, hash_buf_size); - - for (unsigned int i = 0; i < cur_size; i++) { - *p_out ^= cur_hash[i]; - p_out++; - } - - masked_size -= cur_size; - } -} - -size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_size) { - if (src_size != 0x100) { - generic_panic(); - } - - /* RSA Wrapped titlekeys use RSA-OAEP. */ - /* Message is of the form prefix || maskedSalt || maskedDB. */ - /* maskedSalt = salt ^ MGF1(maskedDB) */ - /* maskedDB = DB ^ MGF1(salt) */ - /* Salt is random and not validated in any way. */ - /* DB is of the form label_hash || 00....01 || wrapped_titlekey. */ - /* label_hash is, in practice, a constant in es .rodata. */ - /* I have no idea why Nintendo did this, it should be either nonconstant (in tik) or in tz .rodata. */ - - uint8_t *message = (uint8_t *)src; - - /* Prefix should always be zero. */ - if (*message != 0) { - return 0; - } - - - uint8_t *salt = message + 1; - uint8_t *db = message + 0x21; - - /* This will be passed to smc_unwrap_rsa_oaep_wrapped_titlekey. */ - uint8_t *expected_label_hash = (uint8_t *)(&g_rsa_shared_data.unwrap_titlekey.expected_label_hash[0]); - - /* Unmask the salt. */ - calculate_mgf1_and_xor(salt, 0x20, db, 0xDF); - /* Unmask the DB. */ - calculate_mgf1_and_xor(db, 0xDF, salt, 0x20); - - /* Validate expected salt. */ - for (unsigned int i = 0; i < 0x20; i++) { - if (expected_label_hash[i] != db[i]) { - return 0; - } - } - - /* Don't validate salt from message[1:0x21] at all. */ - - /* Advance pointer to DB, since we've validated the salt prefix. */ - db += 0x20; - - /* DB must be of the form 0000...01 || wrapped_titlekey */ - if (*db != 0) { - return 0; - } - - /* Locate wrapped_titlekey inside DB. */ - size_t wrapped_key_offset_in_db = 0; - while (wrapped_key_offset_in_db < 0xBF) { - if (db[wrapped_key_offset_in_db] == 0) { - wrapped_key_offset_in_db++; - } else if (db[wrapped_key_offset_in_db] == 1) { - wrapped_key_offset_in_db++; - break; - } else { - /* Invalid wrapped titlekey prefix. */ - return 0; - } - } - - /* Validate size... */ - size_t wrapped_titlekey_size = 0xBF - wrapped_key_offset_in_db; - if (wrapped_titlekey_size > dst_size || wrapped_titlekey_size == 0) { - return 0; - } - - /* Extract the wrapped key. */ - memcpy(dst, &db[wrapped_key_offset_in_db], wrapped_titlekey_size); - return wrapped_titlekey_size; -} - -static const uint8_t titlekek_sources[TITLEKEY_TYPE_MAX+1][0x10] = { - {0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B}, - {0x3B, 0x78, 0xF2, 0x61, 0x0F, 0x9D, 0x5A, 0xE2, 0x7B, 0x4E, 0x45, 0xAF, 0xCB, 0x0B, 0x67, 0x4D} -}; - -void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size) { - if (g_rsa_shared_data.unwrap_titlekey.master_key_rev >= MASTERKEY_REVISION_MAX || dst_size != 0x10 || src_size != 0x10) { - generic_panic(); - } - - /* Generate the appropriate titlekek into keyslot 9. */ - unsigned int master_keyslot = mkey_get_keyslot(g_rsa_shared_data.unwrap_titlekey.master_key_rev); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_sources[g_rsa_shared_data.unwrap_titlekey.type], 0x10); - - /* Unwrap the titlekey using the titlekek. */ - se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10); -} diff --git a/exosphere/src/titlekey.h b/exosphere/src/titlekey.h deleted file mode 100644 index 4d33783dc..000000000 --- a/exosphere/src/titlekey.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_TITLEKEY_H -#define EXOSPHERE_TITLEKEY_H - -#include -#include "rsa_common.h" - -#define TITLEKEY_TYPE_MAX 0x1 - -void tkey_set_expected_label_hash(uint64_t *label_hash); -void tkey_set_master_key_rev(unsigned int master_key_rev); -void tkey_set_type(unsigned int type); - -size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_size); - -void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size); - -#endif \ No newline at end of file diff --git a/exosphere/src/uart.c b/exosphere/src/uart.c deleted file mode 100644 index 020dbd583..000000000 --- a/exosphere/src/uart.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * 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 "uart.h" -#include "timers.h" -#include "pinmux.h" - -static inline void uart_wait_cycles(uint32_t baud, uint32_t num) -{ - udelay((num * 1000000 + 16 * baud - 1) / (16 * baud)); -} - -static inline void uart_wait_syms(uint32_t baud, uint32_t num) -{ - udelay((num * 1000000 + baud - 1) / baud); -} - -void uart_config(UartDevice dev) { - volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); - - switch (dev) { - case UART_A: - pinmux->uart1_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - pinmux->uart1_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_UP | PINMUX_SELECT_FUNCTION0); - pinmux->uart1_rts = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0); - break; - case UART_B: - pinmux->uart2_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - pinmux->uart2_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - pinmux->uart2_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0); - pinmux->uart2_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - break; - case UART_C: - pinmux->uart3_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - pinmux->uart3_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - pinmux->uart3_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0); - pinmux->uart3_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0); - break; - case UART_D: - pinmux->uart4_tx = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0); - pinmux->uart4_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0); - pinmux->uart4_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0); - pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0); - break; - case UART_E: - /* Unused. */ - break; - default: break; - } -} - -void uart_init(UartDevice dev, uint32_t baud) { - volatile tegra_uart_t *uart = uart_get_regs(dev); - - /* Wait for idle state. */ - uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE); - - /* Calculate baud rate, round to nearest. */ - uint32_t rate = (8 * baud + 408000000) / (16 * baud); - - /* Setup UART in FIFO mode. */ - uart->UART_IER_DLAB = 0; - uart->UART_MCR = 0; - uart->UART_LCR = (UART_LCR_DLAB | UART_LCR_WD_LENGTH_8); /* Enable DLAB and set word length 8. */ - uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */ - uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */ - uart->UART_LCR &= ~(UART_LCR_DLAB); /* Disable DLAB. */ - uart->UART_SPR; /* Dummy read. */ - uart_wait_syms(baud, 3); /* Wait for 3 symbols at the new baudrate. */ - - /* Enable FIFO with default settings. */ - uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO; - uart->UART_SPR; /* Dummy read as mandated by TRM. */ - uart_wait_cycles(baud, 3); /* Wait for 3 baud cycles, as mandated by TRM (erratum). */ - - /* Flush FIFO. */ - uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE); /* Make sure there's no data being written in TX FIFO (TRM). */ - uart->UART_IIR_FCR |= UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Clear TX and RX FIFOs. */ - uart_wait_cycles(baud, 32); /* Wait for 32 baud cycles (TRM, erratum). */ - /* Wait for idle state (TRM). */ - uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE); -} - -/* This function blocks until the UART device is in the desired state. */ -void uart_wait_idle(UartDevice dev, UartVendorStatus status) { - volatile tegra_uart_t *uart = uart_get_regs(dev); - - if (status & UART_VENDOR_STATE_TX_IDLE) { - while (!(uart->UART_LSR & UART_LSR_TMTY)) { - /* Wait */ - } - } - if (status & UART_VENDOR_STATE_RX_IDLE) { - while (uart->UART_LSR & UART_LSR_RDR) { - /* Wait */ - } - } -} - -void uart_send(UartDevice dev, const void *buf, size_t len) { - volatile tegra_uart_t *uart = uart_get_regs(dev); - - for (size_t i = 0; i < len; i++) { - while (!(uart->UART_LSR & UART_LSR_THRE)) { - /* Wait until it's possible to send data. */ - } - uart->UART_THR_DLAB = *((const uint8_t *)buf + i); - } -} - -void uart_recv(UartDevice dev, void *buf, size_t len) { - volatile tegra_uart_t *uart = uart_get_regs(dev); - - for (size_t i = 0; i < len; i++) { - while (!(uart->UART_LSR & UART_LSR_RDR)) { - /* Wait until it's possible to receive data. */ - } - *((uint8_t *)buf + i) = uart->UART_THR_DLAB; - } -} diff --git a/exosphere/src/uart.h b/exosphere/src/uart.h deleted file mode 100644 index 3dd90f7f2..000000000 --- a/exosphere/src/uart.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * 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 . - */ - -#ifndef EXOSPHERE_UART_H -#define EXOSPHERE_UART_H - -#include -#include "memory_map.h" - -/* Exosphere driver for the Tegra X1 UARTs. */ - -static inline uintptr_t get_uart_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_UART); -} - -#define UART_BASE (get_uart_base()) - -#define BAUD_115200 115200 - -/* UART devices */ -typedef enum { - UART_A = 0, - UART_B = 1, - UART_C = 2, - UART_D = 3, - UART_E = 4, -} UartDevice; - -/* 36.3.12 UART_VENDOR_STATUS_0_0 */ -typedef enum { - UART_VENDOR_STATE_TX_IDLE = 1 << 0, - UART_VENDOR_STATE_RX_IDLE = 1 << 1, - - /* This bit is set to 1 when a read is issued to an empty FIFO and gets cleared on register read (sticky bit until read) - 0 = NO_UNDERRUN - 1 = UNDERRUN - */ - UART_VENDOR_STATE_RX_UNDERRUN = 1 << 2, - - /* This bit is set to 1 when write data is issued to the TX FIFO when it is already full and gets cleared on register read (sticky bit until read) - 0 = NO_OVERRUN - 1 = OVERRUN - */ - UART_VENDOR_STATE_TX_OVERRUN = 1 << 3, - - UART_VENDOR_STATE_RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ - UART_VENDOR_STATE_TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ -} UartVendorStatus; - -/* 36.3.6 UART_LSR_0 */ -typedef enum { - UART_LSR_RDR = 1 << 0, /* Receiver Data Ready */ - UART_LSR_OVRF = 1 << 1, /* Receiver Overrun Error */ - UART_LSR_PERR = 1 << 2, /* Parity Error */ - UART_LSR_FERR = 1 << 3, /* Framing Error */ - UART_LSR_BRK = 1 << 4, /* BREAK condition detected on line */ - UART_LSR_THRE = 1 << 5, /* Transmit Holding Register is Empty -- OK to write data */ - UART_LSR_TMTY = 1 << 6, /* Transmit Shift Register empty status */ - UART_LSR_FIFOE = 1 << 7, /* Receive FIFO Error */ - UART_LSR_TX_FIFO_FULL = 1 << 8, /* Transmitter FIFO full status */ - UART_LSR_RX_FIFO_EMPTY = 1 << 9, /* Receiver FIFO empty status */ -} UartLineStatus; - -/* 36.3.4 UART_LCR_0 */ -typedef enum { - UART_LCR_WD_LENGTH_5 = 0, /* word length 5 */ - UART_LCR_WD_LENGTH_6 = 1, /* word length 6 */ - UART_LCR_WD_LENGTH_7 = 2, /* word length 7 */ - UART_LCR_WD_LENGTH_8 = 3, /* word length 8 */ - - /* STOP: - 0 = Transmit 1 stop bit - 1 = Transmit 2 stop bits (receiver always checks for 1 stop bit) - */ - UART_LCR_STOP = 1 << 2, - UART_LCR_PAR = 1 << 3, /* Parity enabled */ - UART_LCR_EVEN = 1 << 4, /* Even parity format. There will always be an even number of 1s in the binary representation (PAR = 1) */ - UART_LCR_SET_P = 1 << 5, /* Set (force) parity to value in LCR[4] */ - UART_LCR_SET_B = 1 << 6, /* Set BREAK condition -- Transmitter sends all zeroes to indicate BREAK */ - UART_LCR_DLAB = 1 << 7, /* Divisor Latch Access Bit (set to allow programming of the DLH, DLM Divisors) */ -} UartLineControl; - -/* 36.3.3 UART_IIR_FCR_0 */ -typedef enum { - UART_FCR_FCR_EN_FIFO = 1 << 0, /* Enable the transmit and receive FIFOs. This bit should be enabled */ - UART_FCR_RX_CLR = 1 << 1, /* Clears the contents of the receive FIFO and resets its counter logic to 0 (the receive shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ - UART_FCR_TX_CLR = 1 << 2, /* Clears the contents of the transmit FIFO and resets its counter logic to 0 (the transmit shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ - - /* DMA: - 0 = DMA_MODE_0 - 1 = DMA_MODE_1 - */ - UART_FCR_DMA = 1 << 3, - - /* TX_TRIG - 0 = FIFO_COUNT_GREATER_16 - 1 = FIFO_COUNT_GREATER_8 - 2 = FIFO_COUNT_GREATER_4 - 3 = FIFO_COUNT_GREATER_1 - */ - UART_FCR_TX_TRIG = 3 << 4, - UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_16 = 0 << 4, - UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_8 = 1 << 4, - UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_4 = 2 << 4, - UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_1 = 3 << 4, - - /* RX_TRIG - 0 = FIFO_COUNT_GREATER_1 - 1 = FIFO_COUNT_GREATER_4 - 2 = FIFO_COUNT_GREATER_8 - 3 = FIFO_COUNT_GREATER_16 - */ - UART_FCR_RX_TRIG = 3 << 6, - UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_1 = 0 << 6, - UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_4 = 1 << 6, - UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_8 = 2 << 6, - UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_16 = 3 << 6, -} UartFifoControl; - -/* 36.3.3 UART_IIR_FCR_0 */ -typedef enum { - UART_IIR_IS_STA = 1 << 0, /* Interrupt Pending if ZERO */ - UART_IIR_IS_PRI0 = 1 << 1, /* Encoded Interrupt ID Refer to IIR[3:0] table [36.3.3] */ - UART_IIR_IS_PRI1 = 1 << 2, /* Encoded Interrupt ID Refer to IIR[3:0] table */ - UART_IIR_IS_PRI2 = 1 << 3, /* Encoded Interrupt ID Refer to IIR[3:0] table */ - - /* FIFO Mode Status - 0 = 16450 mode (no FIFO) - 1 = 16550 mode (FIFO) - */ - UART_IIR_EN_FIFO = 3 << 6, - UART_IIR_MODE_16450 = 0 << 6, - UART_IIR_MODE_16550 = 1 << 6, -} UartInterruptIdentification; - -typedef struct { - uint32_t UART_THR_DLAB; - uint32_t UART_IER_DLAB; - uint32_t UART_IIR_FCR; - uint32_t UART_LCR; - uint32_t UART_MCR; - uint32_t UART_LSR; - uint32_t UART_MSR; - uint32_t UART_SPR; - uint32_t UART_IRDA_CSR; - uint32_t UART_RX_FIFO_CFG; - uint32_t UART_MIE; - uint32_t UART_VENDOR_STATUS; - uint8_t _0x30[0x0C]; - uint32_t UART_ASR; -} tegra_uart_t; - -void uart_config(UartDevice dev); -void uart_init(UartDevice dev, uint32_t baud); -void uart_wait_idle(UartDevice dev, UartVendorStatus status); -void uart_send(UartDevice dev, const void *buf, size_t len); -void uart_recv(UartDevice dev, void *buf, size_t len); - -static inline volatile tegra_uart_t *uart_get_regs(UartDevice dev) { - static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400}; - return (volatile tegra_uart_t *)(UART_BASE + offsets[dev]); -} - -#endif diff --git a/exosphere/src/userpage.c b/exosphere/src/userpage.c deleted file mode 100644 index c34e5fdb7..000000000 --- a/exosphere/src/userpage.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 "utils.h" -#include "userpage.h" -#include "memory_map.h" -#include "arm.h" - -static uintptr_t g_user_page_user_address = 0ull; - -static inline uintptr_t get_page_for_address(const void *address) { - return ((uintptr_t)(address)) & ~0xFFFULL; -} - -/* Create a user page reference for the desired address. */ -/* Returns 1 on success, 0 on failure. */ -bool upage_init(upage_ref_t *upage, void *user_address) { - upage->user_address = get_page_for_address(user_address); - upage->secure_monitor_address = 0ull; - - if (g_user_page_user_address != 0ull) { - /* Different physical address indicate SPL was rebooted, or another process got access to svcCallSecureMonitor. Panic. */ - if (g_user_page_user_address != upage->user_address) { - generic_panic(); - } - upage->secure_monitor_address = USER_PAGE_SECURE_MONITOR_ADDR; - } else { - /* Validate SPL's physically random address (must be in DRAM (supports up to 6GB, retail console have 4GB) and page-aligned). */ - if ((upage->user_address - 0x80000000ull) < (6ull << 30) && ((uintptr_t)user_address & 0xFFF) == 0) { - static const uint64_t userpage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_NORMAL; - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - g_user_page_user_address = upage->user_address; - mmu_map_page(mmu_l3_tbl, USER_PAGE_SECURE_MONITOR_ADDR, upage->user_address, userpage_attributes); - tlb_invalidate_page_inner_shareable((void *)USER_PAGE_SECURE_MONITOR_ADDR); - upage->secure_monitor_address = USER_PAGE_SECURE_MONITOR_ADDR; - } else { - generic_panic(); - } - } - - return upage->secure_monitor_address != 0ull; -} - -bool user_copy_to_secure(upage_ref_t *upage, void *secure_dst, const void *user_src, size_t size) { - /* Fail if the page doesn't match. */ - if (get_page_for_address(user_src) != upage->user_address) { - return false; - } - - /* Fail if we go past the page boundary. */ - if (size != 0 && get_page_for_address(user_src + size - 1) != upage->user_address) { - return false; - } - - const void *secure_src = (const void *)(upage->secure_monitor_address + ((uintptr_t)user_src - upage->user_address)); - if (size != 0) { - memcpy(secure_dst, secure_src, size); - } - return true; -} - -bool secure_copy_to_user(upage_ref_t *upage, void *user_dst, const void *secure_src, size_t size) { - /* Fail if the page doesn't match. */ - if (get_page_for_address(user_dst) != upage->user_address) { - return false; - } - - /* Fail if we go past the page boundary. */ - if (size != 0 && get_page_for_address(user_dst + size - 1) != upage->user_address) { - return false; - } - - void *secure_dst = (void *)(upage->secure_monitor_address + ((uintptr_t)user_dst - upage->user_address)); - if(size != 0) { - memcpy(secure_dst, secure_src, size); - } - return true; -} diff --git a/exosphere/src/userpage.h b/exosphere/src/userpage.h deleted file mode 100644 index 076d85844..000000000 --- a/exosphere/src/userpage.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_USERPAGE_H -#define EXOSPHERE_USERPAGE_H - -#include "utils.h" -#include "memory_map.h" - -static inline uintptr_t get_user_page_secure_monitor_addr(void) { - return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_USERPAGE); -} - -#define USER_PAGE_SECURE_MONITOR_ADDR (get_user_page_secure_monitor_addr()) - -typedef struct { - uintptr_t user_address; - uintptr_t secure_monitor_address; -} upage_ref_t; - -bool upage_init(upage_ref_t *user_page, void *user_address); - -bool user_copy_to_secure(upage_ref_t *user_page, void *secure_dst, const void *user_src, size_t size); -bool secure_copy_to_user(upage_ref_t *user_page, void *user_dst, const void *secure_src, size_t size); - -#endif diff --git a/exosphere/src/utils.c b/exosphere/src/utils.c deleted file mode 100644 index 938f80d0e..000000000 --- a/exosphere/src/utils.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 -#include "utils.h" -#include "se.h" -#include "fuse.h" -#include "pmc.h" -#include "timers.h" - -#define SAVE_SYSREG64(reg, ofs) do { __asm__ __volatile__ ("mrs %0, " #reg : "=r"(temp_reg) :: "memory"); MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + ofs) = (uint32_t)((temp_reg >> 0) & 0xFFFFFFFFULL); MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + ofs + 4) = (uint32_t)((temp_reg >> 32) & 0xFFFFFFFFULL); } while(false) - -__attribute__ ((noreturn)) void panic(uint32_t code) { - /* Set Panic Code for NX_BOOTLOADER. */ - if (APBDEV_PMC_SCRATCH200_0 == 0) { - APBDEV_PMC_SCRATCH200_0 = code; - } - - /* // Uncomment for Debugging. - uint64_t temp_reg; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM)) = APBDEV_PMC_SCRATCH200_0; - SAVE_SYSREG64(ESR_EL3, 0x10); - SAVE_SYSREG64(ELR_EL3, 0x18); - SAVE_SYSREG64(FAR_EL3, 0x20); - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; */ - - - /* TODO: Custom Panic Driver, which displays to screen without rebooting. */ - /* For now, just use NX BOOTLOADER's panic. */ - fuse_disable_programming(); - APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */ - // while (1) { } - watchdog_reboot(); -} - -__attribute__ ((noreturn)) void generic_panic(void) { - /* //Uncomment for Debugging. - uint64_t temp_reg; - do { __asm__ __volatile__ ("mov %0, LR" : "=r"(temp_reg) :: "memory"); } while (false); - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + 0x28) = (uint32_t)((temp_reg >> 0) & 0xFFFFFFFFULL); - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + 0x28 + 4) = (uint32_t)((temp_reg >> 32) & 0xFFFFFFFFULL); - do { __asm__ __volatile__ ("mov %0, SP" : "=r"(temp_reg) :: "memory"); } while (false); - for (unsigned int i = 0; i < 0x80; i += 4) { - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + 0x40 + i) = *((volatile uint32_t *)(temp_reg + i)); - } */ - panic(0xFF000006); -} - -__attribute__ ((noreturn)) void panic_predefined(uint32_t which) { - static const uint32_t codes[0x10] = {COLOR_0, COLOR_1, COLOR_2, COLOR_3, COLOR_4, COLOR_5, COLOR_6, COLOR_7, COLOR_8, COLOR_9, COLOR_A, COLOR_B, COLOR_C, COLOR_D, COLOR_E, COLOR_F}; - panic(codes[which & 0xF]); -} - -__attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be) -{ - if(as <= bs && bs < ae) - return true; - if(bs <= as && as < be) - return true; - return false; -} - -uintptr_t get_iram_address_for_debug(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM); -} diff --git a/exosphere/src/utils.h b/exosphere/src/utils.h deleted file mode 100644 index f95fd1e65..000000000 --- a/exosphere/src/utils.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 . - */ - -#ifndef EXOSPHERE_UTILS_H -#define EXOSPHERE_UTILS_H - -#include -#include -#include - -#include "panic_color.h" - -#define BIT(n) (1u << (n)) -#define BITL(n) (1ull << (n)) -#define MASK(n) (BIT(n) - 1) -#define MASKL(n) (BITL(n) - 1) -#define MASK2(a,b) (MASK(a) & ~MASK(b)) -#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) - -#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) - -#define ALIGN(m) __attribute__((aligned(m))) -#define PACKED __attribute__((packed)) - -#define ALINLINE __attribute__((always_inline)) - -#define SET_SYSREG(reg, val) do { temp_reg = (val); __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false) - -/* Custom stuff below */ - -/* For coldboot */ -typedef struct { - uint8_t *vma; - uint8_t *end_vma; - uintptr_t lma; -} coldboot_crt0_reloc_t; - -typedef struct { - uintptr_t reloc_base; - size_t loaded_bin_size; - size_t nb_relocs_pre_mmu_init; /* first is always warmboot_crt0 */ - size_t nb_relocs_post_mmu_init; /* first is always main segment excl. .bss */ - coldboot_crt0_reloc_t relocs[]; -} coldboot_crt0_reloc_list_t; - -__attribute__ ((noreturn)) void panic(uint32_t code); -__attribute__ ((noreturn)) void generic_panic(void); -__attribute__ ((noreturn)) void panic_predefined(uint32_t which); -bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be); - -uintptr_t get_iram_address_for_debug(void); - -static inline uintptr_t get_physical_address(const void *vaddr) { - uintptr_t PAR; - __asm__ __volatile__ ("at s1e3r, %0" :: "r"(vaddr)); - __asm__ __volatile__ ("mrs %0, par_el1" : "=r"(PAR)); - return (PAR & 1) ? 0ull : (PAR & MASK2L(40, 12)) | ((uintptr_t)vaddr & MASKL(12)); -} - -static inline uintptr_t get_physical_address_el0(const uintptr_t el0_vaddr) { - uintptr_t PAR; - __asm__ __volatile__ ("at s1e0r, %0" :: "r"(el0_vaddr)); - __asm__ __volatile__ ("mrs %0, par_el1" : "=r"(PAR)); - return (PAR & 1) ? 0ull : (PAR & MASK2L(40, 12)) | ((uintptr_t)el0_vaddr & MASKL(12)); -} - -static inline uint32_t read32le(const volatile void *dword, size_t offset) { - return *(uint32_t *)((uintptr_t)dword + offset); -} - -static inline uint32_t read32be(const volatile void *dword, size_t offset) { - return __builtin_bswap32(read32le(dword, offset)); -} - -static inline uint64_t read64le(const volatile void *qword, size_t offset) { - return *(uint64_t *)((uintptr_t)qword + offset); -} - -static inline uint64_t read64be(const volatile void *qword, size_t offset) { - return __builtin_bswap64(read64le(qword, offset)); -} - -static inline void write32le(volatile void *dword, size_t offset, uint32_t value) { - *(uint32_t *)((uintptr_t)dword + offset) = value; -} - -static inline void write32be(volatile void *dword, size_t offset, uint32_t value) { - write32le(dword, offset, __builtin_bswap32(value)); -} - -static inline void write64le(volatile void *qword, size_t offset, uint64_t value) { - *(uint64_t *)((uintptr_t)qword + offset) = value; -} - -static inline void write64be(volatile void *qword, size_t offset, uint64_t value) { - write64le(qword, offset, __builtin_bswap64(value)); -} - -static inline unsigned int get_core_id(void) { - uint64_t core_id; - __asm__ __volatile__ ("mrs %0, mpidr_el1" : "=r"(core_id)); - return (unsigned int)core_id & 3; -} - -static inline uint64_t get_debug_authentication_status(void) { - uint64_t debug_auth; - __asm__ __volatile__ ("mrs %0, dbgauthstatus_el1" : "=r"(debug_auth)); - return debug_auth; -} - -static inline uint32_t get_spsr(void) { - uint32_t spsr; - __asm__ __volatile__ ("mrs %0, spsr_el3" : "=r"(spsr)); - return spsr; -} - -static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) { - return __builtin_add_overflow_p(a, b, (uint32_t)0); -} - -#endif diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c deleted file mode 100644 index b7cce98fc..000000000 --- a/exosphere/src/warmboot_init.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * 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 "utils.h" -#include "memory_map.h" -#include "mc.h" -#include "arm.h" -#include "synchronization.h" -#include "exocfg.h" -#include "pmc.h" - -#undef MC_BASE -#define MC_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC)) - -#define WARMBOOT_GET_TZRAM_SEGMENT_PA(x) ((g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) \ - ? TZRAM_GET_SEGMENT_PA(x) : TZRAM_GET_SEGMENT_5X_PA(x)) - -/* start.s */ -void __set_memory_registers(uintptr_t ttbr0, uintptr_t vbar, uint64_t cpuectlr, uint32_t scr, - uint32_t tcr, uint32_t cptr, uint64_t mair, uint32_t sctlr); - -unsigned int g_exosphere_target_firmware_for_init = 0; - -uintptr_t get_warmboot_crt0_stack_address(void) { - return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE012_STACK) + 0x800; -} - -uintptr_t get_warmboot_crt0_stack_address_critsec_enter(void) { - unsigned int core_id = get_core_id(); - - if (core_id == 3) { - return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000; - } else { - return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x80 * (core_id + 1); - } -} - -void warmboot_crt0_critical_section_enter(volatile critical_section_t *critical_section) { - critical_section_enter(critical_section); -} - -void init_dma_controllers(unsigned int target_firmware) { - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - /* Set some unknown registers in HOST1X. */ - MAKE_REG32(0x500038F8) &= 0xFFFFFFFE; - MAKE_REG32(0x50003300) = 0; - - /* AHB_MASTER_SWID_0 - Enable SWID[0] for all bits. */ - MAKE_REG32(0x6000C018) = 0xFFFFFFFF; - - /* AHB_MASTER_SWID_1 */ - MAKE_REG32(0x6000C038) = 0x0; - - /* MSELECT_CONFIG_0 |= WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */ - MAKE_REG32(0x50060000) = (MAKE_REG32(0x50060000) & 0xC4FFFFFF) | 0x38000000; - - /* AHB_ARBITRATION_DISABLE_0 - Disables USB, USB2, and AHB-DMA from arbitration */ - MAKE_REG32(0x6000C004) = 0x40060; - - /* AHB_ARBITRATION_PRIORITY_CTRL_0 - Select high prio group with prio 7 */ - MAKE_REG32(0x6000C008) = 0xE0000001; - - /* AHB_GIZMO_TZRAM_0 |= DONT_SPLIT_AHB_WR */ - MAKE_REG32(0x6000C054) = 0x80; - } else { - /* SYSCTR0_CNTCR_0 = ENABLE | HALT_ON_DEBUG (write-once init) */ - MAKE_REG32(0x700F0000) = 3; - - /* Set some unknown registers in HOST1X. */ - MAKE_REG32(0x500038F8) &= 0xFFFFFFFE; - MAKE_REG32(0x50003300) = 0; - - /* AHB_MASTER_SWID_0 */ - MAKE_REG32(0x6000C018) = 0; - - /* AHB_MASTER_SWID_1 - Makes USB1/USB2 use SWID[1] */ - MAKE_REG32(0x6000C038) = 0x40040; - - /* APBDMA_CHANNEL_SWID_0 = ~0 (SWID = 1 for all APB-DMA channels) */ - MAKE_REG32(0x6002003C) = 0xFFFFFFFF; - - /* APBDMA_CHANNEL_SWID1_0 = 0 (See above) */ - MAKE_REG32(0x60020054) = 0; - - /* APBDMA_SECURITY_REG_0 = 0 (All APB-DMA channels non-secure) */ - MAKE_REG32(0x60020038) = 0; - - /* MSELECT_CONFIG_0 |= WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */ - MAKE_REG32(0x50060000) |= (MAKE_REG32(0x50060000) & 0xC4FFFFFF) | 0x38000000; - - /* AHB_ARBITRATION_PRIORITY_CTRL_0 - Select high prio group with prio 7 */ - MAKE_REG32(0x6000C008) = 0xE0000001; - - /* AHB_GIZMO_TZRAM_0 |= DONT_SPLIT_AHB_WR */ - MAKE_REG32(0x6000C054) = 0x80; - } -} - -void _set_memory_registers_enable_mmu(const uintptr_t ttbr0) { - static const uintptr_t vbar = TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800; - /* - - Non-cacheable load forwarding enabled - - Disable load-pass DMB. - - NOTE: This and this alone is done via inline asm, due to register argument limits. - */ - - static const uint64_t cpuactlr = 0x800000001000000ull; - __asm__ __volatile__("msr s3_1_c15_c2_0, %0" :: "r"(cpuactlr) : "memory", "cc"); - - /* - - Disable table walk descriptor access prefetch. - - L2 instruction fetch prefetch distance = 3 (reset value) - - L2 load/store data prefetch distance = 8 (reset value) - - Enable the processor to receive instruction cache and TLB maintenance operations broadcast from other processors in the cluster - */ - static const uint64_t cpuectlr = 0x1B00000040ull; - - /* - - The next lower level is Aarch64 - - Secure instruction fetch (when the PE is in Secure state, this bit disables instruction fetch from Non-secure memory) - - External Abort/SError taken to EL3 - - FIQ taken to EL3 - - NS (EL0 and EL1 are nonsecure) - */ - static const uint32_t scr = 0x63D; - - /* - - PA size: 36-bit (64 GB) - - Granule size: 4KB - - Shareability attribute for memory associated with translation table walks using TTBR0_EL3: Inner Shareable - - Outer cacheability attribute for memory associated with translation table walks using TTBR0_EL3: Normal memory, Outer Write-Back Read-Allocate Write-Allocate Cacheable - - Inner cacheability attribute for memory associated with translation table walks using TTBR0_EL3: Normal memory, Inner Write-Back Read-Allocate Write-Allocate Cacheable - - T0SZ = 31 (33-bit address space) - */ - static const uint32_t tcr = TCR_EL3_RSVD | TCR_PS(1) | TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA | TCR_T0SZ(33); - - /* Nothing trapped */ - static const uint32_t cptr = 0; - - /* - - Attribute 0: Normal memory, Inner and Outer Write-Back Read-Allocate Write-Allocate Non-transient - - Attribute 1: Device-nGnRE memory - - Other attributes: Device-nGnRnE memory - */ - static const uint64_t mair = 0x4FFull; - - /* - - Cacheability control, for EL3 instruction accesses DISABLED - (- SP Alignment check bit NOT SET) - - Cacheability control, for EL3 data accesses DISABLED (normal memory accesses from EL3 are cacheable) - (- Alignement check bit NOT SET) - - MMU enabled for EL3 stage 1 address translation - */ - static const uint32_t sctlr = 0x30C51835ull; - - __set_memory_registers(ttbr0, vbar, cpuectlr, scr, tcr, cptr, mair, sctlr); -} - -void set_memory_registers_enable_mmu_1x_ttbr0(void) { - static const uintptr_t ttbr0 = TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64; - _set_memory_registers_enable_mmu(ttbr0); -} - -void set_memory_registers_enable_mmu_5x_ttbr0(void) { - static const uintptr_t ttbr0 = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64; - _set_memory_registers_enable_mmu(ttbr0); -} - -#if 0 /* Since we decided not to identity-unmap TZRAM */ -static void identity_remap_tzram(void) { - /* See also: configure_ttbls (in coldboot_init.c). */ - uintptr_t *mmu_l1_tbl = (uintptr_t *)(WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - uintptr_t *mmu_l2_tbl = (uintptr_t *)WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); - uintptr_t *mmu_l3_tbl = (uintptr_t *)WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - - mmu_map_table(1, mmu_l1_tbl, 0x40000000, mmu_l2_tbl, 0); - mmu_map_table(2, mmu_l2_tbl, 0x7C000000, mmu_l3_tbl, 0); - - identity_map_mapping(mmu_l1_tbl, mmu_l3_tbl, IDENTITY_GET_MAPPING_ADDRESS(IDENTITY_MAPPING_TZRAM), - IDENTITY_GET_MAPPING_SIZE(IDENTITY_MAPPING_TZRAM), IDENTITY_GET_MAPPING_ATTRIBS(IDENTITY_MAPPING_TZRAM), - IDENTITY_IS_MAPPING_BLOCK_RANGE(IDENTITY_MAPPING_TZRAM)); -} -#endif - -void warmboot_init(void) { - /* - From https://events.static.linuxfound.org/sites/events/files/slides/slides_17.pdf : - Caches may write back dirty lines at any time: - - To make space for new allocations - - Even if MMU is off - - Even if Cacheable accesses are disabled (caches are never 'off') - */ - flush_dcache_all(); - invalidate_icache_all(); - - /* On warmboot (not cpu_on) only */ - if (VIRT_MC_SECURITY_CFG3 == 0) { - init_dma_controllers(g_exosphere_target_firmware_for_init); - } - - /*identity_remap_tzram();*/ - /* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */ - if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_5_0_0) { - set_memory_registers_enable_mmu_1x_ttbr0(); - } else { - set_memory_registers_enable_mmu_5x_ttbr0(); - } -} diff --git a/exosphere/src/warmboot_main.c b/exosphere/src/warmboot_main.c deleted file mode 100644 index d8ee82e91..000000000 --- a/exosphere/src/warmboot_main.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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 "utils.h" -#include "mmu.h" -#include "memory_map.h" -#include "cpu_context.h" -#include "bootconfig.h" -#include "configitem.h" -#include "masterkey.h" -#include "bootup.h" -#include "smc_api.h" -#include "exocfg.h" -#include "se.h" -#include "mc.h" -#include "car.h" -#include "i2c.h" -#include "misc.h" -#include "uart.h" -#include "interrupt.h" -#include "pmc.h" - -uintptr_t get_warmboot_main_stack_address(void) { - return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x780; -} - -static void warmboot_configure_hiz_mode(void) { - /* Enable input to I2C1 */ - i2c_config(I2C_1); - - clkrst_reboot(CARDEVICE_I2C1); - i2c_init(0); - i2c_clear_ti_charger_bit_7(); - clkrst_disable(CARDEVICE_I2C1); -} - -void __attribute__((noreturn)) warmboot_main(void) { - /* - This function and its callers are reached in either of the following events, under normal conditions: - - warmboot (core 3) - - cpu_on - */ - - if (is_core_active(get_core_id())) { - panic(0xF7F00009); /* invalid CPU context */ - } - - /* IRAM C+D identity mapping has actually been removed on coldboot but we don't really care */ - /* For our crt0 to work, this doesn't actually unmap TZRAM */ - identity_unmap_iram_cd_tzram(); - - /* On warmboot (not cpu_on) only */ - if (VIRT_MC_SECURITY_CFG3 == 0) { - /* N only does this on dev units, but we will do it unconditionally. */ - { - uart_config(UART_A); - clkrst_reboot(CARDEVICE_UARTA); - uart_init(UART_A, 115200); - } - - if (!configitem_is_retail()) { - uart_send(UART_A, "OHAYO", 6); - uart_wait_idle(UART_A, UART_VENDOR_STATE_TX_IDLE); - } - - /* Sanity check the Security Engine. */ - se_verify_flags_cleared(); - - /* Initialize interrupts. */ - intr_initialize_gic_nonsecure(); - - bootup_misc_mmio(); - - /* Make PMC (2.x+), MC (4.x+) registers secure-only */ - secure_additional_devices(); - - if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) || - ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) && configitem_get_hardware_type() == 0) || - (configitem_is_hiz_mode_enabled())) { - warmboot_configure_hiz_mode(); - } - - clear_user_smc_in_progress(); - - if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - setup_4x_mmio(); - } - } - - setup_current_core_state(); - - /* Update SCR_EL3 depending on value in Bootconfig. */ - set_extabt_serror_taken_to_el3(bootconfig_take_extabt_serror_to_el3()); - core_jump_to_lower_el(); -}