exo2: Initial work on the exosphere rewrite.

exo2: Implement uncompressor stub and boot code up to Main().

exo2: implement some more init (uart/gic)

exo2: implement more of init

exo2: improve reg api, add keyslot flag setters

exo2: implement se aes decryption/enc

exo2: fix bugs in loader stub/mmu mappings

exo2: start skeletoning bootconfig/global context types

arch: fix makefile flags

exo2: implement through master key derivation

exo2: implement device master keygen

exo2: more init through start of SetupSocSecurity

exo2: implement pmc secure scratch management

se: implement sticky bit validation

libexosphere: fix building for arm32

libexo: fix makefile flags

libexo: support building for arm64/arm

sc7fw: skeleton binary

sc7fw: skeleton a little more

sc7fw: implement all non-dram functionality

exo2: fix DivideUp error

sc7fw: implement more dram code, fix reg library errors

sc7fw: complete sc7fw impl.

exo2: skeleton the rest of SetupSocSecurity

exo2: implement fiq interrupt handler

exo2: implement all exception handlers

exo2: skeleton the entire smc api, implement the svc invoker

exo2: implement rest of SetupSocSecurity

exo2: correct slave security errors

exo2: fix register definition

exo2: minor fixes
This commit is contained in:
Michael Scire 2020-05-04 23:33:16 -07:00
parent bef5c13bb2
commit bc653fa855
109 changed files with 9129 additions and 20 deletions

11
config/arch/arm/arch.mk Normal file
View File

@ -0,0 +1,11 @@
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
include $(DEVKITPRO)/devkitARM/base_rules
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_ARM7TDMI
export ATMOSPHERE_SETTINGS += -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_BOARD_NINTENDO_NX -D__BPMP__
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@ -8,12 +8,13 @@ export ATMOSPHERE_LIBRARIES_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/..
ifeq ($(strip $(ATMOSPHERE_BOARD)),) ifeq ($(strip $(ATMOSPHERE_BOARD)),)
export ATMOSPHERE_BOARD := nx-hac-001 export ATMOSPHERE_BOARD := nx-hac-001
endif
ifeq ($(strip $(ATMOSPHERE_CPU)),) ifeq ($(strip $(ATMOSPHERE_CPU)),)
export ATMOSPHERE_CPU := arm-cortex-a57 export ATMOSPHERE_CPU := arm-cortex-a57
endif endif
endif
export ATMOSPHERE_DEFINES := -DATMOSPHERE export ATMOSPHERE_DEFINES := -DATMOSPHERE
export ATMOSPHERE_SETTINGS := -fPIE -g export ATMOSPHERE_SETTINGS := -fPIE -g
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \ export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
@ -23,6 +24,8 @@ export ATMOSPHERE_ASFLAGS :=
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001) ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
export ATMOSPHERE_ARCH_DIR := arch/arm64 export ATMOSPHERE_ARCH_DIR := arch/arm64
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx export ATMOSPHERE_BOARD_DIR := board/nintendo/nx
export ATMOSPHERE_OS_DIR := os/horizon export ATMOSPHERE_OS_DIR := os/horizon
@ -30,6 +33,16 @@ export ATMOSPHERE_OS_DIR := os/horizon
export ATMOSPHERE_ARCH_NAME := arm64 export ATMOSPHERE_ARCH_NAME := arm64
export ATMOSPHERE_BOARD_NAME := nintendo_nx export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon export ATMOSPHERE_OS_NAME := horizon
else ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
export ATMOSPHERE_ARCH_DIR := arch/arm
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx_bpmp
export ATMOSPHERE_OS_DIR := os/horizon
export ATMOSPHERE_ARCH_NAME := arm
export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon
endif
endif endif
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57) ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
@ -37,12 +50,20 @@ export ATMOSPHERE_CPU_DIR := arch/arm64/cpu/cortex_a57
export ATMOSPHERE_CPU_NAME := arm_cortex_a57 export ATMOSPHERE_CPU_NAME := arm_cortex_a57
endif endif
ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
export ATMOSPHERE_CPU_DIR := arch/arm/cpu/arm7tdmi
export ATMOSPHERE_CPU_NAME := arm7tdmi
endif
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_ARCH_DIR) export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_ARCH_DIR)
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_BOARD_DIR) export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_BOARD_DIR)
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_OS_DIR) export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_OS_DIR)
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_CPU_DIR) export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_CPU_DIR)
export ATMOSPHERE_LIBRARY_DIR := lib_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
export ATMOSPHERE_BUILD_DIR := build_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
include $(ATMOSPHERE_ARCH_MAKE_DIR)/arch.mk include $(ATMOSPHERE_ARCH_MAKE_DIR)/arch.mk
include $(ATMOSPHERE_BOARD_MAKE_DIR)/board.mk include $(ATMOSPHERE_BOARD_MAKE_DIR)/board.mk
include $(ATMOSPHERE_OS_MAKE_DIR)/os.mk include $(ATMOSPHERE_OS_MAKE_DIR)/os.mk

View File

@ -0,0 +1,46 @@
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -O2 -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
else ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm)
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
endif
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -nostdlib -nostartfiles -g $(SETTINGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,__cxa_throw \
-Wl,--wrap,__cxa_rethrow \
-Wl,--wrap,__cxa_allocate_exception \
-Wl,--wrap,__cxa_free_exception \
-Wl,--wrap,__cxa_begin_catch \
-Wl,--wrap,__cxa_end_catch \
-Wl,--wrap,__cxa_call_unexpected \
-Wl,--wrap,__cxa_call_terminate \
-Wl,--wrap,__gxx_personality_v0 \
-Wl,--wrap,_Unwind_Resume \
-Wl,--wrap,_ZSt19__throw_logic_errorPKc \
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
export LIBS := -lexosphere
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere

19
libexosphere/Makefile Normal file
View File

@ -0,0 +1,19 @@
.PHONY: all arm64 arm clean arm64-clean arm-clean
all: arm64 arm
arm64:
$(MAKE) -f arm64.mk
arm:
$(MAKE) -f arm.mk
#---------------------------------------------------------------------------------
clean: arm64-clean arm-clean
arm64-clean:
$(MAKE) -f arm64.mk clean
arm-clean:
$(MAKE) -f arm.mk clean

142
libexosphere/arm.mk Normal file
View File

@ -0,0 +1,142 @@
#---------------------------------------------------------------------------------
# Define the atmosphere board and cpu
#---------------------------------------------------------------------------------
export ATMOSPHERE_BOARD := nx-hac-001
export ATMOSPHERE_CPU := arm7tdmi
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
SOURCES += $(call ALL_SOURCE_DIRS,../libvapours/source)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
#---------------------------------------------------------------------------------
# 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 VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
#---------------------------------------------------------------------------------
# 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 GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.gch),$(notdir $(hdr)))
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.
.PHONY: clean all
#---------------------------------------------------------------------------------
all: $(ATMOSPHERE_LIBRARY_DIR)/$(TARGET).a
$(ATMOSPHERE_LIBRARY_DIR):
@[ -d $@ ] || mkdir -p $@
$(ATMOSPHERE_BUILD_DIR):
@[ -d $@ ] || mkdir -p $@
$(ATMOSPHERE_LIBRARY_DIR)/$(TARGET).a : $(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=$(ATMOSPHERE_BUILD_DIR) OUTPUT=$(CURDIR)/$@ \
DEPSDIR=$(CURDIR)/$(ATMOSPHERE_BUILD_DIR) \
--no-print-directory -C $(ATMOSPHERE_BUILD_DIR) \
-f $(CURDIR)/arm.mk
dist-bin: all
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include $(ATMOSPHERE_LIBRARY_DIR)
dist-src:
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source arm.mk
dist: dist-src dist-bin
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(OFILES) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
libc.o: CFLAGS += -fno-builtin
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

143
libexosphere/arm64.mk Normal file
View File

@ -0,0 +1,143 @@
#---------------------------------------------------------------------------------
# Define the atmosphere board and cpu
#---------------------------------------------------------------------------------
export ATMOSPHERE_BOARD := nx-hac-001
export ATMOSPHERE_CPU := arm-cortex-a57
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -O2 -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
SOURCES += $(call ALL_SOURCE_DIRS,../libvapours/source)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
#---------------------------------------------------------------------------------
# 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 VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
#---------------------------------------------------------------------------------
# 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 GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.gch),$(notdir $(hdr)))
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.
.PHONY: clean all
#---------------------------------------------------------------------------------
all: $(ATMOSPHERE_LIBRARY_DIR)/$(TARGET).a
$(ATMOSPHERE_LIBRARY_DIR):
@[ -d $@ ] || mkdir -p $@
$(ATMOSPHERE_BUILD_DIR):
@[ -d $@ ] || mkdir -p $@
$(ATMOSPHERE_LIBRARY_DIR)/$(TARGET).a : $(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=$(ATMOSPHERE_BUILD_DIR) OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
DEPSDIR=$(CURDIR)/$(ATMOSPHERE_BUILD_DIR) \
--no-print-directory -C $(ATMOSPHERE_BUILD_DIR) \
-f $(CURDIR)/arm64.mk
dist-bin: all
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include $(ATMOSPHERE_LIBRARY_DIR)
dist-src:
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source arm64.mk
dist: dist-src dist-bin
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(OFILES) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
libc.o: CFLAGS += -fno-builtin
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,38 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/common.hpp>
#include <exosphere/reg.hpp>
#include <exosphere/hw.hpp>
#include <exosphere/util.hpp>
#include <exosphere/mmu.hpp>
#include <exosphere/gic.hpp>
#include <exosphere/wdt.hpp>
#include <exosphere/pkg1.hpp>
#include <exosphere/tsec.hpp>
#include <exosphere/se.hpp>
#include <exosphere/fuse.hpp>
#include <exosphere/i2c.hpp>
#include <exosphere/uart.hpp>
#include <exosphere/pmic.hpp>
#include <exosphere/log.hpp>
#include <exosphere/clkrst.hpp>
#include <exosphere/actmon.hpp>
#include <exosphere/pmc.hpp>
#include <exosphere/secmon.hpp>
#include <exosphere/tegra.hpp>

View File

@ -0,0 +1,30 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::actmon {
using InterruptHandler = void(*)();
void SetRegisterAddress(uintptr_t address);
void HandleInterrupt();
void StartMonitoringBpmp(InterruptHandler handler);
void StopMonitoringBpmp();
}

View File

@ -0,0 +1,29 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::clkrst {
void SetRegisterAddress(uintptr_t address);
void SetFuseVisibility(bool visible);
void EnableUartAClock();
void EnableUartBClock();
void EnableUartCClock();
}

View File

@ -0,0 +1,30 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#if 1 || defined(AMS_BUILD_FOR_AUDITING)
#define EXOSPHERE_BUILD_FOR_AUDITING
#endif
#if defined(EXOSPHERE_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
#define EXOSPHERE_BUILD_FOR_DEBUGGING
#endif
#ifdef EXOSPHERE_BUILD_FOR_DEBUGGING
#define EXOSPHERE_ENABLE_ASSERTIONS
#define EXOSPHERE_ENABLE_DEBUG_PRINT
#endif

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/pmic.hpp>
namespace ams::fuse {
enum HardwareType {
HardwareType_Icosa = 0,
HardwareType_Copper = 1,
HardwareType_Hoag = 2,
HardwareType_Iowa = 3,
HardwareType_Calcio = 4,
HardwareType_Five = 5,
HardwareType_Undefined = 0xF,
};
enum HardwareState {
HardwareState_Development = 0,
HardwareState_Production = 1,
HardwareState_Undefined = 2,
};
void SetRegisterAddress(uintptr_t address);
void SetWriteSecureOnly();
void Lockout();
u32 GetOdmWord(int index);
HardwareType GetHardwareType();
HardwareState GetHardwareState();
pmic::Regulator GetRegulator();
}

View File

@ -0,0 +1,42 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::gic {
enum InterruptMode {
InterruptMode_Level = 0,
InterruptMode_Edge = 1,
};
constexpr inline s32 HighestPriority = 0;
constexpr inline s32 InterruptCount = 224;
void SetRegisterAddress(uintptr_t distributor_address, uintptr_t cpu_interface_address);
void InitializeCommon();
void InitializeCoreUnique();
void SetPriority(int interrupt_id, int priority);
void SetInterruptGroup(int interrupt_id, int group);
void SetEnable(int interrupt_id, bool enable);
void SetSpiTargetCpu(int interrupt_id, u32 cpu_mask);
void SetSpiMode(int interrupt_id, InterruptMode mode);
int GetInterruptRequestId();
void SetEndOfInterrupt(int interrupt_id);
}

View File

@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#if defined(ATMOSPHERE_ARCH_ARM64)
#include <exosphere/hw/hw_arm64.hpp>
namespace ams::hw { using namespace ams::hw::arch::arm64; }
#elif defined(ATMOSPHERE_ARCH_ARM)
#include <exosphere/hw/hw_arm.hpp>
namespace ams::hw { using namespace ams::hw::arch::arm; }
#else
#error "Unknown architecture for hw!"
#endif

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::hw::arch::arm {
#ifdef __BPMP__
constexpr inline size_t DataCacheLineSize = 0x1;
ALWAYS_INLINE void DataSynchronizationBarrier() {
/* ... */
}
ALWAYS_INLINE void DataSynchronizationBarrierInnerShareable() {
/* ... */
}
ALWAYS_INLINE void DataMemoryBarrier() {
/* ... */
}
ALWAYS_INLINE void InstructionSynchronizationBarrier() {
/* ... */
}
ALWAYS_INLINE void FlushDataCache(const void *ptr, size_t size) {
AMS_UNUSED(ptr);
AMS_UNUSED(size);
/* ... */
}
#else
#error "Unknown ARM board for ams::hw"
#endif
}

View File

@ -0,0 +1,69 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/hw/hw_arm64_system_registers.hpp>
#include <exosphere/hw/hw_arm64_cache.hpp>
namespace ams::hw::arch::arm64 {
ALWAYS_INLINE void DataSynchronizationBarrier() {
__asm__ __volatile__("dsb sy" ::: "memory");
}
ALWAYS_INLINE void DataSynchronizationBarrierInnerShareable() {
__asm__ __volatile__("dsb ish" ::: "memory");
}
ALWAYS_INLINE void DataMemoryBarrier() {
__asm__ __volatile__("dmb sy" ::: "memory");
}
ALWAYS_INLINE void InstructionSynchronizationBarrier() {
__asm__ __volatile__("isb" ::: "memory");
}
ALWAYS_INLINE void WaitForInterrupt() {
__asm__ __volatile__("wfi" ::: "memory");
}
ALWAYS_INLINE void WaitForEvent() {
__asm__ __volatile__("wfe" ::: "memory");
}
ALWAYS_INLINE void SendEvent() {
__asm__ __volatile__("sev" ::: "memory");
}
ALWAYS_INLINE int CountLeadingZeros(u64 v) {
u64 z;
__asm__ __volatile__("clz %[z], %[v]" : [z]"=r"(z) : [v]"r"(v));
return z;
}
ALWAYS_INLINE int CountLeadingZeros(u32 v) {
u32 z;
__asm__ __volatile__("clz %w[z], %w[v]" : [z]"=r"(z) : [v]"r"(v));
return z;
}
ALWAYS_INLINE int GetCurrentCoreId() {
u64 mpidr;
HW_CPU_GET_MPIDR_EL1(mpidr);
return mpidr & 0xFF;
}
}

View File

@ -0,0 +1,55 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::hw::arch::arm64 {
#if defined(ATMOSPHERE_CPU_ARM_CORTEX_A57) || defined(ATMOSPHERE_CPU_ARM_CORTEX_A53)
constexpr inline size_t InstructionCacheLineSize = 0x40;
constexpr inline size_t DataCacheLineSize = 0x40;
constexpr inline size_t NumPerformanceCounters = 6;
#else
#error "Unknown CPU for cache line sizes"
#endif
ALWAYS_INLINE void InvalidateEntireTlb() {
__asm__ __volatile__("tlbi alle3is" ::: "memory");
}
ALWAYS_INLINE void InvalidateDataCacheLine(void *ptr) {
__asm __volatile__("dc ivac, %[ptr]" :: [ptr]"r"(ptr) : "memory");
}
ALWAYS_INLINE void FlushDataCacheLine(void *ptr) {
__asm __volatile__("dc civac, %[ptr]" :: [ptr]"r"(ptr) : "memory");
}
ALWAYS_INLINE void InvalidateEntireInstructionCache() {
__asm__ __volatile__("ic iallu" ::: "memory");
}
ALWAYS_INLINE void InvalidateTlb(uintptr_t address) {
__asm__ __volatile__("tlbi vae3is, %[address]" :: [address]"r"(address) : "memory");
}
ALWAYS_INLINE void InvalidateTlbLastLevel(uintptr_t address) {
__asm__ __volatile__("tlbi vale3is, %[address]" :: [address]"r"(address) : "memory");
}
void FlushDataCache(const void *ptr, size_t size);
}

View File

@ -0,0 +1,245 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::hw::arch::arm64 {
#define HW_CPU_GET_SYSREG(name, value) __asm__ __volatile__("mrs %0, " #name "" : "=&r"(value) :: "memory");
#define HW_CPU_SET_SYSREG(name, value) __asm__ __volatile__("msr " #name ", %0" :: "r"(value) : "memory", "cc")
#define HW_CPU_GET_SCTLR_EL3(value) HW_CPU_GET_SYSREG(sctlr_el3, value)
#define HW_CPU_SET_SCTLR_EL3(value) HW_CPU_SET_SYSREG(sctlr_el3, value)
#define HW_CPU_GET_SCR_EL3(value) HW_CPU_GET_SYSREG(scr_el3, value)
#define HW_CPU_SET_SCR_EL3(value) HW_CPU_SET_SYSREG(scr_el3, value)
#define HW_CPU_GET_CPTR_EL3(value) HW_CPU_GET_SYSREG(cptr_el3, value)
#define HW_CPU_SET_CPTR_EL3(value) HW_CPU_SET_SYSREG(cptr_el3, value)
#define HW_CPU_GET_TTBR0_EL3(value) HW_CPU_GET_SYSREG(ttbr0_el3, value)
#define HW_CPU_SET_TTBR0_EL3(value) HW_CPU_SET_SYSREG(ttbr0_el3, value)
#define HW_CPU_GET_TCR_EL3(value) HW_CPU_GET_SYSREG(tcr_el3, value)
#define HW_CPU_SET_TCR_EL3(value) HW_CPU_SET_SYSREG(tcr_el3, value)
#define HW_CPU_GET_MAIR_EL3(value) HW_CPU_GET_SYSREG(mair_el3, value)
#define HW_CPU_SET_MAIR_EL3(value) HW_CPU_SET_SYSREG(mair_el3, value)
#define HW_CPU_GET_VBAR_EL3(value) HW_CPU_GET_SYSREG(vbar_el3, value)
#define HW_CPU_SET_VBAR_EL3(value) HW_CPU_SET_SYSREG(vbar_el3, value)
#define HW_CPU_GET_CLIDR_EL1(value) HW_CPU_GET_SYSREG(clidr_el1, value)
#define HW_CPU_SET_CLIDR_EL1(value) HW_CPU_SET_SYSREG(clidr_el1, value)
#define HW_CPU_GET_CCSIDR_EL1(value) HW_CPU_GET_SYSREG(ccsidr_el1, value)
#define HW_CPU_SET_CCSIDR_EL1(value) HW_CPU_SET_SYSREG(ccsidr_el1, value)
#define HW_CPU_GET_CSSELR_EL1(value) HW_CPU_GET_SYSREG(csselr_el1, value)
#define HW_CPU_SET_CSSELR_EL1(value) HW_CPU_SET_SYSREG(csselr_el1, value)
#define HW_CPU_GET_CPUACTLR_EL1(value) HW_CPU_GET_SYSREG(s3_1_c15_c2_0, value)
#define HW_CPU_SET_CPUACTLR_EL1(value) HW_CPU_SET_SYSREG(s3_1_c15_c2_0, value)
#define HW_CPU_GET_CPUECTLR_EL1(value) HW_CPU_GET_SYSREG(s3_1_c15_c2_1, value)
#define HW_CPU_SET_CPUECTLR_EL1(value) HW_CPU_SET_SYSREG(s3_1_c15_c2_1, value)
#define HW_CPU_GET_DBGAUTHSTATUS_EL1(value) HW_CPU_GET_SYSREG(dbgauthstatus_el1, value)
#define HW_CPU_SET_DBGAUTHSTATUS_EL1(value) HW_CPU_SET_SYSREG(dbgauthstatus_el1, value)
#define HW_CPU_GET_MPIDR_EL1(value) HW_CPU_GET_SYSREG(mpidr_el1, value)
#define HW_CPU_GET_OSLAR_EL1(value) HW_CPU_GET_SYSREG(oslar_el1, value)
#define HW_CPU_SET_OSLAR_EL1(value) HW_CPU_SET_SYSREG(oslar_el1, value)
#define HW_CPU_GET_OSDTRRX_EL1(value) HW_CPU_GET_SYSREG(osdtrrx_el1, value)
#define HW_CPU_SET_OSDTRRX_EL1(value) HW_CPU_SET_SYSREG(osdtrrx_el1, value)
#define HW_CPU_GET_OSDTRTX_EL1(value) HW_CPU_GET_SYSREG(osdtrtx_el1, value)
#define HW_CPU_SET_OSDTRTX_EL1(value) HW_CPU_SET_SYSREG(osdtrtx_el1, value)
#define HW_CPU_GET_MDSCR_EL1(value) HW_CPU_GET_SYSREG(mdscr_el1, value)
#define HW_CPU_SET_MDSCR_EL1(value) HW_CPU_SET_SYSREG(mdscr_el1, value)
#define HW_CPU_GET_OSECCR_EL1(value) HW_CPU_GET_SYSREG(oseccr_el1, value)
#define HW_CPU_SET_OSECCR_EL1(value) HW_CPU_SET_SYSREG(oseccr_el1, value)
#define HW_CPU_GET_MDCCINT_EL1(value) HW_CPU_GET_SYSREG(mdccint_el1, value)
#define HW_CPU_SET_MDCCINT_EL1(value) HW_CPU_SET_SYSREG(mdccint_el1, value)
#define HW_CPU_GET_DBGCLAIMCLR_EL1(value) HW_CPU_GET_SYSREG(dbgclaimclr_el1, value)
#define HW_CPU_SET_DBGCLAIMCLR_EL1(value) HW_CPU_SET_SYSREG(dbgclaimclr_el1, value)
#define HW_CPU_GET_DBGVCR32_EL2(value) HW_CPU_GET_SYSREG(dbgvcr32_el2, value)
#define HW_CPU_SET_DBGVCR32_EL2(value) HW_CPU_SET_SYSREG(dbgvcr32_el2, value)
#define HW_CPU_GET_SDER32_EL3(value) HW_CPU_GET_SYSREG(sder32_el3, value)
#define HW_CPU_SET_SDER32_EL3(value) HW_CPU_SET_SYSREG(sder32_el3, value)
#define HW_CPU_GET_MDCR_EL2(value) HW_CPU_GET_SYSREG(mdcr_el2, value)
#define HW_CPU_SET_MDCR_EL2(value) HW_CPU_SET_SYSREG(mdcr_el2, value)
#define HW_CPU_GET_MDCR_EL3(value) HW_CPU_GET_SYSREG(mdcr_el3, value)
#define HW_CPU_SET_MDCR_EL3(value) HW_CPU_SET_SYSREG(mdcr_el3, value)
#define HW_CPU_GET_SPSR_EL3(value) HW_CPU_GET_SYSREG(spsr_el3, value)
#define HW_CPU_SET_SPSR_EL3(value) HW_CPU_SET_SYSREG(spsr_el3, value)
#define HW_CPU_GET_DBGBVR0_EL1(value) HW_CPU_GET_SYSREG(dbgbvr0_el1, value)
#define HW_CPU_SET_DBGBVR0_EL1(value) HW_CPU_SET_SYSREG(dbgbvr0_el1, value)
#define HW_CPU_GET_DBGBCR0_EL1(value) HW_CPU_GET_SYSREG(dbgbcr0_el1, value)
#define HW_CPU_SET_DBGBCR0_EL1(value) HW_CPU_SET_SYSREG(dbgbcr0_el1, value)
#define HW_CPU_GET_DBGBVR1_EL1(value) HW_CPU_GET_SYSREG(dbgbvr1_el1, value)
#define HW_CPU_SET_DBGBVR1_EL1(value) HW_CPU_SET_SYSREG(dbgbvr1_el1, value)
#define HW_CPU_GET_DBGBCR1_EL1(value) HW_CPU_GET_SYSREG(dbgbcr1_el1, value)
#define HW_CPU_SET_DBGBCR1_EL1(value) HW_CPU_SET_SYSREG(dbgbcr1_el1, value)
#define HW_CPU_GET_DBGBVR2_EL1(value) HW_CPU_GET_SYSREG(dbgbvr2_el1, value)
#define HW_CPU_SET_DBGBVR2_EL1(value) HW_CPU_SET_SYSREG(dbgbvr2_el1, value)
#define HW_CPU_GET_DBGBCR2_EL1(value) HW_CPU_GET_SYSREG(dbgbcr2_el1, value)
#define HW_CPU_SET_DBGBCR2_EL1(value) HW_CPU_SET_SYSREG(dbgbcr2_el1, value)
#define HW_CPU_GET_DBGBVR3_EL1(value) HW_CPU_GET_SYSREG(dbgbvr3_el1, value)
#define HW_CPU_SET_DBGBVR3_EL1(value) HW_CPU_SET_SYSREG(dbgbvr3_el1, value)
#define HW_CPU_GET_DBGBCR3_EL1(value) HW_CPU_GET_SYSREG(dbgbcr3_el1, value)
#define HW_CPU_SET_DBGBCR3_EL1(value) HW_CPU_SET_SYSREG(dbgbcr3_el1, value)
#define HW_CPU_GET_DBGBVR4_EL1(value) HW_CPU_GET_SYSREG(dbgbvr4_el1, value)
#define HW_CPU_SET_DBGBVR4_EL1(value) HW_CPU_SET_SYSREG(dbgbvr4_el1, value)
#define HW_CPU_GET_DBGBCR4_EL1(value) HW_CPU_GET_SYSREG(dbgbcr4_el1, value)
#define HW_CPU_SET_DBGBCR4_EL1(value) HW_CPU_SET_SYSREG(dbgbcr4_el1, value)
#define HW_CPU_GET_DBGBVR5_EL1(value) HW_CPU_GET_SYSREG(dbgbvr5_el1, value)
#define HW_CPU_SET_DBGBVR5_EL1(value) HW_CPU_SET_SYSREG(dbgbvr5_el1, value)
#define HW_CPU_GET_DBGBCR5_EL1(value) HW_CPU_GET_SYSREG(dbgbcr5_el1, value)
#define HW_CPU_SET_DBGBCR5_EL1(value) HW_CPU_SET_SYSREG(dbgbcr5_el1, value)
#define HW_CPU_GET_DBGWVR0_EL1(value) HW_CPU_GET_SYSREG(dbgwvr0_el1, value)
#define HW_CPU_SET_DBGWVR0_EL1(value) HW_CPU_SET_SYSREG(dbgwvr0_el1, value)
#define HW_CPU_GET_DBGWCR0_EL1(value) HW_CPU_GET_SYSREG(dbgwcr0_el1, value)
#define HW_CPU_SET_DBGWCR0_EL1(value) HW_CPU_SET_SYSREG(dbgwcr0_el1, value)
#define HW_CPU_GET_DBGWVR1_EL1(value) HW_CPU_GET_SYSREG(dbgwvr1_el1, value)
#define HW_CPU_SET_DBGWVR1_EL1(value) HW_CPU_SET_SYSREG(dbgwvr1_el1, value)
#define HW_CPU_GET_DBGWCR1_EL1(value) HW_CPU_GET_SYSREG(dbgwcr1_el1, value)
#define HW_CPU_SET_DBGWCR1_EL1(value) HW_CPU_SET_SYSREG(dbgwcr1_el1, value)
#define HW_CPU_GET_DBGWVR2_EL1(value) HW_CPU_GET_SYSREG(dbgwvr2_el1, value)
#define HW_CPU_SET_DBGWVR2_EL1(value) HW_CPU_SET_SYSREG(dbgwvr2_el1, value)
#define HW_CPU_GET_DBGWCR2_EL1(value) HW_CPU_GET_SYSREG(dbgwcr2_el1, value)
#define HW_CPU_SET_DBGWCR2_EL1(value) HW_CPU_SET_SYSREG(dbgwcr2_el1, value)
#define HW_CPU_GET_DBGWVR3_EL1(value) HW_CPU_GET_SYSREG(dbgwvr3_el1, value)
#define HW_CPU_SET_DBGWVR3_EL1(value) HW_CPU_SET_SYSREG(dbgwvr3_el1, value)
#define HW_CPU_GET_DBGWCR3_EL1(value) HW_CPU_GET_SYSREG(dbgwcr3_el1, value)
#define HW_CPU_SET_DBGWCR3_EL1(value) HW_CPU_SET_SYSREG(dbgwcr3_el1, value)
/* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/system-control-register-el3 */
struct SctlrEl3 {
using M = util::BitPack32::Field< 0, 1>;
using A = util::BitPack32::Field< 1, 1>;
using C = util::BitPack32::Field< 2, 1>;
using Sa = util::BitPack32::Field< 3, 1>;
using I = util::BitPack32::Field<12, 1>;
using Wxn = util::BitPack32::Field<19, 1>;
using Ee = util::BitPack32::Field<25, 1>;
static constexpr u32 Res1 = 0x30C50830;
};
/* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/BABGIHHJ.html */
struct ScrEl3 {
using Ns = util::BitPack32::Field< 0, 1>;
using Irq = util::BitPack32::Field< 1, 1>;
using Fiq = util::BitPack32::Field< 2, 1>;
using Ea = util::BitPack32::Field< 3, 1>;
using Fw = util::BitPack32::Field< 4, 1>;
using Aw = util::BitPack32::Field< 5, 1>;
using Net = util::BitPack32::Field< 6, 1>;
using Smd = util::BitPack32::Field< 7, 1>;
using Hce = util::BitPack32::Field< 8, 1>;
using Sif = util::BitPack32::Field< 9, 1>;
using RwCortexA53 = util::BitPack32::Field<10, 1>;
using StCortexA53 = util::BitPack32::Field<11, 1>;
using Twi = util::BitPack32::Field<12, 1>;
using Twe = util::BitPack32::Field<13, 1>;
};
/* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/CIHDEBIG.html */
struct CptrEl3 {
using Tfp = util::BitPack32::Field<10, 1>;
using Tta = util::BitPack32::Field<20, 1>;
using Tcpac = util::BitPack32::Field<31, 1>;
};
/* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/translation-control-register-el3 */
struct TcrEl3 {
using T0sz = util::BitPack32::Field< 0, 6>;
using Irgn0 = util::BitPack32::Field< 8, 2>;
using Orgn0 = util::BitPack32::Field<10, 2>;
using Sh0 = util::BitPack32::Field<12, 2>;
using Tg0 = util::BitPack32::Field<14, 2>;
using Ps = util::BitPack32::Field<16, 3>;
using Tbi = util::BitPack32::Field<20, 1>;
static constexpr u32 Res1 = 0x80800000;
};
struct ClidrEl1 {
using Ctype1 = util::BitPack32::Field< 0, 3>;
using Ctype2 = util::BitPack32::Field< 3, 3>;
using Ctype3 = util::BitPack32::Field< 6, 3>;
using Louis = util::BitPack32::Field<21, 3>;
using Loc = util::BitPack32::Field<24, 3>;
using Louu = util::BitPack32::Field<27, 3>;
};
struct CcsidrEl1 {
using LineSize = util::BitPack32::Field< 0, 3>;
using Associativity = util::BitPack32::Field< 3, 10>;
using NumSets = util::BitPack32::Field<13, 15>;
using Wa = util::BitPack32::Field<28, 1>;
using Ra = util::BitPack32::Field<29, 1>;
using Wb = util::BitPack32::Field<30, 1>;
using Wt = util::BitPack32::Field<31, 1>;
};
struct CsselrEl1 {
using InD = util::BitPack32::Field<0, 1>;
using Level = util::BitPack32::Field<1, 3>;
};
/* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/cpu-auxiliary-control-register-el1 */
struct CpuactlrEl1CortexA57 {
/* TODO: Other bits */
using NonCacheableStreamingEnhancement = util::BitPack64::Field<24, 1>;
/* TODO: Other bits */
using DisableLoadPassDmb = util::BitPack64::Field<59, 1>;
using ForceProcessorRcgEnablesActive = util::BitPack64::Field<63, 1>;
};
/* https://developer.arm.com/docs/ddi0488/h/system-control/aarch64-register-descriptions/cpu-extended-control-register-el1 */
struct CpuectlrEl1CortexA57 {
using ProcessorDynamicRetentionControl = util::BitPack64::Field< 0, 2>;
using Smpen = util::BitPack64::Field< 6, 1>;
using L2LoadStoreDataPrefetchDistance = util::BitPack64::Field<32, 2>;
using L2InstructionFetchPrefetchDistance = util::BitPack64::Field<35, 2>;
using DisableTableWalkDescriptorAccessPrefetch = util::BitPack64::Field<38, 1>;
};
/* https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/dbgauthstatus_el1 */
struct DbgAuthStatusEl1 {
using Nsid = util::BitPack32::Field<0, 2>;
using Nsnid = util::BitPack32::Field<2, 2>;
using Sid = util::BitPack32::Field<4, 2>;
using Snid = util::BitPack32::Field<6, 2>;
};
}

View File

@ -0,0 +1,46 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::i2c {
enum Port {
Port_1 = 0,
/* TODO: Support other ports? */
Port_5 = 4,
Port_Count = 5,
};
void SetRegisterAddress(Port port, uintptr_t address);
void Initialize(Port port);
bool Query(void *dst, size_t dst_size, Port port, int address, int r);
bool Send(Port port, int address, int r, const void *src, size_t src_size);
inline u8 QueryByte(Port port, int address, int r) {
u8 byte;
Query(std::addressof(byte), sizeof(byte), port, address, r);
return byte;
}
inline void SendByte(Port port, int address, int r, u8 byte) {
Send(port, address, r, std::addressof(byte), sizeof(byte));
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::log {
void Initialize();
}

View File

@ -0,0 +1,18 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/mmu/mmu_api.hpp>

View File

@ -0,0 +1,43 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::mmu::arch::arm {
/* NOTE: mmu is not supported by libexosphere-on-arm. */
/* However, we want the memory layout to be parseable, so we will include some arm64 mmu definitions. */
constexpr inline u64 L1EntryShift = 30;
constexpr inline u64 L2EntryShift = 21;
constexpr inline u64 L3EntryShift = 12;
constexpr inline u64 L1EntrySize = 1_GB;
constexpr inline u64 L2EntrySize = 2_MB;
constexpr inline u64 L3EntrySize = 4_KB;
constexpr inline u64 PageSize = L3EntrySize;
constexpr inline u64 L1EntryMask = ((static_cast<u64>(1) << (48 - L1EntryShift)) - 1) << L1EntryShift;
constexpr inline u64 L2EntryMask = ((static_cast<u64>(1) << (48 - L2EntryShift)) - 1) << L2EntryShift;
constexpr inline u64 L3EntryMask = ((static_cast<u64>(1) << (48 - L3EntryShift)) - 1) << L3EntryShift;
constexpr inline u64 TableEntryMask = L3EntryMask;
static_assert(L1EntryMask == 0x0000FFFFC0000000ul);
static_assert(L2EntryMask == 0x0000FFFFFFE00000ul);
static_assert(L3EntryMask == 0x0000FFFFFFFFF000ul);
}

View File

@ -0,0 +1,279 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::mmu::arch::arm64 {
enum PageTableTableAttribute : u64 {
PageTableTableAttribute_None = (0ul << 0),
PageTableTableAttribute_PrivilegedExecuteNever = (1ul << 59),
PageTableTableAttribute_ExecuteNever = (1ul << 60),
PageTableTableAttribute_NonSecure = (1ul << 63),
PageTableTableAttributes_El3SecureCode = PageTableTableAttribute_None,
PageTableTableAttributes_El3SecureData = PageTableTableAttribute_ExecuteNever,
PageTableTableAttributes_El3NonSecureCode = PageTableTableAttributes_El3SecureCode | PageTableTableAttribute_NonSecure,
PageTableTableAttributes_El3NonSecureData = PageTableTableAttributes_El3SecureData | PageTableTableAttribute_NonSecure,
};
enum PageTableMappingAttribute : u64{
/* Security. */
PageTableMappingAttribute_NonSecure = (1ul << 5),
/* El1 Access. */
PageTableMappingAttribute_El1NotAllowed = (0ul << 6),
PageTableMappingAttribute_El1Allowed = (1ul << 6),
/* RW Permission. */
PageTableMappingAttribute_PermissionReadWrite = (0ul << 7),
PageTableMappingAttribute_PermissionReadOnly = (1ul << 7),
/* Shareability. */
PageTableMappingAttribute_ShareabilityNonShareable = (0ul << 8),
PageTableMappingAttribute_ShareabiltiyOuterShareable = (2ul << 8),
PageTableMappingAttribute_ShareabilityInnerShareable = (3ul << 8),
/* Access flag. */
PageTableMappingAttribute_AccessFlagNotAccessed = (0ul << 10),
PageTableMappingAttribute_AccessFlagAccessed = (1ul << 10),
/* Global. */
PageTableMappingAttribute_Global = (0ul << 11),
PageTableMappingAttribute_NonGlobal = (1ul << 11),
/* Contiguous */
PageTableMappingAttribute_NonContiguous = (0ul << 52),
PageTableMappingAttribute_Contiguous = (1ul << 52),
/* Privileged Execute Never */
PageTableMappingAttribute_PrivilegedExecuteNever = (1ul << 53),
/* Execute Never */
PageTableMappingAttribute_ExecuteNever = (1ul << 54),
/* Useful definitions. */
PageTableMappingAttributes_El3SecureRwCode = (
PageTableMappingAttribute_PermissionReadWrite |
PageTableMappingAttribute_ShareabilityInnerShareable
),
PageTableMappingAttributes_El3SecureRoCode = (
PageTableMappingAttribute_PermissionReadOnly |
PageTableMappingAttribute_ShareabilityInnerShareable
),
PageTableMappingAttributes_El3SecureRoData = (
PageTableMappingAttribute_PermissionReadOnly |
PageTableMappingAttribute_ShareabilityInnerShareable |
PageTableMappingAttribute_ExecuteNever
),
PageTableMappingAttributes_El3SecureRwData = (
PageTableMappingAttribute_PermissionReadWrite |
PageTableMappingAttribute_ShareabilityInnerShareable |
PageTableMappingAttribute_ExecuteNever
),
PageTableMappingAttributes_El3NonSecureRwCode = PageTableMappingAttributes_El3SecureRwCode | PageTableMappingAttribute_NonSecure,
PageTableMappingAttributes_El3NonSecureRoCode = PageTableMappingAttributes_El3SecureRoCode | PageTableMappingAttribute_NonSecure,
PageTableMappingAttributes_El3NonSecureRoData = PageTableMappingAttributes_El3SecureRoData | PageTableMappingAttribute_NonSecure,
PageTableMappingAttributes_El3NonSecureRwData = PageTableMappingAttributes_El3SecureRwData | PageTableMappingAttribute_NonSecure,
PageTableMappingAttributes_El3SecureDevice = PageTableMappingAttributes_El3SecureRwData,
PageTableMappingAttributes_El3NonSecureDevice = PageTableMappingAttributes_El3NonSecureRwData,
};
enum MemoryRegionAttribute : u64 {
MemoryRegionAttribute_Device_nGnRnE = (0ul << 2),
MemoryRegionAttribute_Device_nGnRE = (1ul << 2),
MemoryRegionAttribute_NormalMemory = (2ul << 2),
MemoryRegionAttribute_NormalMemoryNotCacheable = (3ul << 2),
MemoryRegionAttribute_NormalInnerShift = 0,
MemoryRegionAttribute_NormalOuterShift = 4,
#define AMS_MRA_DEFINE_NORMAL_ATTR(__NAME__, __VAL__) \
MemoryRegionAttribute_NormalInner##__NAME__ = (__VAL__ << MemoryRegionAttribute_NormalInnerShift), \
MemoryRegionAttribute_NormalOuter##__NAME__ = (__VAL__ << MemoryRegionAttribute_NormalOuterShift)
AMS_MRA_DEFINE_NORMAL_ATTR(NonCacheable, 4),
AMS_MRA_DEFINE_NORMAL_ATTR(WriteAllocate, (1ul << 0)),
AMS_MRA_DEFINE_NORMAL_ATTR(ReadAllocate, (1ul << 1)),
AMS_MRA_DEFINE_NORMAL_ATTR(WriteThroughTransient, (0ul << 2)),
AMS_MRA_DEFINE_NORMAL_ATTR(WriteBackTransient, (1ul << 2)),
AMS_MRA_DEFINE_NORMAL_ATTR(WriteThroughNonTransient, (2ul << 2)),
AMS_MRA_DEFINE_NORMAL_ATTR(WriteBackNonTransient, (3ul << 2)),
#undef AMS_MRA_DEFINE_NORMAL_ATTR
MemoryRegionAttributes_Normal = (
MemoryRegionAttribute_NormalInnerReadAllocate |
MemoryRegionAttribute_NormalOuterReadAllocate |
MemoryRegionAttribute_NormalInnerWriteAllocate |
MemoryRegionAttribute_NormalOuterWriteAllocate |
MemoryRegionAttribute_NormalInnerWriteBackNonTransient |
MemoryRegionAttribute_NormalOuterWriteBackNonTransient
),
MemoryRegionAttributes_Device = (
MemoryRegionAttribute_Device_nGnRE
),
};
constexpr inline u64 MemoryRegionAttributeWidth = 8;
constexpr PageTableMappingAttribute AddMappingAttributeIndex(PageTableMappingAttribute attr, int index) {
return static_cast<PageTableMappingAttribute>(attr | (static_cast<typename std::underlying_type<PageTableMappingAttribute>::type>(index) << 2));
}
constexpr inline u64 L1EntryShift = 30;
constexpr inline u64 L2EntryShift = 21;
constexpr inline u64 L3EntryShift = 12;
constexpr inline u64 L1EntrySize = 1_GB;
constexpr inline u64 L2EntrySize = 2_MB;
constexpr inline u64 L3EntrySize = 4_KB;
constexpr inline u64 PageSize = L3EntrySize;
constexpr inline u64 L1EntryMask = ((1ul << (48 - L1EntryShift)) - 1) << L1EntryShift;
constexpr inline u64 L2EntryMask = ((1ul << (48 - L2EntryShift)) - 1) << L2EntryShift;
constexpr inline u64 L3EntryMask = ((1ul << (48 - L3EntryShift)) - 1) << L3EntryShift;
constexpr inline u64 TableEntryMask = L3EntryMask;
static_assert(L1EntryMask == 0x0000FFFFC0000000ul);
static_assert(L2EntryMask == 0x0000FFFFFFE00000ul);
static_assert(L3EntryMask == 0x0000FFFFFFFFF000ul);
constexpr inline u64 TableEntryIndexMask = 0x1FF;
constexpr inline u64 EntryBlock = 0x1ul;
constexpr inline u64 EntryPage = 0x3ul;
constexpr u64 MakeTableEntry(u64 address, PageTableTableAttribute attr) {
return address | static_cast<u64>(attr) | 0x3ul;
}
constexpr u64 MakeL1BlockEntry(u64 address, PageTableMappingAttribute attr) {
return address | static_cast<u64>(attr) | 0x1ul;
}
constexpr u64 MakeL2BlockEntry(u64 address, PageTableMappingAttribute attr) {
return address | static_cast<u64>(attr) | 0x1ul;
}
constexpr u64 MakeL3BlockEntry(u64 address, PageTableMappingAttribute attr) {
return address | static_cast<u64>(attr) | 0x3ul;
}
constexpr uintptr_t GetL2Offset(uintptr_t address) {
return address & ((1ul << L2EntryShift) - 1);
}
constexpr u64 GetL1EntryIndex(uintptr_t address) {
return ((address >> L1EntryShift) & TableEntryIndexMask);
}
constexpr u64 GetL2EntryIndex(uintptr_t address) {
return ((address >> L2EntryShift) & TableEntryIndexMask);
}
constexpr u64 GetL3EntryIndex(uintptr_t address) {
return ((address >> L3EntryShift) & TableEntryIndexMask);
}
constexpr ALWAYS_INLINE void SetTableImpl(u64 *table, u64 index, u64 value) {
/* Ensure (for constexpr validation purposes) that the entry we set is clear. */
if (table[index]) {
__builtin_unreachable();
}
/* Set the value. */
table[index] = value;
}
constexpr void SetL1TableEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, PageTableTableAttribute attr) {
SetTableImpl(table, GetL1EntryIndex(virt_addr), MakeTableEntry(phys_addr & TableEntryMask, attr));
}
constexpr void SetL2TableEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, PageTableTableAttribute attr) {
SetTableImpl(table, GetL2EntryIndex(virt_addr), MakeTableEntry(phys_addr & TableEntryMask, attr));
}
constexpr void SetL1BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
const u64 start = GetL1EntryIndex(virt_addr);
const u64 count = (size >> L1EntryShift);
for (u64 i = 0; i < count; ++i) {
SetTableImpl(table, start + i, MakeL1BlockEntry((phys_addr & L1EntryMask) + (i << L1EntryShift), attr));
}
}
constexpr void SetL2BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
const u64 start = GetL2EntryIndex(virt_addr);
const u64 count = (size >> L2EntryShift);
for (u64 i = 0; i < count; ++i) {
SetTableImpl(table, start + i, MakeL2BlockEntry((phys_addr & L2EntryMask) + (i << L2EntryShift), attr));
}
}
constexpr void SetL3BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
const u64 start = GetL3EntryIndex(virt_addr);
const u64 count = (size >> L3EntryShift);
for (u64 i = 0; i < count; ++i) {
SetTableImpl(table, start + i, MakeL3BlockEntry((phys_addr & L3EntryMask) + (i << L3EntryShift), attr));
}
}
constexpr void InvalidateL1Entries(u64 *table, uintptr_t virt_addr, size_t size) {
const u64 start = GetL1EntryIndex(virt_addr);
const u64 count = (size >> L1EntryShift);
const u64 end = start + count;
for (u64 i = start; i < end; ++i) {
table[i] = 0;
}
}
constexpr void InvalidateL2Entries(u64 *table, uintptr_t virt_addr, size_t size) {
const u64 start = GetL2EntryIndex(virt_addr);
const u64 count = (size >> L2EntryShift);
const u64 end = start + count;
for (u64 i = start; i < end; ++i) {
table[i] = 0;
}
}
constexpr void InvalidateL3Entries(u64 *table, uintptr_t virt_addr, size_t size) {
const u64 start = GetL3EntryIndex(virt_addr);
const u64 count = (size >> L3EntryShift);
const u64 end = start + count;
for (u64 i = start; i < end; ++i) {
table[i] = 0;
}
}
}

View File

@ -0,0 +1,37 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#if defined(ATMOSPHERE_ARCH_ARM64)
#include <exosphere/mmu/mmu_api.arch.arm64.hpp>
#elif defined(ATMOSPHERE_ARCH_ARM)
#include <exosphere/mmu/mmu_api.arch.arm.hpp>
#else
#error "Unknown architecture for mmu!"
#endif
namespace ams::mmu {
#if defined(ATMOSPHERE_ARCH_ARM64)
using namespace ams::mmu::arch::arm64;
#elif defined(ATMOSPHERE_ARCH_ARM)
using namespace ams::mmu::arch::arm;
#else
#error "Unknown architecture for mmu!"
#endif
}

View File

@ -0,0 +1,22 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/pkg1/pkg1_bootloader_parameters.hpp>
#include <exosphere/pkg1/pkg1_boot_config.hpp>
#include <exosphere/pkg1/pkg1_error_types.hpp>
#include <exosphere/pkg1/pkg1_key_generation.hpp>
#include <exosphere/pkg1/pkg1_se_key_slots.hpp>

View File

@ -0,0 +1,133 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::pkg1 {
enum MemorySize {
MemorySize_4GB = 0,
MemorySize_6GB = 1,
MemorySize_8GB = 2,
};
enum MemoryArrange {
MemoryArrange_Normal = 1,
MemoryArrange_AppletDev = 2,
MemoryArrange_SystemDev = 2,
};
enum MemoryMode {
MemoryMode_SizeShift = 4,
MemoryMode_SizeMask = 0x30,
MemoryMode_ArrangeMask = 0x0F,
MemoryMode_Auto = 0x00,
MemoryMode_4GB = ((MemorySize_4GB << MemoryMode_SizeShift) | (MemoryArrange_Normal)),
MemoryMode_4GBAppletDev = ((MemorySize_4GB << MemoryMode_SizeShift) | (MemoryArrange_AppletDev)),
MemoryMode_4GBSystemDev = ((MemorySize_4GB << MemoryMode_SizeShift) | (MemoryArrange_SystemDev)),
MemoryMode_6GB = ((MemorySize_6GB << MemoryMode_SizeShift) | (MemoryArrange_Normal)),
MemoryMode_6GBAppletDev = ((MemorySize_6GB << MemoryMode_SizeShift) | (MemoryArrange_AppletDev)),
MemoryMode_8GB = ((MemorySize_8GB << MemoryMode_SizeShift) | (MemoryArrange_Normal)),
};
constexpr ALWAYS_INLINE MemorySize GetMemorySize(MemoryMode mode) {
return static_cast<MemorySize>(mode >> MemoryMode_SizeShift);
}
constexpr ALWAYS_INLINE MemoryArrange GetMemoryArrange(MemoryMode mode) {
return static_cast<MemoryArrange>(mode & MemoryMode_ArrangeMask);
}
constexpr ALWAYS_INLINE MemoryMode MakeMemoryMode(MemorySize size, MemoryArrange arrange) {
return static_cast<MemoryMode>((size << MemoryMode_SizeShift) | (arrange));
}
struct BootConfigData {
u32 version;
u32 reserved_04;
u32 reserved_08;
u32 reserved_0C;
u8 flags1[0x10];
u8 flags0[0x10];
u64 initial_tsc_value;
u8 padding_38[0x200 - 0x38];
constexpr bool IsDevelopmentFunctionEnabled() const {
return (this->flags1[0] & (1 << 1)) != 0;
}
constexpr bool IsSErrorDebugEnabled() const {
return (this->flags1[0] & (1 << 2)) != 0;
}
constexpr u8 GetKernelFlags0() const {
return this->flags0[1];
}
constexpr u8 GetKernelFlags1() const {
return this->flags1[0];
}
constexpr MemoryMode GetMemoryMode() const {
return static_cast<MemoryMode>(this->flags0[3]);
}
bool IsTscInitialValueValid() const {
return (this->flags0[4] & (1 << 0)) != 0;
}
};
static_assert(util::is_pod<BootConfigData>::value);
static_assert(sizeof(BootConfigData) == 0x200);
struct BootConfigSignedData {
u32 version;
u32 reserved_04;
u8 flags;
u8 reserved_09[0x10 - 9];
u8 ecid[0x10];
u8 flags1[0x10];
u8 flags0[0x10];
u8 padding_40[0x100 - 0x40];
constexpr bool IsPackage2EncryptionDisabled() const {
return (this->flags & (1 << 0)) != 0;
}
constexpr bool IsPackage2SignatureVerificationDisabled() const {
return (this->flags & (1 << 1)) != 0;
}
constexpr bool IsProgramVerificationDisabled() const {
return (this->flags1[0] & (1 << 0)) != 0;
}
};
static_assert(util::is_pod<BootConfigSignedData>::value);
static_assert(sizeof(BootConfigSignedData) == 0x100);
struct BootConfig {
BootConfigData data;
u8 signature[0x100];
BootConfigSignedData signed_data;
};
static_assert(util::is_pod<BootConfig>::value);
static_assert(sizeof(BootConfig) == 0x400);
}

View File

@ -0,0 +1,68 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::pkg1 {
enum BootloaderState {
BootloaderState_Start = 0,
BootloaderState_LoadedBootConfig = 1,
BootloaderState_InitializedDram = 2,
BootloaderState_LoadedPackage2 = 3,
BootloaderState_Done = 4,
};
enum SecureMonitorState {
SecureMonitorState_Start = 0,
SecureMonitorState_Initialized = 1,
};
struct BctParameters {
u32 bootloader_version;
u32 bootloader_start_block;
u32 bootloader_start_page;
u32 bootloader_attributes;
};
static_assert(util::is_pod<BctParameters>::value && sizeof(BctParameters) == 0x10);
struct SecureMonitorParameters {
u32 bootloader_start_time;
u32 bootloader_end_time;
u32 secmon_start_time;
u32 secmon_end_time;
BctParameters bct_params;
u8 reserved[0xD8];
u32 bootloader_state;
u32 secmon_state;
u8 reserved2[0x100];
};
static_assert(util::is_pod<SecureMonitorParameters>::value);
static_assert(sizeof(SecureMonitorParameters) == 0x200);
static_assert(offsetof(SecureMonitorParameters, bct_params) == 0x10);
static_assert(offsetof(SecureMonitorParameters, bootloader_state) == 0xF8);
static_assert(offsetof(SecureMonitorParameters, secmon_state) == 0xFC);
enum BootloaderAttribute {
BootloaderAttribute_None = (0u << 0),
BootloaderAttribute_RecoveryBoot = (1u << 0),
BootloaderAttribute_RestrictedSmcShift = 1,
BootloaderAttribute_RestrictedSmcMask = (0xFu << BootloaderAttribute_RestrictedSmcShift),
};
}

View File

@ -0,0 +1,108 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::pkg1 {
enum ErrorReason {
ErrorReason_None = 0,
ErrorReason_InvalidPackage2Signature = 1,
ErrorReason_InvalidPackage2Meta = 2,
ErrorReason_InvalidPackage2Version = 3,
ErrorReason_InvalidPackage2Payload = 4,
ErrorReason_UnknownSmc = 5,
ErrorReason_UnknownAbort = 6,
ErrorReason_InvalidCoreContext = 7,
ErrorReason_InvalidSecurityEngineStickyBits = 8,
ErrorReason_UnexpectedReset = 9,
ErrorReason_Exception = 0x10,
ErrorReason_TransitionToSafeMode = 0x20,
ErrorReason_SecureInitializerReboot = 0x21,
ErrorReason_SdmmcError = 0x30,
ErrorReason_InvalidDramId = 0x31,
ErrorReason_InvalidPackage2 = 0x32,
ErrorReason_InvalidBct = 0x33,
ErrorReason_InvalidGpt = 0x34,
ErrorReason_FailedToTransitionToSafeMode = 0x35,
ErrorReason_ActivityMonitorInterrupt = 0x36,
ErrorReason_KernelPanic = 0x40,
};
enum ErrorColor {
ErrorColor_Black = 0x000,
ErrorColor_Red = 0x00F,
ErrorColor_Yellow = 0x0FF,
ErrorColor_Orange = 0x07F,
ErrorColor_Blue = 0xF00,
ErrorColor_LightBlue = 0xFF0,
ErrorColor_Pink = 0xF7F,
ErrorColor_Purple = 0xF0A,
};
enum ErrorInfo {
ErrorInfo_ReasonMask = 0xFF,
ErrorInfo_ColorShift = 20,
#define MAKE_ERROR_INFO(_COLOR_, _DESC_) ((static_cast<u32>(ErrorColor_##_COLOR_) << ErrorInfo_ColorShift) | (ErrorReason_##_DESC_))
ErrorInfo_None = MAKE_ERROR_INFO(Black, None),
ErrorInfo_InvalidPackage2Signature = MAKE_ERROR_INFO(Blue, InvalidPackage2Signature),
ErrorInfo_InvalidPackage2Meta = MAKE_ERROR_INFO(Blue, InvalidPackage2Meta),
ErrorInfo_InvalidPackage2Version = MAKE_ERROR_INFO(Blue, InvalidPackage2Version),
ErrorInfo_InvalidPackage2Payload = MAKE_ERROR_INFO(Blue, InvalidPackage2Payload),
ErrorInfo_UnknownSmc = MAKE_ERROR_INFO(LightBlue, UnknownSmc),
ErrorInfo_UnknownAbort = MAKE_ERROR_INFO(Yellow, UnknownAbort),
ErrorInfo_InvalidCoreContext = MAKE_ERROR_INFO(Pink, InvalidCoreContext),
ErrorInfo_InvalidSecurityEngineStickyBits = MAKE_ERROR_INFO(Pink, InvalidSecurityEngineStickyBits),
ErrorInfo_UnexpectedReset = MAKE_ERROR_INFO(Pink, UnexpectedReset),
ErrorInfo_Exception = MAKE_ERROR_INFO(Orange, Exception),
ErrorInfo_TransitionToSafeMode = MAKE_ERROR_INFO(Black, TransitionToSafeMode),
ErrorInfo_SecureInitializerReboot = MAKE_ERROR_INFO(Black, SecureInitializerReboot),
ErrorInfo_SdmmcError = MAKE_ERROR_INFO(Purple, SdmmcError),
ErrorInfo_InvalidDramId = MAKE_ERROR_INFO(Purple, InvalidDramId),
ErrorInfo_InvalidPackage2 = MAKE_ERROR_INFO(Purple, InvalidPackage2),
ErrorInfo_InvalidBct = MAKE_ERROR_INFO(Purple, InvalidBct),
ErrorInfo_InvalidGpt = MAKE_ERROR_INFO(Purple, InvalidGpt),
ErrorInfo_FailedToTransitionToSafeMode = MAKE_ERROR_INFO(Purple, FailedToTransitionToSafeMode),
ErrorInfo_ActivityMonitorInterrupt = MAKE_ERROR_INFO(Purple, ActivityMonitorInterrupt),
#undef MAKE_ERROR_INFO
};
constexpr inline ErrorReason GetErrorReason(u32 info) {
return static_cast<ErrorReason>(info & ErrorInfo_ReasonMask);
}
constexpr inline ErrorInfo MakeKernelPanicResetInfo(u32 color) {
return static_cast<ErrorInfo>((color << ErrorInfo_ColorShift) | (ErrorReason_KernelPanic));
}
#define PKG1_SECURE_MONITOR_PMC_ERROR_SCRATCH (0x840)
}

View File

@ -0,0 +1,47 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::pkg1 {
enum KeyGeneration : int {
KeyGeneration_1_0_0 = 0x00,
KeyGeneration_3_0_0 = 0x01,
KeyGeneration_3_0_1 = 0x02,
KeyGeneration_4_0_0 = 0x03,
KeyGeneration_5_0_0 = 0x04,
KeyGeneration_6_0_0 = 0x05,
KeyGeneration_6_2_0 = 0x06,
KeyGeneration_7_0_0 = 0x07,
KeyGeneration_8_1_0 = 0x08,
KeyGeneration_9_0_0 = 0x09,
KeyGeneration_9_1_0 = 0x0A,
KeyGeneration_Count,
KeyGeneration_Current = KeyGeneration_Count - 1,
KeyGeneration_Min = 0x00,
KeyGeneration_Max = 0x20,
};
static_assert(KeyGeneration_Count <= KeyGeneration_Max);
constexpr inline const int OldMasterKeyCount = KeyGeneration_Count - 1;
constexpr inline const int OldDeviceMasterKeyCount = KeyGeneration_Count - KeyGeneration_4_0_0;
}

View File

@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::pkg1 {
enum AesKeySlot {
AesKeySlot_UserStart = 0,
AesKeySlot_TzramSave = 2,
AesKeySlot_UserLast = 5,
AesKeySlot_UserEnd = AesKeySlot_UserLast + 1,
AesKeySlot_SecmonStart = 8,
AesKeySlot_Temporary = 8,
AesKeySlot_Smc = 9,
AesKeySlot_RandomForUserWrap = 10,
AesKeySlot_RandomForKeyStorageWrap = 11,
AesKeySlot_DeviceMaster = 12,
AesKeySlot_Master = 13,
AesKeySlot_Device = 15,
AesKeySlot_SecmonEnd = 16,
/* Used only during boot. */
AesKeySlot_Tsec = 12,
AesKeySlot_TsecRoot = 13,
AesKeySlot_SecureBoot = 14,
AesKeySlot_SecureStorage = 15,
AesKeySlot_MasterKek = 13,
AesKeySlot_DeviceMasterKeySourceKek = 14,
};
enum RsaKeySlot {
RsaKeySlot_Temporary = 0,
RsaKeySlot_PrivateKey = 1,
};
}

View File

@ -0,0 +1,50 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::pmc {
enum SecureRegister {
SecureRegister_Other = (1 << 0),
SecureRegister_DramParameters = (1 << 1),
SecureRegister_ResetVector = (1 << 2),
SecureRegister_Carveout = (1 << 3),
SecureRegister_CmacWrite = (1 << 4),
SecureRegister_CmacRead = (1 << 5),
SecureRegister_KeySourceWrite = (1 << 6),
SecureRegister_KeySourceRead = (1 << 7),
SecureRegister_Srk = (1 << 8),
SecureRegister_CmacReadWrite = SecureRegister_CmacRead | SecureRegister_CmacWrite,
SecureRegister_KeySourceReadWrite = SecureRegister_KeySourceRead | SecureRegister_KeySourceWrite,
};
void SetRegisterAddress(uintptr_t address);
void InitializeRandomScratch();
void LockSecureRegister(SecureRegister reg);
enum class LockState {
Locked = 0,
NotLocked = 1,
PartiallyLocked = 2,
};
LockState GetSecureRegisterLockState(SecureRegister reg);
}

View File

@ -0,0 +1,33 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::pmic {
enum Regulator {
/* Erista regulators. */
Regulator_Erista_Max77621 = 0, /* Device code 0x3A000001 */
/* Mariko regulators. */
Regulator_Mariko_Max77812_A = 1, /* Device code 0x3A000002 */
Regulator_Mariko_Max77812_B = 2, /* Device code 0x3A000006 */
};
void EnableVddCpu(Regulator regulator);
void DisableVddCpu(Regulator regulator);
}

View File

@ -0,0 +1,205 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::reg {
using BitsValue = std::tuple<u32, u32, u32>;
using BitsMask = std::tuple<u32, u32>;
constexpr ALWAYS_INLINE u32 GetOffset(const BitsMask v) { return std::get<0>(v); }
constexpr ALWAYS_INLINE u32 GetOffset(const BitsValue v) { return std::get<0>(v); }
constexpr ALWAYS_INLINE u32 GetWidth(const BitsMask v) { return std::get<1>(v); }
constexpr ALWAYS_INLINE u32 GetWidth(const BitsValue v) { return std::get<1>(v); }
constexpr ALWAYS_INLINE u32 GetValue(const BitsValue v) { return std::get<2>(v); }
constexpr ALWAYS_INLINE u32 EncodeMask(const BitsMask v) {
return (~0u >> (BITSIZEOF(u32) - GetWidth(v))) << GetOffset(v);
}
constexpr ALWAYS_INLINE u32 EncodeMask(const BitsValue v) {
return (~0u >> (BITSIZEOF(u32) - GetWidth(v))) << GetOffset(v);
}
constexpr ALWAYS_INLINE u32 EncodeValue(const BitsValue v) {
return ((GetValue(v) << GetOffset(v)) & EncodeMask(v));
}
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
constexpr ALWAYS_INLINE u32 Encode(const Values... values) {
return (EncodeValue(values) | ...);
}
ALWAYS_INLINE void Write(volatile u32 *reg, u32 val) { *reg = val; }
ALWAYS_INLINE void Write(volatile u32 &reg, u32 val) { reg = val; }
ALWAYS_INLINE void Write(uintptr_t reg, u32 val) { Write(reinterpret_cast<volatile u32 *>(reg), val); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE void Write(volatile u32 *reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE void Write(volatile u32 &reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE void Write(uintptr_t reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
ALWAYS_INLINE u32 Read(volatile u32 *reg) { return *reg; }
ALWAYS_INLINE u32 Read(volatile u32 &reg) { return reg; }
ALWAYS_INLINE u32 Read(uintptr_t reg) { return Read(reinterpret_cast<volatile u32 *>(reg)); }
ALWAYS_INLINE u32 Read(volatile u32 *reg, u32 mask) { return *reg & mask; }
ALWAYS_INLINE u32 Read(volatile u32 &reg, u32 mask) { return reg & mask; }
ALWAYS_INLINE u32 Read(uintptr_t reg, u32 mask) { return Read(reinterpret_cast<volatile u32 *>(reg), mask); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE u32 Read(volatile u32 *reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE u32 Read(volatile u32 &reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE u32 Read(uintptr_t reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE bool HasValue(volatile u32 *reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE bool HasValue(volatile u32 &reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE bool HasValue(uintptr_t reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
ALWAYS_INLINE void ReadWrite(volatile u32 *reg, u32 val, u32 mask) { *reg = (*reg & (~mask)) | (val & mask); }
ALWAYS_INLINE void ReadWrite(volatile u32 &reg, u32 val, u32 mask) { reg = ( reg & (~mask)) | (val & mask); }
ALWAYS_INLINE void ReadWrite(uintptr_t reg, u32 val, u32 mask) { ReadWrite(reinterpret_cast<volatile u32 *>(reg), val, mask); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE void ReadWrite(volatile u32 *reg, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE void ReadWrite(volatile u32 &reg, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
ALWAYS_INLINE void ReadWrite(uintptr_t reg, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
ALWAYS_INLINE void SetBits(volatile u32 *reg, u32 mask) { *reg = *reg | mask; }
ALWAYS_INLINE void SetBits(volatile u32 &reg, u32 mask) { reg = reg | mask; }
ALWAYS_INLINE void SetBits(uintptr_t reg, u32 mask) { SetBits(reinterpret_cast<volatile u32 *>(reg), mask); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void SetBits(volatile u32 *reg, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void SetBits(volatile u32 &reg, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void SetBits(uintptr_t reg, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
ALWAYS_INLINE void ClearBits(volatile u32 *reg, u32 mask) { *reg = *reg & ~mask; }
ALWAYS_INLINE void ClearBits(volatile u32 &reg, u32 mask) { reg = reg & ~mask; }
ALWAYS_INLINE void ClearBits(uintptr_t reg, u32 mask) { ClearBits(reinterpret_cast<volatile u32 *>(reg), mask); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void ClearBits(volatile u32 *reg, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void ClearBits(volatile u32 &reg, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void ClearBits(uintptr_t reg, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
ALWAYS_INLINE void MaskBits(volatile u32 *reg, u32 mask) { *reg = *reg & mask; }
ALWAYS_INLINE void MaskBits(volatile u32 &reg, u32 mask) { reg = reg & mask; }
ALWAYS_INLINE void MaskBits(uintptr_t reg, u32 mask) { MaskBits(reinterpret_cast<volatile u32 *>(reg), mask); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void MaskBits(volatile u32 *reg, const Masks... masks) { return MaskBits(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void MaskBits(volatile u32 &reg, const Masks... masks) { return MaskBits(reg, (EncodeMask(masks) | ...)); }
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
ALWAYS_INLINE void MaskBits(uintptr_t reg, const Masks... masks) { return MaskBits(reg, (EncodeMask(masks) | ...)); }
#define REG_BITS_MASK(OFFSET, WIDTH) ::ams::reg::BitsMask{OFFSET, WIDTH}
#define REG_BITS_VALUE(OFFSET, WIDTH, VALUE) ::ams::reg::BitsValue{OFFSET, WIDTH, VALUE}
#define REG_NAMED_BITS_MASK(PREFIX, NAME) REG_BITS_MASK(PREFIX##_##NAME##_OFFSET, PREFIX##_##NAME##_WIDTH)
#define REG_NAMED_BITS_VALUE(PREFIX, NAME, VALUE) REG_BITS_VALUE(PREFIX##_##NAME##_OFFSET, PREFIX##_##NAME##_WIDTH, VALUE)
#define REG_NAMED_BITS_ENUM(PREFIX, NAME, ENUM) REG_BITS_VALUE(PREFIX##_##NAME##_OFFSET, PREFIX##_##NAME##_WIDTH, PREFIX##_##NAME##_##ENUM)
#define REG_NAMED_BITS_ENUM_SEL(PREFIX, NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_BITS_VALUE(PREFIX##_##NAME##_OFFSET, PREFIX##_##NAME##_WIDTH, (__COND__) ? PREFIX##_##NAME##_##TRUE_ENUM : PREFIX##_##NAME##_##FALSE_ENUM)
#define REG_DEFINE_NAMED_REG(PREFIX, NAME, __OFFSET__, __WIDTH__) \
constexpr inline u32 PREFIX##_##NAME##_OFFSET = __OFFSET__; \
constexpr inline u32 PREFIX##_##NAME##_WIDTH = __WIDTH__
#define REG_DEFINE_NAMED_BIT_ENUM(PREFIX, NAME, __OFFSET__, ZERO, ONE) \
REG_DEFINE_NAMED_REG(PREFIX, NAME, __OFFSET__, 1); \
\
enum PREFIX##_##NAME { \
PREFIX##_##NAME##_##ZERO = 0, \
PREFIX##_##NAME##_##ONE = 1, \
};
#define REG_DEFINE_NAMED_TWO_BIT_ENUM(PREFIX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE) \
REG_DEFINE_NAMED_REG(PREFIX, NAME, __OFFSET__, 2); \
\
enum PREFIX##_##NAME { \
PREFIX##_##NAME##_##ZERO = 0, \
PREFIX##_##NAME##_##ONE = 1, \
PREFIX##_##NAME##_##TWO = 2, \
PREFIX##_##NAME##_##THREE = 3, \
};
#define REG_DEFINE_NAMED_THREE_BIT_ENUM(PREFIX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) \
REG_DEFINE_NAMED_REG(PREFIX, NAME, __OFFSET__, 3); \
\
enum PREFIX##_##NAME { \
PREFIX##_##NAME##_##ZERO = 0, \
PREFIX##_##NAME##_##ONE = 1, \
PREFIX##_##NAME##_##TWO = 2, \
PREFIX##_##NAME##_##THREE = 3, \
PREFIX##_##NAME##_##FOUR = 4, \
PREFIX##_##NAME##_##FIVE = 5, \
PREFIX##_##NAME##_##SIX = 6, \
PREFIX##_##NAME##_##SEVEN = 7, \
};
#define REG_DEFINE_NAMED_FOUR_BIT_ENUM(PREFIX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) \
REG_DEFINE_NAMED_REG(PREFIX, NAME, __OFFSET__, 4); \
\
enum PREFIX##_##NAME { \
PREFIX##_##NAME##_##ZERO = 0, \
PREFIX##_##NAME##_##ONE = 1, \
PREFIX##_##NAME##_##TWO = 2, \
PREFIX##_##NAME##_##THREE = 3, \
PREFIX##_##NAME##_##FOUR = 4, \
PREFIX##_##NAME##_##FIVE = 5, \
PREFIX##_##NAME##_##SIX = 6, \
PREFIX##_##NAME##_##SEVEN = 7, \
PREFIX##_##NAME##_##EIGHT = 8, \
PREFIX##_##NAME##_##NINE = 9, \
PREFIX##_##NAME##_##TEN = 10, \
PREFIX##_##NAME##_##ELEVEN = 11, \
PREFIX##_##NAME##_##TWELVE = 12, \
PREFIX##_##NAME##_##THIRTEEN = 13, \
PREFIX##_##NAME##_##FOURTEEN = 14, \
PREFIX##_##NAME##_##FIFTEEN = 15, \
};
}

View File

@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/se/se_common.hpp>
#include <exosphere/se/se_management.hpp>
#include <exosphere/se/se_aes.hpp>
#include <exosphere/se/se_rsa.hpp>
#include <exosphere/se/se_rng.hpp>
#include <exosphere/se/se_suspend.hpp>

View File

@ -0,0 +1,36 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/se/se_common.hpp>
namespace ams::se {
constexpr inline int AesKeySlotCount = 16;
constexpr inline size_t AesBlockSize = crypto::AesEncryptor128::BlockSize;
void ClearAesKeySlot(int slot);
void LockAesKeySlot(int slot, u32 flags);
void SetAesKey(int slot, const void *key, size_t key_size);
void SetEncryptedAesKey128(int dst_slot, int kek_slot, const void *key, size_t key_size);
void SetEncryptedAesKey256(int dst_slot, int kek_slot, const void *key, size_t key_size);
void EncryptAes128(void *dst, size_t dst_size, int slot, const void *src, size_t src_size);
void DecryptAes128(void *dst, size_t dst_size, int slot, const void *src, size_t src_size);
}

View File

@ -0,0 +1,53 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::secmon {
u8 *GetSecurityEngineEphemeralWorkBlock();
}
namespace ams::se {
using DoneHandler = void(*)();
enum KeySlotLockFlags {
KeySlotLockFlags_None = 0,
KeySlotLockFlags_KeyRead = (1u << 0),
KeySlotLockFlags_KeyWrite = (1u << 1),
KeySlotLockFlags_OriginalIvRead = (1u << 2),
KeySlotLockFlags_OriginalIvWrite = (1u << 3),
KeySlotLockFlags_UpdatedIvRead = (1u << 4),
KeySlotLockFlags_UpdatedIvWrite = (1u << 5),
KeySlotLockFlags_KeyUse = (1u << 6),
KeySlotLockFlags_DstKeyTableOnly = (1u << 7),
KeySlotLockFlags_PerKey = (1u << 8),
KeySlotLockFlags_AllReadLock = (KeySlotLockFlags_KeyRead | KeySlotLockFlags_OriginalIvRead | KeySlotLockFlags_UpdatedIvRead),
KeySlotLockFlags_AllLockKek = 0x1FF,
KeySlotLockFlags_AllLockKey = (KeySlotLockFlags_AllLockKek & ~KeySlotLockFlags_DstKeyTableOnly),
KeySlotLockFlags_EristaMask = 0x7F,
KeySlotLockFlags_MarikoMask = 0xFF,
};
ALWAYS_INLINE u8 *GetEphemeralWorkBlock() {
return ::ams::secmon::GetSecurityEngineEphemeralWorkBlock();
}
}

View File

@ -0,0 +1,33 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::se {
void SetRegisterAddress(uintptr_t address);
void Initialize();
void SetSecure(bool secure);
void SetTzramSecure();
void SetPerKeySecure();
void Lockout();
void HandleInterrupt();
}

View File

@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::se {
void InitializeRandom();
void GenerateRandomBytes(void *dst, size_t size);
void SetRandomKey(int slot);
void GenerateSrk();
}

View File

@ -0,0 +1,29 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::se {
constexpr inline int RsaKeySlotCount = 2;
constexpr inline int RsaSize = 0x100;
void ClearRsaKeySlot(int slot);
void LockRsaKeySlot(int slot, u32 flags);
void SetRsaKey(int slot, const void *mod, size_t mod_size, const void *exp, size_t exp_size);
}

View File

@ -0,0 +1,55 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/se/se_aes.hpp>
#include <exosphere/se/se_rsa.hpp>
namespace ams::se {
/* 256-bit AES keyslots are two 128-bit keys. */
constexpr inline int AesKeySlotPartCount = 2;
/* RSA keys are both a modulus and an exponent. */
constexpr inline int RsaKeySlotPartCount = 2;
constexpr inline size_t StickyBitContextSize = 2 * AesBlockSize;
struct Context {
u8 random[AesBlockSize];
u8 sticky_bits[StickyBitContextSize / AesBlockSize][AesBlockSize];
u8 aes_key[AesKeySlotCount][AesKeySlotPartCount][AesBlockSize];
u8 aes_oiv[AesKeySlotCount][AesBlockSize];
u8 aes_uiv[AesKeySlotCount][AesBlockSize];
u8 rsa_key[RsaKeySlotCount][RsaKeySlotPartCount][RsaSize / AesBlockSize][AesBlockSize];
u8 fixed_pattern[AesBlockSize];
};
static_assert(sizeof(Context) == 0x840);
static_assert(util::is_pod<Context>::value);
struct StickyBits {
u8 se_security;
u8 tzram_security;
u16 crypto_security_perkey;
u8 crypto_keytable_access[AesKeySlotCount];
u8 rsa_security_perkey;
u8 rsa_keytable_access[RsaKeySlotCount];
};
static_assert(util::is_pod<StickyBits>::value);
bool ValidateStickyBits(const StickyBits &bits);
}

View File

@ -0,0 +1,20 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/secmon/secmon_memory_layout.hpp>
#include <exosphere/secmon/secmon_configuration_context.hpp>
#include <exosphere/secmon/secmon_volatile_context.hpp>

View File

@ -0,0 +1,99 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/pkg1.hpp>
#include <exosphere/se.hpp>
#include <exosphere/secmon/secmon_monitor_context.hpp>
namespace ams::secmon {
struct ConfigurationContext {
union {
SecureMonitorConfiguration secmon_cfg;
u8 _raw_exosphere_config[0x80];
};
union {
EmummcConfiguration emummc_cfg;
u8 _raw_emummc_config[0x120];
};
union {
u8 _misc_data[0x400 - sizeof(_raw_exosphere_config) - sizeof(_raw_emummc_config)];
};
u8 sealed_device_keys[pkg1::KeyGeneration_Max][se::AesBlockSize];
u8 sealed_master_keys[pkg1::KeyGeneration_Max][se::AesBlockSize];
pkg1::BootConfig boot_config;
u8 rsa_private_exponents[4][se::RsaSize];
};
static_assert(sizeof(ConfigurationContext) == 0x1000);
static_assert(util::is_pod<ConfigurationContext>::value);
static_assert(offsetof(ConfigurationContext, sealed_device_keys) == 0x400);
namespace impl {
ALWAYS_INLINE uintptr_t GetConfigurationContextAddress() {
register uintptr_t x18 asm("x18");
__asm__ __volatile__("" : [x18]"=r"(x18));
return x18;
}
ALWAYS_INLINE ConfigurationContext &GetConfigurationContext() {
return *reinterpret_cast<ConfigurationContext *>(GetConfigurationContextAddress());
}
ALWAYS_INLINE u8 *GetMasterKeyStorage(int generation) {
return GetConfigurationContext().sealed_master_keys[generation];
}
ALWAYS_INLINE u8 *GetDeviceMasterKeyStorage(int generation) {
return GetConfigurationContext().sealed_device_keys[generation];
}
ALWAYS_INLINE u8 *GetRsaPrivateExponentStorage(int which) {
return GetConfigurationContext().rsa_private_exponents[which];
}
ALWAYS_INLINE void SetKeyGeneration(int generation) {
GetConfigurationContext().secmon_cfg.key_generation = generation;
}
}
ALWAYS_INLINE const ConfigurationContext &GetConfigurationContext() {
return *reinterpret_cast<const ConfigurationContext *>(impl::GetConfigurationContextAddress());
}
ALWAYS_INLINE const SecureMonitorConfiguration &GetSecmonConfiguration() {
return GetConfigurationContext().secmon_cfg;
}
ALWAYS_INLINE const EmummcConfiguration &GetEmummcConfiguration() {
return GetConfigurationContext().emummc_cfg;
}
ALWAYS_INLINE const pkg1::BootConfig &GetBootConfig() {
return GetConfigurationContext().boot_config;
}
ALWAYS_INLINE ams::TargetFirmware GetTargetFirmware() {
return GetSecmonConfiguration().GetTargetFirmware();
}
ALWAYS_INLINE int GetKeyGeneration() {
return GetSecmonConfiguration().GetKeyGeneration();
}
}

View File

@ -0,0 +1,25 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#if defined(ATMOSPHERE_ARCH_ARM64)
#include <exosphere/secmon/secmon_configuration_context.arch.arm64.hpp>
#elif defined(ATMOSPHERE_ARCH_ARM)
/* Nothing to include. */
#else
#error "Unknown architecture for secmon::ConfigurationContext.hpp"
#endif

View File

@ -0,0 +1,73 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::secmon {
enum EmummcType : u32 {
EmummcType_None = 0,
EmummcType_Partition = 1,
EmummcType_File = 2,
};
enum EmummcMmc {
EmummcMmc_Nand = 0,
EmummcMmc_Sd = 1,
EmummcMmc_Gc = 2,
};
constexpr inline size_t EmummcFilePathLengthMax = 0x80;
struct EmummcFilePath {
char str[EmummcFilePathLengthMax];
};
static_assert(util::is_pod<EmummcFilePath>::value);
static_assert(sizeof(EmummcFilePath) == EmummcFilePathLengthMax);
struct EmummcBaseConfiguration {
static constexpr u32 Magic = util::FourCC<'E','F','S','0'>::Code;
u32 magic;
EmummcType type;
u32 id;
u32 fs_version;
};
static_assert(util::is_pod<EmummcBaseConfiguration>::value);
static_assert(sizeof(EmummcBaseConfiguration) == 0x10);
struct EmummcPartitionConfiguration {
u64 start_sector;
};
static_assert(util::is_pod<EmummcPartitionConfiguration>::value);
struct EmummcFileConfiguration {
EmummcFilePath path;
};
static_assert(util::is_pod<EmummcFileConfiguration>::value);
struct EmummcConfiguration {
EmummcBaseConfiguration base_cfg;
union {
EmummcPartitionConfiguration partition_cfg;
EmummcFileConfiguration file_cfg;
};
EmummcFilePath emu_dir_path;
};
static_assert(util::is_pod<EmummcConfiguration>::value);
static_assert(sizeof(EmummcConfiguration) <= 0x200);
}

View File

@ -0,0 +1,277 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/mmu.hpp>
namespace ams::secmon {
using Address = u64;
struct MemoryRegion {
Address start_address;
Address end_address;
constexpr MemoryRegion(Address address, size_t size) : start_address(address), end_address(address + size) {
if (end_address < start_address) {
__builtin_unreachable();
}
}
constexpr Address GetStartAddress() const {
return this->start_address;
}
constexpr Address GetAddress() const {
return this->GetStartAddress();
}
constexpr Address GetEndAddress() const {
return this->end_address;
}
constexpr Address GetLastAddress() const {
return this->end_address - 1;
}
constexpr size_t GetSize() const {
return this->end_address - this->start_address;
}
constexpr bool Contains(Address address, size_t size) const {
return this->start_address <= address && (address + size - 1) <= this->GetLastAddress();
}
constexpr bool Contains(const MemoryRegion &rhs) const {
return this->Contains(rhs.GetStartAddress(), rhs.GetSize());
}
template<typename T = void> requires (std::is_same<T, void>::value || util::is_pod<T>::value)
ALWAYS_INLINE T *GetPointer() const {
return reinterpret_cast<T *>(this->GetAddress());
}
template<typename T = void> requires (std::is_same<T, void>::value || util::is_pod<T>::value)
ALWAYS_INLINE T *GetEndPointer() const {
return reinterpret_cast<T *>(this->GetEndAddress());
}
};
constexpr inline const MemoryRegion MemoryRegionVirtual = MemoryRegion(UINT64_C(0x1F0000000), 2_MB);
constexpr inline const MemoryRegion MemoryRegionPhysical = MemoryRegion(UINT64_C( 0x40000000), 1_GB);
constexpr inline const MemoryRegion MemoryRegionDram = MemoryRegion(UINT64_C( 0x80000000), 2_GB);
constexpr inline const MemoryRegion MemoryRegionDramDefaultKernelCarveout = MemoryRegion(UINT64_C(0x80060000), UINT64_C(0x1FFE0000));
static_assert(MemoryRegionDram.Contains(MemoryRegionDramDefaultKernelCarveout));
constexpr inline const MemoryRegion MemoryRegionPhysicalIram = MemoryRegion(UINT64_C(0x40000000), 0x40000);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzram = MemoryRegion(UINT64_C(0x7C010000), 0x10000);
static_assert(MemoryRegionPhysical.Contains(MemoryRegionPhysicalIram));
static_assert(MemoryRegionPhysical.Contains(MemoryRegionPhysicalTzram));
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramVolatile(UINT64_C(0x7C010000), 0x2000);
static_assert(MemoryRegionPhysicalTzram.Contains(MemoryRegionPhysicalTzramVolatile));
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramNonVolatile(UINT64_C(0x7C012000), 0xE000);
static_assert(MemoryRegionPhysicalTzram.Contains(MemoryRegionPhysicalTzramNonVolatile));
static_assert(MemoryRegionPhysicalTzram.GetSize() == MemoryRegionPhysicalTzramNonVolatile.GetSize() + MemoryRegionPhysicalTzramVolatile.GetSize());
constexpr inline const MemoryRegion MemoryRegionVirtualL1 = MemoryRegion(util::AlignDown(MemoryRegionVirtual.GetAddress(), mmu::L1EntrySize), mmu::L1EntrySize);
constexpr inline const MemoryRegion MemoryRegionPhysicalL1 = MemoryRegion(util::AlignDown(MemoryRegionPhysical.GetAddress(), mmu::L1EntrySize), mmu::L1EntrySize);
static_assert(MemoryRegionVirtualL1.Contains(MemoryRegionVirtual));
static_assert(MemoryRegionPhysicalL1.Contains(MemoryRegionPhysical));
constexpr inline const MemoryRegion MemoryRegionVirtualL2 = MemoryRegion(util::AlignDown(MemoryRegionVirtual.GetAddress(), mmu::L2EntrySize), mmu::L2EntrySize);
constexpr inline const MemoryRegion MemoryRegionPhysicalIramL2 = MemoryRegion(util::AlignDown(MemoryRegionPhysicalIram.GetAddress(), mmu::L2EntrySize), mmu::L2EntrySize);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramL2 = MemoryRegion(util::AlignDown(MemoryRegionPhysicalTzram.GetAddress(), mmu::L2EntrySize), mmu::L2EntrySize);
static_assert(MemoryRegionVirtualL2.Contains(MemoryRegionVirtual));
static_assert(MemoryRegionPhysicalIramL2.Contains(MemoryRegionPhysicalIram));
static_assert(MemoryRegionPhysicalTzramL2.Contains(MemoryRegionPhysicalTzram));
constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootCode = MemoryRegion(UINT64_C(0x40020000), 0x20000);
static_assert(MemoryRegionPhysicalIram.Contains(MemoryRegionPhysicalIramBootCode));
constexpr inline const MemoryRegion MemoryRegionVirtualDevice = MemoryRegion(UINT64_C(0x1F0040000), UINT64_C(0x40000));
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualDevice));
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceEmpty = MemoryRegion(MemoryRegionVirtualDevice.GetStartAddress(), 0);
#define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \
HANDLER(GicDistributor, Empty, UINT64_C(0x50041000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(GicCpuInterface, GicDistributor, UINT64_C(0x50042000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
HANDLER(Uart, GicCpuInterface, UINT64_C(0x70006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
HANDLER(ClkRst, Uart, UINT64_C(0x60006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
HANDLER(RtcPmc, ClkRst, UINT64_C(0x7000E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(Timer, RtcPmc, UINT64_C(0x60005000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(System, Timer, UINT64_C(0x6000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(SecurityEngine, System, UINT64_C(0x70012000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
HANDLER(SecurityEngine2, SecurityEngine, UINT64_C(0x70412000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
HANDLER(SysCtr0, SecurityEngine2, UINT64_C(0x700F0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController, SysCtr0, UINT64_C(0x70019000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(FuseKFuse, MemoryController, UINT64_C(0x7000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(ApbMisc, FuseKFuse, UINT64_C(0x70000000), UINT64_C(0x4000), true, ## __VA_ARGS__) \
HANDLER(FlowController, ApbMisc, UINT64_C(0x60007000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(BootloaderParams, FlowController, UINT64_C(0x40000000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(I2c5, BootloaderParams, UINT64_C(0x7000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(Gpio, I2c5, UINT64_C(0x6000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(I2c1, Gpio, UINT64_C(0x7000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__)
#define DEFINE_DEVICE_REGION(_NAME_, _PREV_, _ADDRESS_, _SIZE_, _SECURE_) \
constexpr inline const MemoryRegion MemoryRegionVirtualDevice##_NAME_ = MemoryRegion(MemoryRegionVirtualDevice##_PREV_.GetEndAddress() + 0x1000, _SIZE_); \
constexpr inline const MemoryRegion MemoryRegionPhysicalDevice##_NAME_ = MemoryRegion(_ADDRESS_, _SIZE_); \
static_assert(MemoryRegionVirtualDevice.Contains(MemoryRegionVirtualDevice##_NAME_)); \
static_assert(MemoryRegionPhysical.Contains(MemoryRegionPhysicalDevice##_NAME_));
AMS_SECMON_FOREACH_DEVICE_REGION(DEFINE_DEVICE_REGION)
#undef DEFINE_DEVICE_REGION
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceFuses = MemoryRegion(MemoryRegionVirtualDeviceFuseKFuse.GetAddress() + 0x800, 0x400);
constexpr inline const MemoryRegion MemoryRegionPhysicalDeviceFuses = MemoryRegion(MemoryRegionPhysicalDeviceFuseKFuse.GetAddress() + 0x800, 0x400);
static_assert(MemoryRegionVirtualDeviceFuseKFuse.Contains(MemoryRegionVirtualDeviceFuses));
static_assert(MemoryRegionPhysicalDeviceFuseKFuse.Contains(MemoryRegionPhysicalDeviceFuses));
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceActivityMonitor = MemoryRegion(MemoryRegionVirtualDeviceSystem.GetAddress() + 0x800, 0x400);
constexpr inline const MemoryRegion MemoryRegionPhysicalDeviceActivityMonitor = MemoryRegion(MemoryRegionPhysicalDeviceSystem.GetAddress() + 0x800, 0x400);
static_assert(MemoryRegionVirtualDeviceSystem.Contains(MemoryRegionVirtualDeviceActivityMonitor));
static_assert(MemoryRegionPhysicalDeviceSystem.Contains(MemoryRegionPhysicalDeviceActivityMonitor));
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceUartA = MemoryRegion(MemoryRegionVirtualDeviceUart.GetAddress() + 0x000, 0x040);
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceUartB = MemoryRegion(MemoryRegionVirtualDeviceUart.GetAddress() + 0x040, 0x040);
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceUartC = MemoryRegion(MemoryRegionVirtualDeviceUart.GetAddress() + 0x200, 0x100);
static_assert(MemoryRegionVirtualDeviceUart.Contains(MemoryRegionVirtualDeviceUartA));
static_assert(MemoryRegionVirtualDeviceUart.Contains(MemoryRegionVirtualDeviceUartB));
static_assert(MemoryRegionVirtualDeviceUart.Contains(MemoryRegionVirtualDeviceUartC));
constexpr inline const MemoryRegion MemoryRegionPhysicalDeviceUartA = MemoryRegion(MemoryRegionPhysicalDeviceUart.GetAddress() + 0x000, 0x040);
constexpr inline const MemoryRegion MemoryRegionPhysicalDeviceUartB = MemoryRegion(MemoryRegionPhysicalDeviceUart.GetAddress() + 0x040, 0x040);
constexpr inline const MemoryRegion MemoryRegionPhysicalDeviceUartC = MemoryRegion(MemoryRegionPhysicalDeviceUart.GetAddress() + 0x200, 0x100);
static_assert(MemoryRegionPhysicalDeviceUart.Contains(MemoryRegionPhysicalDeviceUartA));
static_assert(MemoryRegionPhysicalDeviceUart.Contains(MemoryRegionPhysicalDeviceUartB));
static_assert(MemoryRegionPhysicalDeviceUart.Contains(MemoryRegionPhysicalDeviceUartC));
constexpr inline const MemoryRegion MemoryRegionVirtualDevicePmc = MemoryRegion(MemoryRegionVirtualDeviceRtcPmc.GetAddress() + 0x400, 0xC00);
constexpr inline const MemoryRegion MemoryRegionPhysicalDevicePmc = MemoryRegion(MemoryRegionPhysicalDeviceRtcPmc.GetAddress() + 0x400, 0xC00);
static_assert(MemoryRegionVirtualDeviceRtcPmc.Contains(MemoryRegionVirtualDevicePmc));
static_assert(MemoryRegionPhysicalDeviceRtcPmc.Contains(MemoryRegionPhysicalDevicePmc));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramReadOnlyAlias = MemoryRegion(UINT64_C(0x1F00A0000), MemoryRegionPhysicalTzram.GetSize());
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramReadOnlyAlias = MemoryRegion(MemoryRegionPhysicalTzram.GetAddress(), MemoryRegionPhysicalTzram.GetSize());
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramReadOnlyAlias));
static_assert(MemoryRegionPhysicalTzram.Contains(MemoryRegionPhysicalTzramReadOnlyAlias));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramProgram(UINT64_C(0x1F00C0000), 0xC000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramProgram));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramProgramExceptionVectors(UINT64_C(0x1F00C0000), 0x800);
static_assert(MemoryRegionVirtualTzramProgram.Contains(MemoryRegionVirtualTzramProgramExceptionVectors));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramProgramMain(UINT64_C(0x1F00C0800), 0xB800);
static_assert(MemoryRegionVirtualTzramProgram.Contains(MemoryRegionVirtualTzramProgramMain));
static_assert(MemoryRegionVirtualTzramProgram.GetSize() == MemoryRegionVirtualTzramProgramExceptionVectors.GetSize() + MemoryRegionVirtualTzramProgramMain.GetSize());
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramProgram(UINT64_C(0x7C012000), 0xC000);
static_assert(MemoryRegionPhysicalTzramNonVolatile.Contains(MemoryRegionPhysicalTzramProgram));
constexpr inline const Address PhysicalTzramProgramResetVector = MemoryRegionPhysicalTzramProgram.GetAddress() + MemoryRegionVirtualTzramProgramExceptionVectors.GetSize();
static_assert(static_cast<u32>(PhysicalTzramProgramResetVector) == PhysicalTzramProgramResetVector);
constexpr uintptr_t GetPhysicalTzramProgramAddress(uintptr_t virtual_address) {
return virtual_address - MemoryRegionVirtualTzramProgram.GetStartAddress() + MemoryRegionPhysicalTzramNonVolatile.GetStartAddress();
}
constexpr inline const MemoryRegion MemoryRegionVirtualIramSc7Work = MemoryRegion(UINT64_C(0x1F0120000), MemoryRegionPhysicalTzram.GetSize());
constexpr inline const MemoryRegion MemoryRegionPhysicalIramSc7Work = MemoryRegion( UINT64_C(0x40020000), MemoryRegionPhysicalTzram.GetSize());
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualIramSc7Work));
static_assert(MemoryRegionPhysicalIram.Contains(MemoryRegionPhysicalIramSc7Work));
constexpr inline const MemoryRegion MemoryRegionVirtualIramSc7Firmware = MemoryRegion(UINT64_C(0x1F0140000), 0x1000);
constexpr inline const MemoryRegion MemoryRegionPhysicalIramSc7Firmware = MemoryRegion( UINT64_C(0x40003000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualIramSc7Firmware));
static_assert(MemoryRegionPhysicalIram.Contains(MemoryRegionPhysicalIramSc7Firmware));
constexpr inline const MemoryRegion MemoryRegionVirtualDebug = MemoryRegion(UINT64_C(0x1F0160000), 0x10000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualIramSc7Firmware));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramBootCode = MemoryRegion(UINT64_C(0x1F01C0000), 0x2000);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramBootCode = MemoryRegion( UINT64_C(0x7C010000), 0x2000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramBootCode));
static_assert(MemoryRegionPhysicalTzramVolatile.Contains(MemoryRegionPhysicalTzramBootCode));
constexpr inline const MemoryRegion MemoryRegionPhysicalDramMonitorConfiguration = MemoryRegion( UINT64_C(0x8000F000), 0x1000);
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStore = MemoryRegion(UINT64_C(0x1F0100000), 0x10000);
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSecureDataStore = MemoryRegion( UINT64_C(0x80010000), 0x10000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualDramSecureDataStore));
static_assert(MemoryRegionDram.Contains(MemoryRegionPhysicalDramSecureDataStore));
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStoreTzram = MemoryRegion(UINT64_C(0x1F0100000), 0xE000);
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStoreWarmbootFirmware = MemoryRegion(UINT64_C(0x1F010E000), 0x17C0);
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStoreSecurityEngineState = MemoryRegion(UINT64_C(0x1F010F7C0), 0x0840);
static_assert(MemoryRegionVirtualDramSecureDataStore.Contains(MemoryRegionVirtualDramSecureDataStoreTzram));
static_assert(MemoryRegionVirtualDramSecureDataStore.Contains(MemoryRegionVirtualDramSecureDataStoreWarmbootFirmware));
static_assert(MemoryRegionVirtualDramSecureDataStore.Contains(MemoryRegionVirtualDramSecureDataStoreSecurityEngineState));
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSecureDataStoreTzram = MemoryRegion(UINT64_C(0x80010000), 0xE000);
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware = MemoryRegion(UINT64_C(0x8001E000), 0x17C0);
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSecureDataStoreSecurityEngineState = MemoryRegion(UINT64_C(0x8001F7C0), 0x0840);
static_assert(MemoryRegionPhysicalDramSecureDataStore.Contains(MemoryRegionPhysicalDramSecureDataStoreTzram));
static_assert(MemoryRegionPhysicalDramSecureDataStore.Contains(MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware));
static_assert(MemoryRegionPhysicalDramSecureDataStore.Contains(MemoryRegionPhysicalDramSecureDataStoreSecurityEngineState));
constexpr inline const MemoryRegion MemoryRegionVirtualAtmosphereIramPage = MemoryRegion(UINT64_C(0x1F01F0000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualAtmosphereIramPage));
constexpr inline const MemoryRegion MemoryRegionVirtualAtmosphereUserPage = MemoryRegion(UINT64_C(0x1F01F2000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualAtmosphereUserPage));
constexpr inline const MemoryRegion MemoryRegionVirtualSmcUserPage = MemoryRegion(UINT64_C(0x1F01F4000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualSmcUserPage));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramVolatileData = MemoryRegion(UINT64_C(0x1F01F6000), 0x1000);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramVolatileData = MemoryRegion( UINT64_C(0x7C010000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramVolatileData));
static_assert(MemoryRegionPhysicalTzramVolatile.Contains(MemoryRegionPhysicalTzramVolatileData));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramVolatileStack = MemoryRegion(UINT64_C(0x1F01F8000), 0x1000);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramVolatileStack = MemoryRegion( UINT64_C(0x7C011000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramVolatileStack));
static_assert(MemoryRegionPhysicalTzramVolatile.Contains(MemoryRegionPhysicalTzramVolatileStack));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramConfigurationData = MemoryRegion(UINT64_C(0x1F01FA000), 0x1000);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramConfigurationData = MemoryRegion( UINT64_C(0x7C01E000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramConfigurationData));
static_assert(MemoryRegionPhysicalTzramNonVolatile.Contains(MemoryRegionPhysicalTzramConfigurationData));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramL1PageTable = MemoryRegion(UINT64_C(0x1F01FCFC0), 0x40);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramL1PageTable = MemoryRegion( UINT64_C(0x7C01EFC0), 0x40);
static_assert(MemoryRegionPhysicalTzramConfigurationData.Contains(MemoryRegionPhysicalTzramL1PageTable));
constexpr inline const MemoryRegion MemoryRegionVirtualTzramL2L3PageTable = MemoryRegion(UINT64_C(0x1F01FE000), 0x1000);
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramL2L3PageTable = MemoryRegion( UINT64_C(0x7C01F000), 0x1000);
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramL2L3PageTable));
static_assert(MemoryRegionPhysicalTzramNonVolatile.Contains(MemoryRegionPhysicalTzramL2L3PageTable));
constexpr inline const MemoryRegion MemoryRegionPhysicalTzramFullProgramImage = MemoryRegion(0x7C010800, 0xD800);
constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootCodeImage = MemoryRegion(0x40032000, 0xC000);
}

View File

@ -0,0 +1,77 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/secmon/secmon_emummc_context.hpp>
namespace ams::secmon {
enum SecureMonitorConfigurationFlag : u32 {
SecureMonitorConfigurationFlag_None = (0u << 0),
SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel = (1u << 1),
SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForUser = (1u << 2),
SecureMonitorConfigurationFlag_DisableUserModeExceptionHandlers = (1u << 3),
SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess = (1u << 4),
SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5),
SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6),
SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel,
};
struct SecureMonitorStorageConfiguration {
static constexpr u32 Magic = util::FourCC<'E','X','O','0'>::Code;
u32 magic;
ams::TargetFirmware target_firmware;
u32 flags;
u32 reserved[5];
EmummcConfiguration emummc_cfg;
constexpr bool IsValid() const { return this->magic == Magic; }
};
static_assert(util::is_pod<SecureMonitorStorageConfiguration>::value);
static_assert(sizeof(SecureMonitorStorageConfiguration) == 0x130);
struct SecureMonitorConfiguration {
ams::TargetFirmware target_firmware;
s32 key_generation;
u32 flags;
u32 reserved[(0x80 - 0x0C) / sizeof(u32)];
constexpr void CopyFrom(const SecureMonitorStorageConfiguration &storage) {
this->target_firmware = storage.target_firmware;
this->flags = storage.flags;
}
constexpr ams::TargetFirmware GetTargetFirmware() const { return this->target_firmware; }
constexpr int GetKeyGeneration() const { return this->key_generation; }
constexpr bool IsDevelopmentFunctionEnabledForKernel() const { return (this->flags & SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel) != 0; }
constexpr bool IsDevelopmentFunctionEnabledForUser() const { return (this->flags & SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForUser) != 0; }
constexpr bool DisableUserModeExceptionHandlers() const { return (this->flags & SecureMonitorConfigurationFlag_DisableUserModeExceptionHandlers) != 0; }
constexpr bool EnableUserModePerformanceCounterAccess() const { return (this->flags & SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess) != 0; }
constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; }
constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; }
};
static_assert(util::is_pod<SecureMonitorConfiguration>::value);
static_assert(sizeof(SecureMonitorConfiguration) == 0x80);
constexpr inline const SecureMonitorConfiguration DefaultSecureMonitorConfiguration = {
.target_firmware = ams::TargetFirmware_Current,
.flags = SecureMonitorConfigurationFlag_Default,
};
}

View File

@ -0,0 +1,62 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::secmon {
/* The VolatileStack page is reserved entirely for use for core 3 SMC handling. */
constexpr inline const Address Core3SmcStackAddress = MemoryRegionVirtualTzramVolatileStack.GetAddress() + MemoryRegionVirtualTzramVolatileStack.GetSize();
constexpr inline const size_t CoreExceptionStackSize = 0x80;
/* Nintendo uses the bottom 0x740 of this as a stack for warmboot setup, and another 0x740 for the core 0/1/2 SMC stacks. */
/* This is...wasteful. The warmboot stack is not deep. We will thus save 1K+ of nonvolatile storage by keeping the random cache in here. */
struct VolatileData {
u8 random_cache[0x400];
u8 se_work_block[crypto::AesEncryptor128::BlockSize];
u8 reserved_danger_zone[0x30]; /* This memory is "available", but careful consideration must be taken before declaring it used. */
u8 warmboot_stack[0x380];
u8 core012_smc_stack[0x6C0];
u8 core_exception_stacks[3][CoreExceptionStackSize];
};
static_assert(util::is_pod<VolatileData>::value);
static_assert(sizeof(VolatileData) == 0x1000);
ALWAYS_INLINE VolatileData &GetVolatileData() {
return *MemoryRegionVirtualTzramVolatileData.GetPointer<VolatileData>();
}
ALWAYS_INLINE u8 *GetRandomBytesCache() {
return GetVolatileData().random_cache;
}
constexpr ALWAYS_INLINE size_t GetRandomBytesCacheSize() {
return sizeof(VolatileData::random_cache);
}
ALWAYS_INLINE u8 *GetSecurityEngineEphemeralWorkBlock() {
return GetVolatileData().se_work_block;
}
constexpr inline const Address WarmbootStackAddress = MemoryRegionVirtualTzramVolatileData.GetAddress() + offsetof(VolatileData, warmboot_stack) + sizeof(VolatileData::warmboot_stack);
constexpr inline const Address Core012SmcStackAddress = MemoryRegionVirtualTzramVolatileData.GetAddress() + offsetof(VolatileData, core012_smc_stack) + sizeof(VolatileData::core012_smc_stack);
constexpr inline const Address Core0ExceptionStackAddress = MemoryRegionVirtualTzramVolatileData.GetAddress() + offsetof(VolatileData, core_exception_stacks) + CoreExceptionStackSize;
constexpr inline const Address Core1ExceptionStackAddress = Core0ExceptionStackAddress + CoreExceptionStackSize;
constexpr inline const Address Core2ExceptionStackAddress = Core1ExceptionStackAddress + CoreExceptionStackSize;
}

View File

@ -0,0 +1,31 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/tegra/tegra_ahb_arbc.hpp>
#include <exosphere/tegra/tegra_apb_misc.hpp>
#include <exosphere/tegra/tegra_avp_cache.hpp>
#include <exosphere/tegra/tegra_emc.hpp>
#include <exosphere/tegra/tegra_evp.hpp>
#include <exosphere/tegra/tegra_flow_ctlr.hpp>
#include <exosphere/tegra/tegra_ictlr.hpp>
#include <exosphere/tegra/tegra_mc.hpp>
#include <exosphere/tegra/tegra_mselect.hpp>
#include <exosphere/tegra/tegra_pmc.hpp>
#include <exosphere/tegra/tegra_sb.hpp>
#include <exosphere/tegra/tegra_sysctr0.hpp>
#include <exosphere/tegra/tegra_timer.hpp>

View File

@ -0,0 +1,26 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define AHB_ARBC(x) (0x6000c000 + x)
#define AHB_ARBITRATION_DISABLE (0x004)
#define AHB_ARBITRATION_PRIORITY_CTRL (0x008)
#define AHB_MASTER_SWID (0x018)
#define AHB_MASTER_SWID_1 (0x038)
#define AHB_GIZMO_TZRAM (0x054)

View File

@ -0,0 +1,99 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 (0xc00)
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 (0xc04)
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 (0xc08)
#define AHB_MISC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (AHB_MISC, NAME)
#define AHB_MISC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (AHB_MISC, NAME, VALUE)
#define AHB_MISC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (AHB_MISC, NAME, ENUM)
#define AHB_MISC_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(AHB_MISC, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_AHB_MISC_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (AHB_MISC, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_AHB_MISC_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (AHB_MISC, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_AHB_MISC_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (AHB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_AHB_MISC_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(AHB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_AHB_MISC_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (AHB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
#define DEFINE_SLAVE_SECURITY_REG(RINDEX, INDEX, NAME) DEFINE_AHB_MISC_REG_BIT_ENUM(SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG##RINDEX##_##NAME##_SECURITY_EN, INDEX, DISABLE, ENABLE)
DEFINE_SLAVE_SECURITY_REG(0, 29, STM);
DEFINE_SLAVE_SECURITY_REG(0, 24, CEC);
DEFINE_SLAVE_SECURITY_REG(0, 23, ATOMICS);
DEFINE_SLAVE_SECURITY_REG(0, 22, LA);
DEFINE_SLAVE_SECURITY_REG(0, 21, HDA);
DEFINE_SLAVE_SECURITY_REG(0, 20, SATA);
DEFINE_SLAVE_SECURITY_REG(0, 16, KFUSE);
DEFINE_SLAVE_SECURITY_REG(0, 15, FUSE);
DEFINE_SLAVE_SECURITY_REG(0, 14, SE);
DEFINE_SLAVE_SECURITY_REG(0, 13, PMC);
DEFINE_SLAVE_SECURITY_REG(0, 11, RTC);
DEFINE_SLAVE_SECURITY_REG(0, 10, CSITE);
DEFINE_SLAVE_SECURITY_REG(0, 9, QSPI);
DEFINE_SLAVE_SECURITY_REG(0, 8, PWM);
DEFINE_SLAVE_SECURITY_REG(0, 6, DTV);
DEFINE_SLAVE_SECURITY_REG(0, 4, APE);
DEFINE_SLAVE_SECURITY_REG(0, 3, PINMUX_AUX);
DEFINE_SLAVE_SECURITY_REG(0, 2, SATA_AUX);
DEFINE_SLAVE_SECURITY_REG(0, 1, MISC_REGS);
DEFINE_SLAVE_SECURITY_REG(1, 31, I2C6);
DEFINE_SLAVE_SECURITY_REG(1, 30, DVC);
DEFINE_SLAVE_SECURITY_REG(1, 29, I2C4);
DEFINE_SLAVE_SECURITY_REG(1, 28, I2C3);
DEFINE_SLAVE_SECURITY_REG(1, 27, I2C2);
DEFINE_SLAVE_SECURITY_REG(1, 26, I2C1);
DEFINE_SLAVE_SECURITY_REG(1, 25, SPI6);
DEFINE_SLAVE_SECURITY_REG(1, 24, SPI5);
DEFINE_SLAVE_SECURITY_REG(1, 23, SPI4);
DEFINE_SLAVE_SECURITY_REG(1, 22, SPI3);
DEFINE_SLAVE_SECURITY_REG(1, 21, SPI2);
DEFINE_SLAVE_SECURITY_REG(1, 20, SPI1);
DEFINE_SLAVE_SECURITY_REG(1, 15, UART_D);
DEFINE_SLAVE_SECURITY_REG(1, 14, UART_C);
DEFINE_SLAVE_SECURITY_REG(1, 13, UART_B);
DEFINE_SLAVE_SECURITY_REG(1, 12, UART_A);
DEFINE_SLAVE_SECURITY_REG(1, 11, EMCB);
DEFINE_SLAVE_SECURITY_REG(1, 10, MCB);
DEFINE_SLAVE_SECURITY_REG(1, 9, EMC1);
DEFINE_SLAVE_SECURITY_REG(1, 8, MC1);
DEFINE_SLAVE_SECURITY_REG(1, 5, EMC0);
DEFINE_SLAVE_SECURITY_REG(1, 4, MC0);
DEFINE_SLAVE_SECURITY_REG(2, 21, FEK);
DEFINE_SLAVE_SECURITY_REG(2, 20, PKA1);
DEFINE_SLAVE_SECURITY_REG(2, 19, SE2);
DEFINE_SLAVE_SECURITY_REG(2, 16, DVFS);
DEFINE_SLAVE_SECURITY_REG(2, 15, MIPI_CAL);
DEFINE_SLAVE_SECURITY_REG(2, 14, XUSB_PADCTL);
DEFINE_SLAVE_SECURITY_REG(2, 13, XUSB_DEV);
DEFINE_SLAVE_SECURITY_REG(2, 12, XUSB_HOST);
DEFINE_SLAVE_SECURITY_REG(2, 11, APB2JTAG);
DEFINE_SLAVE_SECURITY_REG(2, 10, SOC_THERM);
DEFINE_SLAVE_SECURITY_REG(2, 9, DP2);
DEFINE_SLAVE_SECURITY_REG(2, 8, DDS);
DEFINE_SLAVE_SECURITY_REG(2, 7, MIPIBIF);
DEFINE_SLAVE_SECURITY_REG(2, 3, SDMMC4);
DEFINE_SLAVE_SECURITY_REG(2, 2, SDMMC3);
DEFINE_SLAVE_SECURITY_REG(2, 1, SDMMC2);
DEFINE_SLAVE_SECURITY_REG(2, 0, SDMMC1);
#undef DEFINE_SLAVE_SECURITY_REG
#define SLAVE_SECURITY_REG_BITS_ENUM(RINDEX, NAME, ENUM) AHB_MISC_REG_BITS_ENUM(SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG##RINDEX##_##NAME##_SECURITY_EN, ENUM)

View File

@ -0,0 +1,35 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define AVP_CACHE_ADDRESS(x) (0x50040000 + x)
#define AVP_CACHE_CONFIG (0x000)
#define AVP_CACHE_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (AVP_CACHE, NAME)
#define AVP_CACHE_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (AVP_CACHE, NAME, VALUE)
#define AVP_CACHE_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (AVP_CACHE, NAME, ENUM)
#define AVP_CACHE_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(AVP_CACHE, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_AVP_CACHE_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (AVP_CACHE, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_AVP_CACHE_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (AVP_CACHE, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_AVP_CACHE_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (AVP_CACHE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_AVP_CACHE_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(AVP_CACHE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_AVP_CACHE_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (AVP_CACHE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_AVP_CACHE_REG_BIT_ENUM(DISABLE_WB, 10, FALSE, TRUE);
DEFINE_AVP_CACHE_REG_BIT_ENUM(DISABLE_RB, 11, FALSE, TRUE);

View File

@ -0,0 +1,90 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define EMC_ADDRESS(x) (0x7001B000 + x)
#define EMC0_ADDRESS(x) (0x7001E000 + x)
#define EMC1_ADDRESS(x) (0x7001F000 + x)
#define EMC_CFG (0x00C)
#define EMC_ADR_CFG (0x010)
#define EMC_TIMING_CONTROL (0x028)
#define EMC_SELF_REF (0x0E0)
#define EMC_MRW (0x0E8)
#define EMC_FBIO_CFG5 (0x104)
#define EMC_MRW3 (0x138)
#define EMC_AUTO_CAL_CONFIG (0x2A4)
#define EMC_REQ_CTRL (0x2B0)
#define EMC_EMC_STATUS (0x2B4)
#define EMC_CFG_DIG_DLL (0x2BC)
#define EMC_ZCAL_INTERVAL (0x2E0)
#define EMC_PMC_SCRATCH3 (0x448)
#define EMC_FBIO_CFG7 (0x584)
#define EMC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (EMC, NAME)
#define EMC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (EMC, NAME, VALUE)
#define EMC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (EMC, NAME, ENUM)
#define EMC_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(EMC, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_EMC_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (EMC, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_EMC_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (EMC, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_EMC_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (EMC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_EMC_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(EMC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_EMC_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (EMC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_EMC_REG_BIT_ENUM(CFG_DYN_SELF_REF, 28, DISABLED, ENABLED);
DEFINE_EMC_REG_BIT_ENUM(CFG_DRAM_ACPD, 29, NO_POWERDOWN, ACTIVE_POWERDOWN);
DEFINE_EMC_REG_BIT_ENUM(ADR_CFG_EMEM_NUMDEV, 0, N1, N2);
DEFINE_EMC_REG_BIT_ENUM(TIMING_CONTROL_TIMING_UPDATE, 0, DISABLED, ENABLED);
DEFINE_EMC_REG_BIT_ENUM(SELF_REF_SELF_REF_CMD, 0, DISABLED, ENABLED);
DEFINE_EMC_REG_BIT_ENUM(SELF_REF_ACTIVE_SELF_REF, 8, DISABLED, ENABLED);
DEFINE_EMC_REG_TWO_BIT_ENUM(SELF_REF_SREF_DEV_SELECTN, 30, BOTH, DEV1, DEV0, RESERVED);
DEFINE_EMC_REG(MRW_OP, 0, 8);
DEFINE_EMC_REG(MRW_MA, 16, 8);
DEFINE_EMC_REG_TWO_BIT_ENUM(MRW_CNT, 26, SHORT, LONG, EXT1, EXT2);
DEFINE_EMC_REG_TWO_BIT_ENUM(MRW_DEV_SELECTN, 30, BOTH, DEV1, DEV0, RESERVED);
DEFINE_EMC_REG_TWO_BIT_ENUM(FBIO_CFG5_DRAM_TYPE, 0, DDR4, LPDDR4, LPDDR2, DDR2);
DEFINE_EMC_REG_BIT_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_MEASURE_STALL, 9, DISABLE, ENABLE);
DEFINE_EMC_REG_BIT_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_UPDATE_STALL, 10, DISABLE, ENABLE);
DEFINE_EMC_REG_BIT_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_START, 31, DISABLE, ENABLE);
DEFINE_EMC_REG(REQ_CTRL_STALL_ALL_READS, 0, 1);
DEFINE_EMC_REG(REQ_CTRL_STALL_ALL_WRITES, 1, 1);
DEFINE_EMC_REG_TWO_BIT_ENUM(EMC_STATUS_DRAM_IN_SELF_REFRESH, 8, DISABLED, DEV0_ENABLED, DEV1_ENABLED, BOTH_ENABLED);
DEFINE_EMC_REG_BIT_ENUM(EMC_STATUS_DRAM_DEV0_IN_SELF_REFRESH, 8, DISABLED, ENABLED);
DEFINE_EMC_REG_BIT_ENUM(EMC_STATUS_NO_OUTSTANDING_TRANSACTIONS, 2, WAITING, COMPLETED);
DEFINE_EMC_REG_BIT_ENUM(EMC_STATUS_TIMING_UPDATE_STALLED, 23, DONE, BUSY);
DEFINE_EMC_REG_BIT_ENUM(CFG_DIG_DLL_CFG_DLL_EN, 0, DISABLED, ENABLED);
DEFINE_EMC_REG(ZCAL_INTERVAL_LO, 0, 10);
DEFINE_EMC_REG(ZCAL_INTERVAL_HI, 10, 14);
DEFINE_EMC_REG(PMC_SCRATCH3_DDR_CNTRL, 0, 19);
DEFINE_EMC_REG_BIT_ENUM(PMC_SCRATCH3_WEAK_BIAS, 30, DISABLED, ENABLED);
DEFINE_EMC_REG_BIT_ENUM(FBIO_CFG7_CH1_ENABLE, 2, DISABLE, ENABLE);

View File

@ -0,0 +1,19 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define EVP_CPU_RESET_VECTOR (0x100)

View File

@ -0,0 +1,38 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define FLOW_CTLR_FLOW_DBG_QUAL (0x050)
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL (0x098)
#define FLOW_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (FLOW_CTLR, NAME)
#define FLOW_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (FLOW_CTLR, NAME, VALUE)
#define FLOW_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (FLOW_CTLR, NAME, ENUM)
#define FLOW_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(FLOW_CTLR, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_FLOW_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (FLOW_CTLR, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_FLOW_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (FLOW_CTLR, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_FLOW_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (FLOW_CTLR, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_FLOW_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(FLOW_CTLR, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_FLOW_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (FLOW_CTLR, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_FLOW_REG_BIT_ENUM(FLOW_DBG_QUAL_FIQ2CCPLEX_ENABLE, 28, DISABLE, ENABLE);
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER, 0, FAST, SLOW);
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_CLUSTER_SWITCH_ENABLE, 1, DISABLE, ENABLE);
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER_LOCK, 2, DISABLE, ENABLE);

View File

@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define PRI_ICTLR(n) (0x60004000 + n)
#define SEC_ICTLR(n) (0x60004100 + n)
#define TRI_ICTLR(n) (0x60004200 + n)
#define QUAD_ICTLR(n) (0x60004300 + n)
#define PENTA_ICTLR(n) (0x60004400 + n)
#define HEXA_ICTLR(n) (0x60004500 + n)
#define ICTLR_COP_IER_CLR (0x038)

View File

@ -0,0 +1,329 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/reg.hpp>
#define MC_INTSTATUS (0x000)
#define MC_INTMASK (0x004)
#define MC_ERR_STATUS (0x008)
#define MC_ERR_ADR (0x00c)
#define MC_SMMU_CONFIG (0x010)
#define MC_SMMU_TLB_CONFIG (0x014)
#define MC_SMMU_PTC_CONFIG (0x018)
#define MC_SMMU_PTB_ASID (0x01c)
#define MC_SMMU_PTB_DATA (0x020)
#define MC_SMMU_TLB_FLUSH (0x030)
#define MC_SMMU_PTC_FLUSH (0x034)
#define MC_SECURITY_CFG0 (0x070)
#define MC_SECURITY_CFG1 (0x074)
#define MC_SECURITY_CFG3 (0x9BC)
#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_SMMU_ASID_SECURITY (0x038)
#define MC_SMMU_ASID_SECURITY_1 (0x03c)
#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_SEC_CARVEOUT_BOM (0x670)
#define MC_SEC_CARVEOUT_SIZE_MB (0x674)
#define MC_SEC_CARVEOUT_REG_CTRL (0x678)
#define MC_VIDEO_PROTECT_BOM (0x648)
#define MC_VIDEO_PROTECT_SIZE_MB (0x64c)
#define MC_VIDEO_PROTECT_REG_CTRL (0x650)
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 (0x984)
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 (0x988)
#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_SECURITY_CARVEOUT1_CFG0 (0xc08)
#define MC_SECURITY_CARVEOUT1_BOM (0xc0c)
#define MC_SECURITY_CARVEOUT1_BOM_HI (0xc10)
#define MC_SECURITY_CARVEOUT1_SIZE_128KB (0xc14)
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 (0xc18)
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 (0xc1c)
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 (0xc20)
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 (0xc24)
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 (0xc28)
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 (0xc2c)
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 (0xc30)
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 (0xc34)
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 (0xc38)
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 (0xc3c)
#define MC_SECURITY_CARVEOUT2_CFG0 (0xc58)
#define MC_SECURITY_CARVEOUT2_BOM (0xc5c)
#define MC_SECURITY_CARVEOUT2_BOM_HI (0xc60)
#define MC_SECURITY_CARVEOUT2_SIZE_128KB (0xc64)
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 (0xc68)
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 (0xc6c)
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 (0xc70)
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 (0xc74)
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 (0xc78)
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 (0xc7c)
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 (0xc80)
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 (0xc84)
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 (0xc88)
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 (0xc8c)
#define MC_SECURITY_CARVEOUT3_CFG0 (0xca8)
#define MC_SECURITY_CARVEOUT3_BOM (0xcac)
#define MC_SECURITY_CARVEOUT3_BOM_HI (0xcb0)
#define MC_SECURITY_CARVEOUT3_SIZE_128KB (0xcb4)
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 (0xcb8)
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 (0xcbc)
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 (0xcc0)
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 (0xcc4)
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 (0xcc8)
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 (0xccc)
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 (0xcd0)
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 (0xcd4)
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 (0xcd8)
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 (0xcdc)
#define MC_SECURITY_CARVEOUT4_CFG0 (0xcf8)
#define MC_SECURITY_CARVEOUT4_BOM (0xcfc)
#define MC_SECURITY_CARVEOUT4_BOM_HI (0xd00)
#define MC_SECURITY_CARVEOUT4_SIZE_128KB (0xd04)
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 (0xd08)
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 (0xd0c)
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 (0xd10)
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 (0xd14)
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 (0xd18)
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 (0xd1c)
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 (0xd20)
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 (0xd24)
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 (0xd28)
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 (0xd2c)
#define MC_SECURITY_CARVEOUT5_CFG0 (0xd48)
#define MC_SECURITY_CARVEOUT5_BOM (0xd4c)
#define MC_SECURITY_CARVEOUT5_BOM_HI (0xd50)
#define MC_SECURITY_CARVEOUT5_SIZE_128KB (0xd54)
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 (0xd58)
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 (0xd5c)
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 (0xd60)
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 (0xd64)
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 (0xd68)
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 (0xd6c)
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 (0xd70)
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 (0xd74)
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 (0xd78)
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 (0xd7c)
#define MC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (MC, NAME)
#define MC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (MC, NAME, VALUE)
#define MC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (MC, NAME, ENUM)
#define MC_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(MC, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_MC_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (MC, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_MC_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (MC, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_MC_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (MC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_MC_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(MC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_MC_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (MC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_MC_REG_BIT_ENUM(SMMU_CONFIG_SMMU_ENABLE, 0, DISABLE, ENABLE);
DEFINE_MC_REG(SMMU_TLB_CONFIG_TLB_ACTIVE_LINES, 0, 6);
DEFINE_MC_REG_BIT_ENUM(SMMU_TLB_CONFIG_TLB_ROUND_ROBIN_ARBITRATION, 28, DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(SMMU_TLB_CONFIG_TLB_HIT_UNDER_MISS, 29, DISABLE, ENABLE);
DEFINE_MC_REG(SMMU_PTC_CONFIG_PTC_INDEX_MAP, 0, 7);
DEFINE_MC_REG(SMMU_PTC_CONFIG_PTC_REQ_LIMIT, 24, 4);
DEFINE_MC_REG_BIT_ENUM(SMMU_PTC_CONFIG_PTC_CACHE_ENABLE, 29, DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_0, 0, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_1, 1, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_2, 2, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_3, 3, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_4, 4, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_5, 5, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_6, 6, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_7, 7, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_8, 8, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_9, 9, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_10, 10, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_11, 11, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_12, 12, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_13, 13, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_14, 14, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_15, 15, NONSECURE, SECURE);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_0, 16, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_1, 17, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_2, 18, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_3, 19, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_4, 20, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_5, 21, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_6, 22, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_7, 23, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_8, 24, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_9, 25, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_10, 26, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_11, 27, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_12, 28, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_13, 29, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_14, 30, NONPROMOTING, PROMOTING);
DEFINE_MC_REG_BIT_ENUM(SMMU_ASID_SECURITY_PROMOTING_ASIDS_15, 31, NONPROMOTING, PROMOTING);
DEFINE_MC_REG(SECURITY_CFG0_SECURITY_BOM, 20, 12);
DEFINE_MC_REG(SECURITY_CFG1_SECURITY_SIZE, 0, 13);
DEFINE_MC_REG(SECURITY_CFG3_SECURITY_BOM_HI, 0, 2);
DEFINE_MC_REG_BIT_ENUM(SEC_CARVEOUT_REG_CTRL_SEC_CARVEOUT_WRITE_ACCESS, 0, ENABLED, DISABLED);
DEFINE_MC_REG_BIT_ENUM(VIDEO_PROTECT_REG_CTRL_VIDEO_PROTECT_WRITE_ACCESS, 0, ENABLED, DISABLED);
DEFINE_MC_REG_BIT_ENUM(VIDEO_PROTECT_REG_CTRL_VIDEO_PROTECT_ALLOW_TZ_WRITE, 1, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(MTS_CARVEOUT_REG_CTRL_MTS_CARVEOUT_WRITE_ACCESS, 0, ENABLED, DISABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_PROTECT_MODE, 0, LOCKBIT_SECURE, TZ_SECURE);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_LOCK_MODE, 1, UNLOCKED, LOCKED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, 2, ANY_ADDRESS, UNTRANSLATED_ONLY);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, 3, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, 4, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, 5, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, 6, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, 7, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, 8, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, 9, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, 10, DISABLED, ENABLED);
DEFINE_MC_REG(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 11, 3);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, 14, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, 15, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, 16, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, 17, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, 18, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, 19, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, 20, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, 21, ENABLE_CHECKS, DISABLE_CHECKS);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, 22, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, 23, DISABLED, BYPASS_CHECK);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, 24, DISABLED, BYPASS_CHECK);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, 25, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, 26, DISABLED, ENABLED);
DEFINE_MC_REG_BIT_ENUM(SECURITY_CARVEOUT_CFG0_IS_WPR, 27, DISABLED, ENABLED);
#define MC_CLIENT_ACCESS_NUM_CLIENTS 32
/* _ACCESS0 */
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_PTCR, ( 0 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAY0A, ( 1 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAY0AB, ( 2 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAY0B, ( 3 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAY0BB, ( 4 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAY0C, ( 5 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAY0CB, ( 6 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_AFIR, ( 14 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_AVPCARM7R, ( 15 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAYHC, ( 16 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_DISPLAYHCB, ( 17 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_HDAR, ( 21 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_HOST1XDMAR, ( 22 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_HOST1XR, ( 23 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_NVENCSRD, ( 28 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_PPCSAHBDMAR, ( 29 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_PPCSAHBSLVR, ( 30 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS0_SATAR, ( 31 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 0)), DISABLE, ENABLE);
/* _ACCESS1 */
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_VDEBSEVR, ( 34 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_VDEMBER, ( 35 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_VDEMCER, ( 36 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_VDETPER, ( 37 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_MPCORELPR, ( 38 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_MPCORER, ( 39 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_NVENCSWR, ( 43 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_AFIW, ( 49 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_AVPCARM7W, ( 50 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_HDAW, ( 53 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_HOST1XW, ( 54 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_MPCORELPW, ( 56 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_MPCOREW, ( 57 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_PPCSAHBDMAW, ( 59 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_PPCSAHBSLVW, ( 60 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_SATAW, ( 61 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_VDEBSEVW, ( 62 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS1_VDEDBGW, ( 63 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 1)), DISABLE, ENABLE);
/* _ACCESS2 */
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_VDEMBEW, ( 64 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_VDETPMW, ( 65 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_ISPRA, ( 68 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_ISPWA, ( 70 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_ISPWB, ( 71 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_XUSB_HOSTR, ( 74 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_XUSB_HOSTW, ( 75 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_XUSB_DEVR, ( 76 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_XUSB_DEVW, ( 77 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_ISPRAB, ( 78 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_ISPWAB, ( 80 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_ISPWBB, ( 81 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_TSECSRD, ( 84 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_TSECSWR, ( 85 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_A9AVPSCR, ( 86 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_A9AVPSCW, ( 87 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_GPUSRD, ( 88 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_GPUSWR, ( 89 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS2_DISPLAYT, ( 90 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 2)), DISABLE, ENABLE);
/* _ACCESS3 */
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCRA, ( 96 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCRAA, ( 97 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCR, ( 98 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCRAB, ( 99 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCWA, (100 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCWAA, (101 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCW, (102 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_SDMMCWAB, (103 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_VICSRD, (108 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_VICSWR, (109 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_VIW, (114 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_DISPLAYD, (115 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_NVDECSRD, (120 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_NVDECSWR, (121 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_APER, (122 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_APEW, (123 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_NVJPGSRD, (126 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS3_NVJPGSWR, (127 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 3)), DISABLE, ENABLE);
/* _ACCESS4 */
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_SESRD, (128 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_SESWR, (129 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_AXIAPR, (130 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_AXIAPW, (131 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_ETRR, (132 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_ETRW, (133 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_TSECRDB, (134 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_TSECWRB, (135 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_GPUSRD2, (136 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);
DEFINE_MC_REG_BIT_ENUM(CLIENT_ACCESS4_GPUSWR2, (137 - (MC_CLIENT_ACCESS_NUM_CLIENTS * 4)), DISABLE, ENABLE);

View File

@ -0,0 +1,22 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define MSELECT(x) (0x50060000 + x)
#define MSELECT_CONFIG (0x000)

View File

@ -0,0 +1,156 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/reg.hpp>
#define APBDEV_PMC_CNTRL (0x000)
#define APBDEV_PMC_DPD_SAMPLE (0x020)
#define APBDEV_PMC_DPD_ENABLE (0x024)
#define APBDEV_PMC_CLAMP_STATUS (0x02C)
#define APBDEV_PMC_PWRGATE_TOGGLE (0x030)
#define APBDEV_PMC_PWRGATE_STATUS (0x038)
#define APBDEV_PMC_SCRATCH0 (0x050)
#define APBDEV_PMC_SCRATCH1 (0x054)
#define APBDEV_PMC_SCRATCH12 (0x080)
#define APBDEV_PMC_SCRATCH13 (0x084)
#define APBDEV_PMC_SCRATCH18 (0x098)
#define APBDEV_PMC_SCRATCH20 (0x0A0)
#define APBDEV_PMC_CRYPTO_OP (0x0F4)
#define APBDEV_PM (0x014)
#define APBDEV_PMC_WAKE2_STATUS (0x168)
#define APBDEV_PMC_WEAK_BIAS (0x2C8)
#define APBDEV_PMC_CNTRL2 (0x440)
#define APBDEV_PMC_FUSE_CTRL (0x450)
#define APBDEV_PMC_IO_DPD3_REQ (0x45C)
#define APBDEV_PMC_IO_DPD3_STATUS (0x460)
#define APBDEV_PMC_IO_DPD4_REQ (0x464)
#define APBDEV_PMC_IO_DPD4_STATUS (0x468)
#define APBDEV_PMC_SET_SW_CLAMP (0x47C)
#define APBDEV_PMC_DDR_CNTRL (0x4E4)
#define APBDEV_PMC_SEC_DISABLE (0x004)
#define APBDEV_PMC_SEC_DISABLE2 (0x2C4)
#define APBDEV_PMC_SEC_DISABLE3 (0x2D8)
#define APBDEV_PMC_SEC_DISABLE4 (0x5B0)
#define APBDEV_PMC_SEC_DISABLE5 (0x5B4)
#define APBDEV_PMC_SEC_DISABLE6 (0x5B8)
#define APBDEV_PMC_SEC_DISABLE7 (0x5BC)
#define APBDEV_PMC_SEC_DISABLE8 (0x5C0)
#define APBDEV_PMC_SCRATCH43 (0x22C)
#define APBDEV_PMC_SCRATCH190 (0x818)
#define APBDEV_PMC_SCRATCH200 (0x840)
#define APBDEV_PMC_SEC_DISABLE3 (0x2D8)
#define APBDEV_PMC_SECURE_SCRATCH4 (0x0C0)
#define APBDEV_PMC_SECURE_SCRATCH5 (0x0C4)
#define APBDEV_PMC_SECURE_SCRATCH6 (0x224)
#define APBDEV_PMC_SECURE_SCRATCH7 (0x228)
#define APBDEV_PMC_SECURE_SCRATCH16 (0x320)
#define APBDEV_PMC_SECURE_SCRATCH21 (0x334)
#define APBDEV_PMC_SECURE_SCRATCH24 (0x340)
#define APBDEV_PMC_SECURE_SCRATCH25 (0x344)
#define APBDEV_PMC_SECURE_SCRATCH26 (0x348)
#define APBDEV_PMC_SECURE_SCRATCH27 (0x34C)
#define APBDEV_PMC_SECURE_SCRATCH32 (0x360)
#define APBDEV_PMC_SECURE_SCRATCH34 (0x368)
#define APBDEV_PMC_SECURE_SCRATCH35 (0x36C)
#define APBDEV_PMC_SECURE_SCRATCH39 (0x37C)
#define APBDEV_PMC_SECURE_SCRATCH51 (0x3AC)
#define APBDEV_PMC_SECURE_SCRATCH55 (0x3BC)
#define APBDEV_PMC_SECURE_SCRATCH74 (0x408)
#define APBDEV_PMC_SECURE_SCRATCH75 (0x40C)
#define APBDEV_PMC_SECURE_SCRATCH76 (0x410)
#define APBDEV_PMC_SECURE_SCRATCH77 (0x414)
#define APBDEV_PMC_SECURE_SCRATCH78 (0x418)
#define APBDEV_PMC_SECURE_SCRATCH99 (0xAE4)
#define APBDEV_PMC_SECURE_SCRATCH100 (0xAE8)
#define APBDEV_PMC_SECURE_SCRATCH101 (0xAEC)
#define APBDEV_PMC_SECURE_SCRATCH102 (0xAF0)
#define APBDEV_PMC_SECURE_SCRATCH103 (0xAF4)
#define APBDEV_PMC_SECURE_SCRATCH112 (0xB18)
#define APBDEV_PMC_SECURE_SCRATCH113 (0xB1C)
#define APBDEV_PMC_SECURE_SCRATCH114 (0xB20)
#define APBDEV_PMC_SECURE_SCRATCH115 (0xB24)
#define PMC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (APBDEV_PMC, NAME)
#define PMC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (APBDEV_PMC, NAME, VALUE)
#define PMC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (APBDEV_PMC, NAME, ENUM)
#define PMC_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(APBDEV_PMC, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_PMC_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (APBDEV_PMC, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_PMC_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (APBDEV_PMC, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_PMC_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (APBDEV_PMC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_PMC_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(APBDEV_PMC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_PMC_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (APBDEV_PMC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_PMC_REG_BIT_ENUM(CNTRL_MAIN_RESET, 4, DISABLE, ENABLE)
DEFINE_PMC_REG_BIT_ENUM(DPD_SAMPLE_ON, 0, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(DPD_ENABLE_ON, 0, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(DPD_ENABLE_TSC_MULT_EN, 1, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_CRAIL, 0, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_VE, 2, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_PCX, 3, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_MPE, 6, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_SAX, 8, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_CE1, 9, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_CE2, 10, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_CE3, 11, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_CE0, 14, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_C0NC, 15, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_SOR, 17, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_DIS, 18, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_DISB, 19, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_XUSBA, 20, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_XUSBB, 21, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_XUSBC, 22, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_VIC, 23, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_IRAM, 24, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_NVDEC, 25, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_NVJPG, 26, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_AUD, 27, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_DFD, 28, OFF, ON);
DEFINE_PMC_REG_BIT_ENUM(PWRGATE_STATUS_VE2, 29, OFF, ON);
DEFINE_PMC_REG(SET_SW_CLAMP_CRAIL, 0, 1);
DEFINE_PMC_REG_TWO_BIT_ENUM(IO_DPD_REQ_CODE, 30, IDLE, DPD_OFF, DPD_ON, RESERVED3);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_CRAIL, 0, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_TE, 1, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_VE, 2, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_PCX, 3, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_VDE, 4, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_MPE, 6, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_HEG, 7, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_SAX, 8, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_CE1, 9, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_CE2, 10, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_CE3, 11, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_CELP, 12, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_CE0, 14, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_C0NC, 15, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_SOR, 17, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_C1NC, 16, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_DIS, 18, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_DISB, 19, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_XUSBA, 20, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_XUSBB, 21, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_XUSBC, 22, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_VIC, 23, DISABLE, ENABLE);
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_IRAM, 24, DISABLE, ENABLE);

View File

@ -0,0 +1,41 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define SB_CSR (0x200)
#define SB_AA64_RESET_LOW (0x230)
#define SB_AA64_RESET_HIGH (0x234)
#define SB_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (SB, NAME)
#define SB_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (SB, NAME, VALUE)
#define SB_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (SB, NAME, ENUM)
#define SB_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(SB, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_SB_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (SB, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_SB_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (SB, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_SB_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (SB, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_SB_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(SB, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_SB_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (SB, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_SB_REG_BIT_ENUM(CSR_SECURE_BOOT_FLAG, 0, DISABLE, ENABLE);
DEFINE_SB_REG_BIT_ENUM(CSR_NS_RST_VEC_WR_DIS, 1, ENABLE, DISABLE);
DEFINE_SB_REG_BIT_ENUM(CSR_PIROM_DISABLE, 4, ENABLE, DISABLE);
DEFINE_SB_REG_BIT_ENUM(CSR_HANG, 6, DISABLE, ENABLE);
DEFINE_SB_REG_BIT_ENUM(CSR_SWDM_ENABLE, 7, DISABLE, ENABLE);
DEFINE_SB_REG(CSR_SWDM_FAIL_COUNT, 8, 4);
DEFINE_SB_REG(CSR_COT_FAIL_COUNT, 12, 4);

View File

@ -0,0 +1,36 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define SYSCTR0_CNTFID0 (0x020)
#define SYSCTR0_CNTFID1 (0x024)
#define SYSCTR0_COUNTERID4 (0xFD0)
#define SYSCTR0_COUNTERID5 (0xFD4)
#define SYSCTR0_COUNTERID6 (0xFD8)
#define SYSCTR0_COUNTERID7 (0xFDC)
#define SYSCTR0_COUNTERID0 (0xFE0)
#define SYSCTR0_COUNTERID1 (0xFE4)
#define SYSCTR0_COUNTERID2 (0xFE8)
#define SYSCTR0_COUNTERID3 (0xFEC)
#define SYSCTR0_COUNTERID8 (0xFF0)
#define SYSCTR0_COUNTERID9 (0xFF4)
#define SYSCTR0_COUNTERID10 (0xFF8)
#define SYSCTR0_COUNTERID11 (0xFFC)
#define SYSCTR0_COUNTERID(n) SYSCTR0_COUNTERID##n

View File

@ -0,0 +1,41 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#define TIMER_SHARED_TIMER_SECURE_CFG (0x1A4)
#define TIMER_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (TIMER, NAME)
#define TIMER_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (TIMER, NAME, VALUE)
#define TIMER_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (TIMER, NAME, ENUM)
#define TIMER_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(TIMER, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_TIMER_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (TIMER, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_TIMER_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (TIMER, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_TIMER_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (TIMER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_TIMER_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(TIMER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_TIMER_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (TIMER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR5, 5, DISABLE, ENABLE);
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR6, 6, DISABLE, ENABLE);
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR7, 7, DISABLE, ENABLE);
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR8, 8, DISABLE, ENABLE);
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_WDT0, 12, DISABLE, ENABLE);
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_WDT1, 13, DISABLE, ENABLE);
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_WDT2, 14, DISABLE, ENABLE);
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_WDT3, 15, DISABLE, ENABLE);

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::tsec {
void Lock();
}

View File

@ -0,0 +1,42 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::uart {
enum Port {
Port_A = 0,
Port_B = 1,
Port_C = 2,
Port_Count = 3,
Port_ReservedDebug = Port_A,
Port_RightJoyCon = Port_B,
Port_LeftJoyCon = Port_C,
};
enum Flags {
Flag_None = (0u << 0),
Flag_Inverted = (1u << 0),
};
void SetRegisterAddress(uintptr_t address);
void Initialize(Port port, int baud_rate, u32 flags);
}

View File

@ -0,0 +1,33 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::util {
void SetRegisterAddress(uintptr_t address);
u32 GetMicroSeconds();
void WaitMicroSeconds(int us);
void ClearMemory(void *ptr, size_t size);
template<typename T, typename U> requires std::integral<T> && std::integral<U>
constexpr T DivideUp(T x, U y) {
return (x + (y - 1)) / y;
}
}

View File

@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::wdt {
void SetRegisterAddress(uintptr_t address);
void Reboot();
}

View File

@ -0,0 +1,42 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::actmon {
namespace {
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceActivityMonitor.GetAddress();
}
void SetRegisterAddress(uintptr_t address) {
g_register_address = address;
}
void HandleInterrupt() {
/* TODO */
}
void StartMonitoringBpmp(InterruptHandler handler) {
/* TODO */
}
void StopMonitoringBpmp() {
/* TODO */
}
}

View File

@ -0,0 +1,98 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "clkrst_registers.hpp"
namespace ams::clkrst {
namespace {
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceClkRst.GetAddress();
struct ClockParameters {
uintptr_t reset_offset;
uintptr_t clk_enb_offset;
uintptr_t clk_src_offset;
u8 index;
u8 clk_src;
u8 clk_div;
};
void EnableClock(const ClockParameters &param) {
/* Hold reset. */
reg::ReadWrite(g_register_address + param.reset_offset, REG_BITS_VALUE(param.index, 1, 1));
/* Disable clock. */
reg::ReadWrite(g_register_address + param.clk_enb_offset, REG_BITS_VALUE(param.index, 1, 0));
/* Set the clock source. */
if (param.clk_src != 0) {
reg::Write(g_register_address + param.clk_src_offset, (param.clk_src << 29) | (param.clk_div << 0));
}
/* Enable clk. */
reg::ReadWrite(g_register_address + param.clk_enb_offset, REG_BITS_VALUE(param.index, 1, 1));
/* Release reset. */
reg::ReadWrite(g_register_address + param.reset_offset, REG_BITS_VALUE(param.index, 1, 0));
}
// void DisableClock(const ClockParameters &param) {
// /* Hold reset. */
// reg::ReadWrite(g_register_address + param.reset_offset, REG_BITS_VALUE(param.index, 1, 1));
//
// /* Disable clock. */
// reg::ReadWrite(g_register_address + param.clk_enb_offset, REG_BITS_VALUE(param.index, 1, 0));
// }
#define DEFINE_CLOCK_PARAMETERS(_VARNAME_, _REG_, _NAME_, _CLK_, _DIV_) \
constexpr inline const ClockParameters _VARNAME_ = { \
.reset_offset = CLK_RST_CONTROLLER_RST_DEVICES_##_REG_, \
.clk_enb_offset = CLK_RST_CONTROLLER_CLK_OUT_ENB_##_REG_, \
.clk_src_offset = CLK_RST_CONTROLLER_CLK_SOURCE_##_NAME_, \
.index = CLK_RST_CONTROLLER_CLK_ENB_##_NAME_##_INDEX, \
.clk_src = CLK_RST_CONTROLLER_CLK_SOURCE_##_NAME_##_##_NAME_##_CLK_SRC_##_CLK_, \
.clk_div = _DIV_, \
}
DEFINE_CLOCK_PARAMETERS(UartAClock, L, UARTA, PLLP_OUT0, 0);
DEFINE_CLOCK_PARAMETERS(UartBClock, L, UARTB, PLLP_OUT0, 0);
DEFINE_CLOCK_PARAMETERS(UartCClock, H, UARTC, PLLP_OUT0, 0);
}
void SetRegisterAddress(uintptr_t address) {
g_register_address = address;
}
void SetFuseVisibility(bool visible) {
reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_MISC_CLK_ENB, CLK_RST_REG_BITS_VALUE(MISC_CLK_ENB_CFG_ALL_VISIBLE, visible ? 1 : 0));
}
void EnableUartAClock() {
EnableClock(UartAClock);
}
void EnableUartBClock() {
EnableClock(UartAClock);
}
void EnableUartCClock() {
EnableClock(UartAClock);
}
}

View File

@ -0,0 +1,71 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::clkrst {
/* Clock source enums. */
#define CLK_RST_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (CLK_RST_CONTROLLER, NAME)
#define CLK_RST_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (CLK_RST_CONTROLLER, NAME, VALUE)
#define CLK_RST_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (CLK_RST_CONTROLLER, NAME, ENUM)
#define CLK_RST_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(CLK_RST_CONTROLLER, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_CLK_RST_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (CLK_RST_CONTROLLER, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_CLK_RST_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_CLK_RST_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_CLK_RST_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (CLK_RST_CONTROLLER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
#define CLK_RST_CONTROLLER_RST_SOURCE (0x000)
#define CLK_RST_CONTROLLER_MISC_CLK_ENB (0x048)
DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1);
/* RST_DEVICES */
#define CLK_RST_CONTROLLER_RST_DEVICES_L (0x004)
#define CLK_RST_CONTROLLER_RST_DEVICES_H (0x008)
#define CLK_RST_CONTROLLER_RST_DEVICES_U (0x00C)
#define CLK_RST_CONTROLLER_RST_DEVICES_X (0x28C)
#define CLK_RST_CONTROLLER_RST_DEVICES_Y (0x2A4)
#define CLK_RST_CONTROLLER_RST_DEVICES_V (0x358)
#define CLK_RST_CONTROLLER_RST_DEVICES_W (0x35C)
/* CLK_OUT_ENB */
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_L (0x010)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_H (0x014)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_U (0x018)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X (0x280)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_Y (0x298)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_V (0x360)
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_W (0x364)
/* CLK_SOURCE */
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178)
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C)
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0)
/* CLK_ENB_*_INDEX */
#define CLK_RST_CONTROLLER_CLK_ENB_UARTA_INDEX (0x06)
#define CLK_RST_CONTROLLER_CLK_ENB_UARTB_INDEX (0x07)
#define CLK_RST_CONTROLLER_CLK_ENB_UARTC_INDEX (0x17)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTA_UARTA_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTB_UARTB_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTC_UARTC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2)
}

View File

@ -0,0 +1,121 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "fuse_registers.hpp"
namespace ams::fuse {
namespace {
struct OdmWord4 {
using HardwareState1 = util::BitPack32::Field<0, 2, int>;
using HardwareType1 = util::BitPack32::Field<HardwareState1::Next, 1, int>;
using DramId = util::BitPack32::Field<HardwareType1::Next, 5, int>;
using HardwareType2 = util::BitPack32::Field<DramId::Next, 1, int>;
using HardwareState2 = util::BitPack32::Field<HardwareType2::Next, 1, int>;
using QuestState = util::BitPack32::Field<HardwareState2::Next, 1, int>;
using FormatVersion = util::BitPack32::Field<QuestState::Next, 1, int>;
using Reserved = util::BitPack32::Field<FormatVersion::Next, 4, int>;
using HardwareType3 = util::BitPack32::Field<Reserved::Next, 4, int>;
};
constexpr ALWAYS_INLINE int GetHardwareStateValue(const util::BitPack32 odm_word4) {
constexpr auto HardwareState1Shift = 0;
constexpr auto HardwareState2Shift = OdmWord4::HardwareState1::Count + HardwareState1Shift;
return (odm_word4.Get<OdmWord4::HardwareState1>() << HardwareState1Shift) |
(odm_word4.Get<OdmWord4::HardwareState2>() << HardwareState2Shift);
}
constexpr ALWAYS_INLINE int GetHardwareTypeValue(const util::BitPack32 odm_word4) {
constexpr auto HardwareType1Shift = 0;
constexpr auto HardwareType2Shift = OdmWord4::HardwareType1::Count + HardwareType1Shift;
constexpr auto HardwareType3Shift = OdmWord4::HardwareType2::Count + HardwareType2Shift;
return (odm_word4.Get<OdmWord4::HardwareType1>() << HardwareType1Shift) |
(odm_word4.Get<OdmWord4::HardwareType2>() << HardwareType2Shift) |
(odm_word4.Get<OdmWord4::HardwareType3>() << HardwareType3Shift);
}
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceFuses.GetAddress();
ALWAYS_INLINE volatile FuseRegisterRegion *GetRegisterRegion() {
return reinterpret_cast<volatile FuseRegisterRegion *>(g_register_address);
}
ALWAYS_INLINE volatile FuseRegisters &GetRegisters() {
return GetRegisterRegion()->fuse;
}
ALWAYS_INLINE volatile FuseChipRegisters &GetChipRegisters() {
return GetRegisterRegion()->chip;
}
}
void SetRegisterAddress(uintptr_t address) {
g_register_address = address;
}
void SetWriteSecureOnly() {
reg::Write(GetRegisters().FUSE_PRIVATEKEYDISABLE, FUSE_REG_BITS_ENUM(PRIVATEKEYDISABLE_TZ_STICKY_BIT_VAL, KEY_INVISIBLE));
}
void Lockout() {
reg::Write(GetRegisters().FUSE_DISABLEREGPROGRAM, FUSE_REG_BITS_ENUM(DISABLEREGPROGRAM_DISABLEREGPROGRAM_VAL, ENABLE));
}
u32 GetOdmWord(int index) {
return GetChipRegisters().FUSE_RESERVED_ODM[index];
}
HardwareType GetHardwareType() {
/* Read the odm word. */
const util::BitPack32 odm_word4 = { GetOdmWord(4) };
/* Get the value. */
const auto value = GetHardwareTypeValue(odm_word4);
switch (value) {
case 0x01: return HardwareType_Icosa;
case 0x02: return (true /* TODO: GetSocType() == SocType_Mariko */) ? HardwareType_Calcio : HardwareType_Copper;
case 0x04: return HardwareType_Iowa;
case 0x08: return HardwareType_Hoag;
case 0x10: return HardwareType_Five;
default: return HardwareType_Undefined;
}
}
HardwareState GetHardwareState() {
/* Read the odm word. */
const util::BitPack32 odm_word4 = { GetOdmWord(4) };
/* Get the value. */
const auto value = GetHardwareStateValue(odm_word4);
switch (value) {
case 3: return HardwareState_Development;
case 4: return HardwareState_Production;
default: return HardwareState_Undefined;
}
}
pmic::Regulator GetRegulator() {
/* TODO: How should mariko be handled? This reads from ODM word 28 in fuses (not presesnt in erista...). */
return pmic::Regulator_Erista_Max77621;
}
}

View File

@ -0,0 +1,221 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::fuse {
struct FuseRegisters {
u32 FUSE_FUSECTRL;
u32 FUSE_FUSEADDR;
u32 FUSE_FUSERDATA;
u32 FUSE_FUSEWDATA;
u32 FUSE_FUSETIME_RD1;
u32 FUSE_FUSETIME_RD2;
u32 FUSE_FUSETIME_PGM1;
u32 FUSE_FUSETIME_PGM2;
u32 FUSE_PRIV2INTFC_START;
u32 FUSE_FUSEBYPASS;
u32 FUSE_PRIVATEKEYDISABLE;
u32 FUSE_DISABLEREGPROGRAM;
u32 FUSE_WRITE_ACCESS_SW;
u32 FUSE_PWR_GOOD_SW;
u32 _0x38;
u32 FUSE_PRIV2RESHIFT;
u32 _0x40[0x3];
u32 FUSE_FUSETIME_RD3;
u32 _0x50[0xC];
u32 FUSE_PRIVATE_KEY0_NONZERO;
u32 FUSE_PRIVATE_KEY1_NONZERO;
u32 FUSE_PRIVATE_KEY2_NONZERO;
u32 FUSE_PRIVATE_KEY3_NONZERO;
u32 FUSE_PRIVATE_KEY4_NONZERO;
u32 _0x94[0x1B];
};
static_assert(util::is_pod<FuseRegisters>::value);
static_assert(sizeof(FuseRegisters) == 0x100);
struct FuseChipRegisters {
u32 FUSE_PRODUCTION_MODE;
u32 FUSE_JTAG_SECUREID_VALID;
u32 FUSE_ODM_LOCK;
u32 FUSE_OPT_OPENGL_EN;
u32 FUSE_SKU_INFO;
u32 FUSE_CPU_SPEEDO_0_CALIB;
u32 FUSE_CPU_IDDQ_CALIB;
u32 FUSE_DAC_CRT_CALIB;
u32 FUSE_DAC_HDTV_CALIB;
u32 FUSE_DAC_SDTV_CALIB;
u32 FUSE_OPT_FT_REV;
u32 FUSE_CPU_SPEEDO_1_CALIB;
u32 FUSE_CPU_SPEEDO_2_CALIB;
u32 FUSE_SOC_SPEEDO_0_CALIB;
u32 FUSE_SOC_SPEEDO_1_CALIB;
u32 FUSE_SOC_SPEEDO_2_CALIB;
u32 FUSE_SOC_IDDQ_CALIB;
u32 FUSE_RESERVED_PRODUCTION_WP;
u32 FUSE_FA;
u32 FUSE_RESERVED_PRODUCTION;
u32 FUSE_HDMI_LANE0_CALIB;
u32 FUSE_HDMI_LANE1_CALIB;
u32 FUSE_HDMI_LANE2_CALIB;
u32 FUSE_HDMI_LANE3_CALIB;
u32 FUSE_ENCRYPTION_RATE;
u32 FUSE_PUBLIC_KEY[0x8];
u32 FUSE_TSENSOR1_CALIB;
u32 FUSE_TSENSOR2_CALIB;
u32 FUSE_VSENSOR_CALIB;
u32 FUSE_OPT_CP_REV;
u32 FUSE_OPT_PFG;
u32 FUSE_TSENSOR0_CALIB;
u32 FUSE_FIRST_BOOTROM_PATCH_SIZE;
u32 FUSE_SECURITY_MODE;
u32 FUSE_PRIVATE_KEY[0x5];
u32 FUSE_ARM_JTAG_DIS;
u32 FUSE_BOOT_DEVICE_INFO;
u32 FUSE_RESERVED_SW;
u32 FUSE_OPT_VP9_DISABLE;
u32 FUSE_RESERVED_ODM[0x8];
u32 FUSE_OBS_DIS;
u32 FUSE_NOR_INFO;
u32 FUSE_USB_CALIB;
u32 FUSE_SKU_DIRECT_CONFIG;
u32 FUSE_KFUSE_PRIVKEY_CTRL;
u32 FUSE_PACKAGE_INFO;
u32 FUSE_OPT_VENDOR_CODE;
u32 FUSE_OPT_FAB_CODE;
u32 FUSE_OPT_LOT_CODE_0;
u32 FUSE_OPT_LOT_CODE_1;
u32 FUSE_OPT_WAFER_ID;
u32 FUSE_OPT_X_COORDINATE;
u32 FUSE_OPT_Y_COORDINATE;
u32 FUSE_OPT_SEC_DEBUG_EN;
u32 FUSE_OPT_OPS_RESERVED;
u32 FUSE_SATA_CALIB;
u32 FUSE_GPU_IDDQ_CALIB;
u32 FUSE_TSENSOR3_CALIB;
u32 FUSE_SKU_BOND_OUT_L;
u32 FUSE_SKU_BOND_OUT_H;
u32 FUSE_SKU_BOND_OUT_U;
u32 FUSE_SKU_BOND_OUT_V;
u32 FUSE_SKU_BOND_OUT_W;
u32 FUSE_OPT_SAMPLE_TYPE;
u32 FUSE_OPT_SUBREVISION;
u32 FUSE_OPT_SW_RESERVED_0;
u32 FUSE_OPT_SW_RESERVED_1;
u32 FUSE_TSENSOR4_CALIB;
u32 FUSE_TSENSOR5_CALIB;
u32 FUSE_TSENSOR6_CALIB;
u32 FUSE_TSENSOR7_CALIB;
u32 FUSE_OPT_PRIV_SEC_EN;
u32 FUSE_PKC_DISABLE;
u32 _0x16C;
u32 _0x170;
u32 _0x174;
u32 _0x178;
u32 FUSE_FUSE2TSEC_DEBUG_DISABLE;
u32 FUSE_TSENSOR_COMMON;
u32 FUSE_OPT_CP_BIN;
u32 FUSE_OPT_GPU_DISABLE;
u32 FUSE_OPT_FT_BIN;
u32 FUSE_OPT_DONE_MAP;
u32 _0x194;
u32 FUSE_APB2JTAG_DISABLE;
u32 FUSE_ODM_INFO;
u32 _0x1A0;
u32 _0x1A4;
u32 FUSE_ARM_CRYPT_DE_FEATURE;
u32 _0x1AC;
u32 _0x1B0;
u32 _0x1B4;
u32 _0x1B8;
u32 _0x1BC;
u32 FUSE_WOA_SKU_FLAG;
u32 FUSE_ECO_RESERVE_1;
u32 FUSE_GCPLEX_CONFIG_FUSE;
u32 FUSE_PRODUCTION_MONTH;
u32 FUSE_RAM_REPAIR_INDICATOR;
u32 FUSE_TSENSOR9_CALIB;
u32 _0x1D8;
u32 FUSE_VMIN_CALIBRATION;
u32 FUSE_AGING_SENSOR_CALIBRATION;
u32 FUSE_DEBUG_AUTHENTICATION;
u32 FUSE_SECURE_PROVISION_INDEX;
u32 FUSE_SECURE_PROVISION_INFO;
u32 FUSE_OPT_GPU_DISABLE_CP1;
u32 FUSE_SPARE_ENDIS;
u32 FUSE_ECO_RESERVE_0;
u32 _0x1FC;
u32 _0x200;
u32 FUSE_RESERVED_CALIB0;
u32 FUSE_RESERVED_CALIB1;
u32 FUSE_OPT_GPU_TPC0_DISABLE;
u32 FUSE_OPT_GPU_TPC0_DISABLE_CP1;
u32 FUSE_OPT_CPU_DISABLE;
u32 FUSE_OPT_CPU_DISABLE_CP1;
u32 FUSE_TSENSOR10_CALIB;
u32 FUSE_TSENSOR10_CALIB_AUX;
u32 FUSE_OPT_RAM_SVOP_DP;
u32 FUSE_OPT_RAM_SVOP_PDP;
u32 FUSE_OPT_RAM_SVOP_REG;
u32 FUSE_OPT_RAM_SVOP_SP;
u32 FUSE_OPT_RAM_SVOP_SMPDP;
u32 FUSE_OPT_GPU_TPC0_DISABLE_CP2;
u32 FUSE_OPT_GPU_TPC1_DISABLE;
u32 FUSE_OPT_GPU_TPC1_DISABLE_CP1;
u32 FUSE_OPT_GPU_TPC1_DISABLE_CP2;
u32 FUSE_OPT_CPU_DISABLE_CP2;
u32 FUSE_OPT_GPU_DISABLE_CP2;
u32 FUSE_USB_CALIB_EXT;
u32 FUSE_RESERVED_FIELD;
u32 FUSE_OPT_ECC_EN;
u32 _0x25C;
u32 _0x260;
u32 _0x264;
u32 _0x268;
u32 _0x26C;
u32 _0x270;
u32 _0x274;
u32 _0x278;
u32 FUSE_SPARE_REALIGNMENT_REG;
u32 FUSE_SPARE_BIT[0x20];
};
static_assert(util::is_pod<FuseChipRegisters>::value);
static_assert(sizeof(FuseChipRegisters) == 0x300);
struct FuseRegisterRegion {
FuseRegisters fuse;
FuseChipRegisters chip;
};
static_assert(util::is_pod<FuseRegisterRegion>::value);
static_assert(sizeof(FuseRegisterRegion) == secmon::MemoryRegionPhysicalDeviceFuses.GetSize());
#define FUSE_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (FUSE, NAME)
#define FUSE_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (FUSE, NAME, VALUE)
#define FUSE_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (FUSE, NAME, ENUM)
#define FUSE_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(FUSE, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_FUSE_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (FUSE, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_FUSE_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (FUSE, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_FUSE_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (FUSE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_FUSE_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(FUSE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_FUSE_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (FUSE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
DEFINE_FUSE_REG_BIT_ENUM(PRIVATEKEYDISABLE_TZ_STICKY_BIT_VAL, 4, KEY_VISIBLE, KEY_INVISIBLE);
DEFINE_FUSE_REG_BIT_ENUM(PRIVATEKEYDISABLE_PRIVATEKEYDISABLE_VAL_KEY, 0, VISIBLE, INVISIBLE);
DEFINE_FUSE_REG_BIT_ENUM(DISABLEREGPROGRAM_DISABLEREGPROGRAM_VAL, 0, DISABLE, ENABLE);
}

View File

@ -0,0 +1,217 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::gic {
namespace {
struct GicDistributor {
u32 ctlr;
u32 typer;
u32 iidr;
u32 reserved_0x0c;
u32 statusr;
u32 reserved_0x14[3];
u32 impldef_0x20[8];
u32 setspi_nsr;
u32 reserved_0x44;
u32 clrspi_nsr;
u32 reserved_0x4c;
u32 setspi_sr;
u32 reserved_0x54;
u32 clrspi_sr;
u32 reserved_0x5c[9];
u32 igroupr[32];
u32 isenabler[32];
u32 icenabler[32];
u32 ispendr[32];
u32 icpendr[32];
u32 isactiver[32];
u32 icactiver[32];
union {
u8 bytes[1020];
u32 words[255];
} ipriorityr;
u32 _0x7fc;
union {
u8 bytes[1020];
u32 words[255];
} itargetsr;
u32 _0xbfc;
u32 icfgr[64];
u32 igrpmodr[32];
u32 _0xd80[32];
u32 nsacr[64];
u32 sgir;
u32 _0xf04[3];
u32 cpendsgir[4];
u32 spendsgir[4];
u32 reserved_0xf30[52];
static constexpr size_t SgirCpuTargetListShift = 16;
enum SgirTargetListFilter : u32 {
SgirTargetListFilter_CpuTargetList = (0 << 24),
SgirTargetListFilter_Others = (1 << 24),
SgirTargetListFilter_Self = (2 << 24),
SgirTargetListFilter_Reserved = (3 << 24),
};
};
static_assert(util::is_pod<GicDistributor>::value);
static_assert(sizeof(GicDistributor) == 0x1000);
static_assert(sizeof(GicDistributor) == secmon::MemoryRegionPhysicalDeviceGicDistributor.GetSize());
struct GicCpuInterface {
u32 ctlr;
u32 pmr;
u32 bpr;
u32 iar;
u32 eoir;
u32 rpr;
u32 hppir;
u32 abpr;
u32 aiar;
u32 aeoir;
u32 ahppir;
u32 statusr;
u32 reserved_30[4];
u32 impldef_40[36];
u32 apr[4];
u32 nsapr[4];
u32 reserved_f0[3];
u32 iidr;
u32 reserved_100[960];
u32 dir;
u32 _0x1004[1023];
};
static_assert(util::is_pod<GicCpuInterface>::value);
static_assert(sizeof(GicCpuInterface) == 0x2000);
static_assert(sizeof(GicCpuInterface) == secmon::MemoryRegionPhysicalDeviceGicCpuInterface.GetSize());
constexpr inline int InterruptWords = InterruptCount / BITSIZEOF(u32);
constexpr inline int SpiIndex = BITSIZEOF(u32);
constinit uintptr_t g_distributor_address = secmon::MemoryRegionPhysicalDeviceGicDistributor.GetAddress();
constinit uintptr_t g_cpu_interface_address = secmon::MemoryRegionPhysicalDeviceGicCpuInterface.GetAddress();
volatile GicDistributor *GetDistributor() {
return reinterpret_cast<volatile GicDistributor *>(g_distributor_address);
}
volatile GicCpuInterface *GetCpuInterface() {
return reinterpret_cast<volatile GicCpuInterface *>(g_cpu_interface_address);
}
void ReadWrite(uintptr_t address, int width, int i, u32 value) {
/* This code will never be invoked with a negative interrupt id. */
AMS_ASSUME(i >= 0);
const int scale = BITSIZEOF(u32) / width;
const int word = i / scale;
const int bit = (i % scale) * width;
reg::ReadWrite(address + sizeof(u32) * word, REG_BITS_VALUE(bit, width, value));
}
void Write(uintptr_t address, int width, int i, u32 value) {
/* This code will never be invoked with a negative interrupt id. */
AMS_ASSUME(i >= 0);
const int scale = BITSIZEOF(u32) / width;
const int word = i / scale;
const int bit = (i % scale) * width;
reg::Write(address + sizeof(u32) * word, value << bit);
}
}
void SetRegisterAddress(uintptr_t distributor_address, uintptr_t cpu_interface_address) {
g_distributor_address = distributor_address;
g_cpu_interface_address = cpu_interface_address;
}
void InitializeCommon() {
/* Get the gicd registers. */
auto *gicd = GetDistributor();
/* Set IGROUPR for to be FFs. */
for (int i = SpiIndex / BITSIZEOF(u32); i < InterruptWords; ++i) {
gicd->igroupr[i] = 0xFFFFFFFFu;
}
/* Set IPRIORITYR for spi interrupts to be 0x80. */
for (int i = SpiIndex; i < InterruptCount; ++i) {
gicd->ipriorityr.bytes[i] = 0x80;
}
/* Enable group 0. */
gicd->ctlr = 1;
}
void InitializeCoreUnique() {
/* Get the registers. */
auto *gicd = GetDistributor();
auto *gicc = GetCpuInterface();
/* Set IGROUPR0 to be FFs. */
gicd->igroupr[0] = 0xFFFFFFFFu;
/* Set IPRIORITYR for core local interrupts to be 0x80. */
for (int i = 0; i < SpiIndex; ++i) {
gicd->ipriorityr.bytes[i] = 0x80;
}
/* Enable group 0 as FIQs. */
gicc->ctlr = 0x1D9;
/* Set PMR. */
gicc->pmr = 0x80;
/* Set BPR. */
gicc->bpr = 7;
}
void SetPriority(int interrupt_id, int priority) {
ReadWrite(g_distributor_address + offsetof(GicDistributor, ipriorityr), BITSIZEOF(u8), interrupt_id, priority);
}
void SetInterruptGroup(int interrupt_id, int group) {
ReadWrite(g_distributor_address + offsetof(GicDistributor, igroupr), 1, interrupt_id, group);
}
void SetEnable(int interrupt_id, bool enable) {
Write(g_distributor_address + offsetof(GicDistributor, isenabler), 1, interrupt_id, enable);
}
void SetSpiTargetCpu(int interrupt_id, u32 cpu_mask) {
ReadWrite(g_distributor_address + offsetof(GicDistributor, itargetsr), BITSIZEOF(u8), interrupt_id, cpu_mask);
}
void SetSpiMode(int interrupt_id, InterruptMode mode) {
ReadWrite(g_distributor_address + offsetof(GicDistributor, icfgr), 2, interrupt_id, static_cast<u32>(mode) << 1);
}
int GetInterruptRequestId() {
return reg::Read(GetCpuInterface()->iar);
}
void SetEndOfInterrupt(int interrupt_id) {
reg::Write(GetCpuInterface()->eoir, interrupt_id);
}
}

View File

@ -0,0 +1,29 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::hw::arch::arm64 {
void FlushDataCache(const void *ptr, size_t size) {
const uintptr_t start = reinterpret_cast<uintptr_t>(ptr);
const uintptr_t end = util::AlignUp(start + size, hw::DataCacheLineSize);
for (uintptr_t cur = start; cur < end; cur += hw::DataCacheLineSize) {
FlushDataCacheLine(reinterpret_cast<void *>(cur));
}
}
}

View File

@ -0,0 +1,202 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "i2c_registers.hpp"
namespace ams::i2c {
namespace {
constexpr inline size_t MaxTransferSize = sizeof(u32);
constinit std::array<uintptr_t, Port_Count> g_register_addresses = [] {
std::array<uintptr_t, Port_Count> arr = {};
arr[Port_1] = secmon::MemoryRegionPhysicalDeviceI2c1.GetAddress();
arr[Port_5] = secmon::MemoryRegionPhysicalDeviceI2c5.GetAddress();
return arr;
}();
void LoadConfig(uintptr_t address) {
/* Configure for TIMEOUT and MSTR config load. */
/* NOTE: Nintendo writes value 1 to reserved bit 5 here. This bit is documented as having no meaning. */
/* We will reproduce the write just in case it is undocumented. */
reg::Write(address + I2C_CONFIG_LOAD, I2C_REG_BITS_VALUE(CONFIG_LOAD_RESERVED_BIT_5, 1),
I2C_REG_BITS_ENUM (CONFIG_LOAD_TIMEOUT_CONFIG_LOAD, ENABLE),
I2C_REG_BITS_ENUM (CONFIG_LOAD_SLV_CONFIG_LOAD, DISABLE),
I2C_REG_BITS_ENUM (CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
/* Wait up to 20 microseconds for the master config to be loaded. */
for (int i = 0; i < 20; ++i) {
if (reg::HasValue(address + I2C_CONFIG_LOAD, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, DISABLE))) {
return;
}
util::WaitMicroSeconds(1);
}
}
void ClearBus(uintptr_t address) {
/* Configure the bus clear register. */
reg::Write(address + I2C_BUS_CLEAR_CONFIG, I2C_REG_BITS_VALUE(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 9),
I2C_REG_BITS_ENUM (BUS_CLEAR_CONFIG_BC_STOP_COND, NO_STOP),
I2C_REG_BITS_ENUM (BUS_CLEAR_CONFIG_BC_TERMINATE, IMMEDIATE),
I2C_REG_BITS_ENUM (BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE));
/* Load the config. */
LoadConfig(address);
/* Wait up to 250us (in 25 us increments) until the bus clear is done. */
for (int i = 0; i < 10; ++i) {
if (reg::HasValue(address + I2C_INTERRUPT_STATUS_REGISTER, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_BUS_CLEAR_DONE, SET))) {
break;
}
util::WaitMicroSeconds(25);
}
/* Read the bus clear status. */
reg::Read(address + I2C_BUS_CLEAR_STATUS);
}
void InitializePort(uintptr_t address) {
/* Calculate the divisor. */
constexpr int Divisor = util::DivideUp(19200, 8 * 400);
/* Set the divisor. */
reg::Write(address + I2C_CLK_DIVISOR_REGISTER, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_STD_FAST_MODE, Divisor - 1),
I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_HSMODE, 1));
/* Clear the bus. */
ClearBus(address);
/* Clear the status. */
reg::Write(address + I2C_INTERRUPT_STATUS_REGISTER, reg::Read(address + I2C_INTERRUPT_STATUS_REGISTER));
}
bool Write(uintptr_t base_address, Port port, int address, const void *src, size_t src_size, bool unused) {
/* Ensure we don't write too much. */
u32 data = 0;
if (src_size > MaxTransferSize) {
return false;
}
/* Copy the data to a transfer word. */
std::memcpy(std::addressof(data), src, src_size);
/* Configure the to write the 7-bit address. */
reg::Write(base_address + I2C_I2C_CMD_ADDR0, I2C_REG_BITS_VALUE(I2C_CMD_ADDR0_7BIT_ADDR, address),
I2C_REG_BITS_ENUM (I2C_CMD_ADDR0_7BIT_RW, WRITE));
/* Configure to write the data. */
reg::Write(base_address + I2C_I2C_CMD_DATA1, data);
/* Configure to write the correct amount of data. */
reg::Write(base_address + I2C_I2C_CNFG, I2C_REG_BITS_ENUM (I2C_CNFG_DEBOUNCE_CNT, DEBOUNCE_4T),
I2C_REG_BITS_ENUM (I2C_CNFG_NEW_MASTER_FSM, ENABLE),
I2C_REG_BITS_ENUM (I2C_CNFG_CMD1, WRITE),
I2C_REG_BITS_VALUE(I2C_CNFG_LENGTH, src_size - 1));
/* Load the configuration. */
LoadConfig(base_address);
/* Start the command. */
reg::ReadWrite(base_address + I2C_I2C_CNFG, I2C_REG_BITS_ENUM(I2C_CNFG_SEND, GO));
/* Wait for the command to be done. */
while (!reg::HasValue(base_address + I2C_I2C_STATUS, I2C_REG_BITS_ENUM(I2C_STATUS_BUSY, NOT_BUSY))) { /* ... */ }
/* Check if the transfer was successful. */
return reg::HasValue(base_address + I2C_I2C_STATUS, I2C_REG_BITS_ENUM(I2C_STATUS_CMD1_STAT, SL1_XFER_SUCCESSFUL));
}
bool Read(uintptr_t base_address, Port port, void *dst, size_t dst_size, int address, bool unused) {
/* Ensure we don't read too much. */
if (dst_size > MaxTransferSize) {
return false;
}
/* Configure the to read the 7-bit address. */
reg::Write(base_address + I2C_I2C_CMD_ADDR0, I2C_REG_BITS_VALUE(I2C_CMD_ADDR0_7BIT_ADDR, address),
I2C_REG_BITS_ENUM (I2C_CMD_ADDR0_7BIT_RW, READ));
/* Configure to read the correct amount of data. */
reg::Write(base_address + I2C_I2C_CNFG, I2C_REG_BITS_ENUM (I2C_CNFG_DEBOUNCE_CNT, DEBOUNCE_4T),
I2C_REG_BITS_ENUM (I2C_CNFG_NEW_MASTER_FSM, ENABLE),
I2C_REG_BITS_ENUM (I2C_CNFG_CMD1, READ),
I2C_REG_BITS_VALUE(I2C_CNFG_LENGTH, dst_size - 1));
/* Load the configuration. */
LoadConfig(base_address);
/* Start the command. */
reg::ReadWrite(base_address + I2C_I2C_CNFG, I2C_REG_BITS_ENUM(I2C_CNFG_SEND, GO));
/* Wait for the command to be done. */
while (!reg::HasValue(base_address + I2C_I2C_STATUS, I2C_REG_BITS_ENUM(I2C_STATUS_BUSY, NOT_BUSY))) { /* ... */ }
/* Check that the transfer was successful. */
if (!reg::HasValue(base_address + I2C_I2C_STATUS, I2C_REG_BITS_ENUM(I2C_STATUS_CMD1_STAT, SL1_XFER_SUCCESSFUL))) {
return false;
}
/* Read and copy out the data. */
u32 data = reg::Read(base_address + I2C_I2C_CMD_DATA1);
std::memcpy(dst, std::addressof(data), dst_size);
return true;
}
}
void SetRegisterAddress(Port port, uintptr_t address) {
g_register_addresses[port] = address;
}
void Initialize(Port port) {
InitializePort(g_register_addresses[port]);
}
bool Query(void *dst, size_t dst_size, Port port, int address, int r) {
const uintptr_t base_address = g_register_addresses[port];
/* Select the register we want to read. */
bool success = Write(base_address, port, address, std::addressof(r), 1, false);
if (success) {
/* If we successfully selected, read data from the register. */
success = Read(base_address, port, dst, dst_size, address, true);
}
return success;
}
bool Send(Port port, int address, int r, const void *src, size_t src_size) {
const uintptr_t base_address = g_register_addresses[port];
/* Create a transfer buffer, make sure we can use it. */
u8 buffer[MaxTransferSize];
if (src_size > sizeof(buffer) - 1) {
return false;
}
/* Copy data into the buffer. */
buffer[0] = static_cast<u8>(r);
std::memcpy(buffer + 1, src, src_size);
return Write(base_address, port, address, buffer, src_size + 1, false);
}
}

View File

@ -0,0 +1,77 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::i2c {
#define I2C_I2C_CNFG (0x000)
#define I2C_I2C_CMD_ADDR0 (0x004)
#define I2C_I2C_CMD_DATA1 (0x00C)
#define I2C_I2C_STATUS (0x01C)
#define I2C_INTERRUPT_STATUS_REGISTER (0x068)
#define I2C_CLK_DIVISOR_REGISTER (0x06C)
#define I2C_BUS_CLEAR_CONFIG (0x084)
#define I2C_BUS_CLEAR_STATUS (0x088)
#define I2C_CONFIG_LOAD (0x08C)
#define I2C_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (I2C, NAME)
#define I2C_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (I2C, NAME, VALUE)
#define I2C_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (I2C, NAME, ENUM)
#define I2C_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(I2C, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_I2C_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (I2C, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_I2C_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_I2C_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_I2C_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_I2C_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
/* I2C_CNFG */
DEFINE_I2C_REG(I2C_CNFG_LENGTH, 1, 3);
DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_CMD1, 6, WRITE, READ);
DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_SEND, 9, NOP, GO);
DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_NEW_MASTER_FSM, 11, DISABLE, ENABLE);
DEFINE_I2C_REG_THREE_BIT_ENUM(I2C_CNFG_DEBOUNCE_CNT, 12, NO_DEBOUNCE, DEBOUNCE_2T, DEBOUNCE_4T, DEBOUNCE_6T, DEBOUNCE_8T, DEBOUNCE_10T, DEBOUNCE_12T, DEBOUNCE_14T);
/* I2C_CMD_ADDR0 */
DEFINE_I2C_REG_BIT_ENUM(I2C_CMD_ADDR0_7BIT_RW, 0, WRITE, READ);
DEFINE_I2C_REG(I2C_CMD_ADDR0_7BIT_ADDR, 1, 7);
/* I2C_STATUS */
DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD1_STAT, 0, SL1_XFER_SUCCESSFUL, SL1_NOACK_FOR_BYTE1, SL1_NOACK_FOR_BYTE2, SL1_NOACK_FOR_BYTE3, SL1_NOACK_FOR_BYTE4, SL1_NOACK_FOR_BYTE5, SL1_NOACK_FOR_BYTE6, SL1_NOACK_FOR_BYTE7, SL1_NOACK_FOR_BYTE8, SL1_NOACK_FOR_BYTE9, SL1_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15);
DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD2_STAT, 4, SL2_XFER_SUCCESSFUL, SL2_NOACK_FOR_BYTE1, SL2_NOACK_FOR_BYTE2, SL2_NOACK_FOR_BYTE3, SL2_NOACK_FOR_BYTE4, SL2_NOACK_FOR_BYTE5, SL2_NOACK_FOR_BYTE6, SL2_NOACK_FOR_BYTE7, SL2_NOACK_FOR_BYTE8, SL2_NOACK_FOR_BYTE9, SL2_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15);
DEFINE_I2C_REG_BIT_ENUM(I2C_STATUS_BUSY, 8, NOT_BUSY, BUSY);
/* INTERRUPT_STATUS_REGISTER */
DEFINE_I2C_REG_BIT_ENUM(INTERRUPT_STATUS_REGISTER_BUS_CLEAR_DONE, 11, UNSET, SET);
/* CLK_DIVISOR_REGISTER */
DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_HSMODE, 0, 16);
DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_STD_FAST_MODE, 16, 16);
/* BUS_CLEAR_CONFIG */
DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, 0, DISABLE, ENABLE);
DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, 1, THRESHOLD, IMMEDIATE);
DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, 2, NO_STOP, STOP);
DEFINE_I2C_REG(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 16, 8);
/* CONFIG_LOAD */
DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, 0, DISABLE, ENABLE);
DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_SLV_CONFIG_LOAD, 1, DISABLE, ENABLE);
DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_TIMEOUT_CONFIG_LOAD, 2, DISABLE, ENABLE);
DEFINE_I2C_REG(CONFIG_LOAD_RESERVED_BIT_5, 5, 1);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::log {
namespace {
constexpr inline uart::Port UartLogPort = uart::Port_ReservedDebug;
constinit bool g_initialized_uart = false;
constexpr inline u32 UartPortFlags = [] {
if constexpr (UartLogPort == uart::Port_ReservedDebug) {
/* Logging to the debug port. */
/* Don't invert transactions. */
return uart::Flag_None;
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) {
/* Logging to left joy-con (e.g. with Joyless). */
/* Invert transactions. */
return uart::Flag_Inverted;
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) {
/* Logging to right joy-con (e.g. with Joyless). */
/* Invert transactions. */
return uart::Flag_Inverted;
} else {
__builtin_unreachable();
}
}();
}
void Initialize() {
/* Initialize the target uart port. */
uart::Initialize(UartLogPort, 115200, UartPortFlags);
/* Note that we've initialized. */
g_initialized_uart = true;
}
}

View File

@ -0,0 +1,275 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::pmc {
namespace {
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
constexpr inline u32 WriteMask = 0x1;
constexpr inline u32 ReadMask = 0x2;
enum class LockMode {
Read,
Write,
ReadWrite,
};
template<LockMode Mode>
constexpr inline u32 LockMask = [] {
switch (Mode) {
case LockMode::Read: return ReadMask;
case LockMode::Write: return WriteMask;
case LockMode::ReadWrite: return ReadMask | WriteMask;
default: __builtin_unreachable();
}
}();
constexpr inline size_t NumSecureScratchRegisters = 120;
constexpr inline size_t NumSecureDisableRegisters = 8;
template<size_t SecureScratch> requires (SecureScratch < NumSecureScratchRegisters)
constexpr inline std::pair<size_t, size_t> DisableRegisterIndex = [] {
if constexpr (SecureScratch < 8) {
return std::pair<size_t, size_t>{0, 4 + 2 * SecureScratch};
} else {
constexpr size_t Relative = SecureScratch - 8;
return std::pair<size_t, size_t>{1 + (Relative / 16), 2 * (Relative % 16)};
}
}();
struct LockInfo {
size_t scratch;
LockMode mode;
};
template<LockInfo Info>
constexpr ALWAYS_INLINE void SetSecureScratchMask(std::array<u32, NumSecureDisableRegisters> &disables) {
constexpr std::pair<size_t, size_t> Location = DisableRegisterIndex<Info.scratch>;
disables[Location.first] |= LockMask<Info.mode> << Location.second;
}
template<LockInfo... Info>
constexpr ALWAYS_INLINE void SetSecureScratchMasks(std::array<u32, NumSecureDisableRegisters> &disables) {
(SetSecureScratchMask<Info>(disables), ...);
}
template<size_t... Ix>
constexpr ALWAYS_INLINE void SetSecureScratchReadWriteMasks(std::array<u32, NumSecureDisableRegisters> &disables) {
(SetSecureScratchMask<LockInfo{Ix, LockMode::ReadWrite}>(disables), ...);
}
template<size_t... Ix>
constexpr ALWAYS_INLINE void SetSecureScratchReadMasks(std::array<u32, NumSecureDisableRegisters> &disables) {
(SetSecureScratchMask<LockInfo{Ix, LockMode::Read}>(disables), ...);
}
template<size_t... Ix>
constexpr ALWAYS_INLINE void SetSecureScratchWriteMasks(std::array<u32, NumSecureDisableRegisters> &disables) {
(SetSecureScratchMask<LockInfo{Ix, LockMode::Write}>(disables), ...);
}
template<SecureRegister Register>
constexpr ALWAYS_INLINE std::array<u32, NumSecureDisableRegisters> GetSecureScratchMasks() {
std::array<u32, NumSecureDisableRegisters> disables = {};
if constexpr ((Register & SecureRegister_Other) != 0) {
constexpr std::array<u32, NumSecureDisableRegisters> NonOtherDisables = GetSecureScratchMasks<static_cast<SecureRegister>(~SecureRegister_Other)>();
for (size_t i = 0; i < NumSecureDisableRegisters; i++) {
disables[i] |= ~NonOtherDisables[i];
}
disables[0] &= 0x007FFFF0;
}
if constexpr ((Register & SecureRegister_DramParameters) != 0) {
SetSecureScratchReadWriteMasks< 8, 9, 10, 11, 12, 13, 14, 15,
17, 18, 19, 20,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
52, 53, 54,
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
79, 80, 81, 82, 83, 84,
86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
104, 105, 106, 107
>(disables);
}
if constexpr ((Register & SecureRegister_ResetVector) != 0) {
SetSecureScratchReadWriteMasks<34, 35>(disables);
}
if constexpr ((Register & SecureRegister_Carveout) != 0) {
SetSecureScratchReadWriteMasks<16, 39, 51, 55, 74, 75, 76, 77, 78, 99, 100, 101, 102, 103>(disables);
}
if constexpr ((Register & SecureRegister_CmacWrite) != 0) {
SetSecureScratchWriteMasks<112, 113, 114, 115>(disables);
}
if constexpr ((Register & SecureRegister_CmacRead) != 0) {
SetSecureScratchReadMasks<112, 113, 114, 115>(disables);
}
if constexpr ((Register & SecureRegister_KeySourceWrite) != 0) {
SetSecureScratchWriteMasks<24, 25, 26, 27>(disables);
}
if constexpr ((Register & SecureRegister_KeySourceRead) != 0) {
SetSecureScratchReadMasks<24, 25, 26, 27>(disables);
}
if constexpr ((Register & SecureRegister_Srk) != 0) {
SetSecureScratchReadWriteMasks<4, 5, 6, 7>(disables);
}
return disables;
}
/* Validate that the secure scratch masks produced are correct. */
#include "pmc_secure_scratch_test.inc"
ALWAYS_INLINE void LockBits(uintptr_t address, u32 mask) {
reg::Write(address, reg::Read(address) | mask);
}
template<SecureRegister Register>
ALWAYS_INLINE void SetSecureScratchMasks(uintptr_t address) {
constexpr auto Masks = GetSecureScratchMasks<Register>();
if constexpr (Masks[0] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE , Masks[0]); }
if constexpr (Masks[1] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE2, Masks[1]); }
if constexpr (Masks[2] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE3, Masks[2]); }
if constexpr (Masks[3] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE4, Masks[3]); }
if constexpr (Masks[4] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE5, Masks[4]); }
if constexpr (Masks[5] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE6, Masks[5]); }
if constexpr (Masks[6] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE7, Masks[6]); }
if constexpr (Masks[7] != 0) { LockBits(address + APBDEV_PMC_SEC_DISABLE8, Masks[7]); }
static_assert(Masks.size() == 8);
}
template<SecureRegister Register>
ALWAYS_INLINE bool TestSecureScratchMasks(uintptr_t address) {
constexpr auto Masks = GetSecureScratchMasks<Register>();
if constexpr (Masks[0] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE ) & Masks[0]) != Masks[0]) { return false; } }
if constexpr (Masks[1] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE2) & Masks[1]) != Masks[1]) { return false; } }
if constexpr (Masks[2] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE3) & Masks[2]) != Masks[2]) { return false; } }
if constexpr (Masks[3] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE4) & Masks[3]) != Masks[3]) { return false; } }
if constexpr (Masks[4] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE5) & Masks[4]) != Masks[4]) { return false; } }
if constexpr (Masks[5] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE6) & Masks[5]) != Masks[5]) { return false; } }
if constexpr (Masks[6] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE7) & Masks[6]) != Masks[6]) { return false; } }
if constexpr (Masks[7] != 0) { if ((reg::Read(address + APBDEV_PMC_SEC_DISABLE8) & Masks[7]) != Masks[7]) { return false; } }
static_assert(Masks.size() == 8);
return true;
}
NOINLINE void WriteRandomValueToRegister(uintptr_t offset) {
/* Create an aligned buffer. */
util::AlignedBuffer<hw::DataCacheLineSize, sizeof(u32)> buf;
/* Generate random bytes into it. */
se::GenerateRandomBytes(buf, sizeof(u32));
/* Read the random value. */
const u32 random = *reinterpret_cast<const u32 *>(static_cast<u8 *>(buf));
/* Get the address. */
const uintptr_t address = g_register_address + offset;
/* Write the value. */
reg::Write(address, random);
/* Verify it was written. */
AMS_ABORT_UNLESS(reg::Read(address) == random);
}
}
void SetRegisterAddress(uintptr_t address) {
g_register_address = address;
}
void InitializeRandomScratch() {
/* Write random data to the scratch that contains the SRK. */
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH4);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH5);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH6);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH7);
/* Lock the SRK scratch. */
LockSecureRegister(SecureRegister_Srk);
/* Write random data to the scratch used for tzram cmac. */
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH112);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH113);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH114);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH115);
/* Write random data to the scratch used for tzram key source. */
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH24);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH25);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH26);
WriteRandomValueToRegister(APBDEV_PMC_SECURE_SCRATCH27);
/* Here, Nintendo locks the SRK scratch a second time. */
/* This may just be "to be sure". */
LockSecureRegister(SecureRegister_Srk);
}
void LockSecureRegister(SecureRegister reg) {
/* Get the address. */
const uintptr_t address = g_register_address;
/* Apply each mask. */
#define PMC_PROCESS_REG(REG) do { if ((reg & SecureRegister_##REG) != 0) { SetSecureScratchMasks<SecureRegister_##REG>(address); } } while (0)
PMC_PROCESS_REG(Other);
PMC_PROCESS_REG(DramParameters);
PMC_PROCESS_REG(ResetVector);
PMC_PROCESS_REG(Carveout);
PMC_PROCESS_REG(CmacWrite);
PMC_PROCESS_REG(CmacRead);
PMC_PROCESS_REG(KeySourceWrite);
PMC_PROCESS_REG(KeySourceRead);
PMC_PROCESS_REG(Srk);
#undef PMC_PROCESS_REG
}
LockState GetSecureRegisterLockState(SecureRegister reg) {
bool all_valid = true;
bool any_valid = false;
/* Get the address. */
const uintptr_t address = g_register_address;
/* Test each mask. */
#define PMC_PROCESS_REG(REG) do { if ((reg & SecureRegister_##REG) != 0) { const bool test = TestSecureScratchMasks<SecureRegister_##REG>(address); all_valid &= test; any_valid |= test; } } while (0)
PMC_PROCESS_REG(Other);
PMC_PROCESS_REG(DramParameters);
PMC_PROCESS_REG(ResetVector);
PMC_PROCESS_REG(Carveout);
PMC_PROCESS_REG(CmacWrite);
PMC_PROCESS_REG(CmacRead);
PMC_PROCESS_REG(KeySourceWrite);
PMC_PROCESS_REG(KeySourceRead);
PMC_PROCESS_REG(Srk);
#undef PMC_PROCESS_REG
if (all_valid) {
return LockState::Locked;
} else if (any_valid) {
return LockState::PartiallyLocked;
} else {
return LockState::NotLocked;
}
}
}

View File

@ -0,0 +1,100 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
namespace test {
constexpr inline auto Other = GetSecureScratchMasks<SecureRegister_Other>();
static_assert(Other[0] == 0x00700FF0u);
static_assert(Other[1] == 0xFC000000u);
static_assert(Other[2] == 0x3F0FFF00u);
static_assert(Other[3] == 0x00000000u);
static_assert(Other[4] == 0x00000000u);
static_assert(Other[5] == 0x0C000000u);
static_assert(Other[6] == 0x00000000u);
static_assert(Other[7] == 0xFF00FF00u);
constexpr inline auto DramParameters = GetSecureScratchMasks<SecureRegister_DramParameters>();
static_assert(DramParameters[0] == 0x00000000u);
static_assert(DramParameters[1] == 0x03FCFFFFu);
static_assert(DramParameters[2] == 0x00000000u);
static_assert(DramParameters[3] == 0x3F3FFFFFu);
static_assert(DramParameters[4] == 0xFFFFFFFFu);
static_assert(DramParameters[5] == 0xF3FFC00Fu);
static_assert(DramParameters[6] == 0x003FFFFFu);
static_assert(DramParameters[7] == 0x000000FFu);
constexpr inline auto ResetVector = GetSecureScratchMasks<SecureRegister_ResetVector>();
static_assert(ResetVector[0] == 0x00000000u);
static_assert(ResetVector[1] == 0x00000000u);
static_assert(ResetVector[2] == 0x00F00000u);
static_assert(ResetVector[3] == 0x00000000u);
static_assert(ResetVector[4] == 0x00000000u);
static_assert(ResetVector[5] == 0x00000000u);
static_assert(ResetVector[6] == 0x00000000u);
static_assert(ResetVector[7] == 0x00000000u);
constexpr inline auto CmacWrite = GetSecureScratchMasks<SecureRegister_CmacWrite>();
static_assert(CmacWrite[0] == 0x00000000u);
static_assert(CmacWrite[1] == 0x00000000u);
static_assert(CmacWrite[2] == 0x00000000u);
static_assert(CmacWrite[3] == 0x00000000u);
static_assert(CmacWrite[4] == 0x00000000u);
static_assert(CmacWrite[5] == 0x00000000u);
static_assert(CmacWrite[6] == 0x00000000u);
static_assert(CmacWrite[7] == 0x00550000u);
constexpr inline auto CmacRead = GetSecureScratchMasks<SecureRegister_CmacRead>();
static_assert(CmacRead[0] == 0x00000000u);
static_assert(CmacRead[1] == 0x00000000u);
static_assert(CmacRead[2] == 0x00000000u);
static_assert(CmacRead[3] == 0x00000000u);
static_assert(CmacRead[4] == 0x00000000u);
static_assert(CmacRead[5] == 0x00000000u);
static_assert(CmacRead[6] == 0x00000000u);
static_assert(CmacRead[7] == 0x00AA0000u);
constexpr inline auto KeySourceWrite = GetSecureScratchMasks<SecureRegister_KeySourceWrite>();
static_assert(KeySourceWrite[0] == 0x00000000u);
static_assert(KeySourceWrite[1] == 0x00000000u);
static_assert(KeySourceWrite[2] == 0x00000055u);
static_assert(KeySourceWrite[3] == 0x00000000u);
static_assert(KeySourceWrite[4] == 0x00000000u);
static_assert(KeySourceWrite[5] == 0x00000000u);
static_assert(KeySourceWrite[6] == 0x00000000u);
static_assert(KeySourceWrite[7] == 0x00000000u);
constexpr inline auto KeySourceRead = GetSecureScratchMasks<SecureRegister_KeySourceRead>();
static_assert(KeySourceRead[0] == 0x00000000u);
static_assert(KeySourceRead[1] == 0x00000000u);
static_assert(KeySourceRead[2] == 0x000000AAu);
static_assert(KeySourceRead[3] == 0x00000000u);
static_assert(KeySourceRead[4] == 0x00000000u);
static_assert(KeySourceRead[5] == 0x00000000u);
static_assert(KeySourceRead[6] == 0x00000000u);
static_assert(KeySourceRead[7] == 0x00000000u);
constexpr inline auto Srk = GetSecureScratchMasks<SecureRegister_Srk>();
static_assert(Srk[0] == 0x000FF000u);
static_assert(Srk[1] == 0x00000000u);
static_assert(Srk[2] == 0x00000000u);
static_assert(Srk[3] == 0x00000000u);
static_assert(Srk[4] == 0x00000000u);
static_assert(Srk[5] == 0x00000000u);
static_assert(Srk[6] == 0x00000000u);
static_assert(Srk[7] == 0x00000000u);
}

View File

@ -0,0 +1,340 @@
/*
* Defining registers address and its bit definitions of MAX77620 and MAX20024
*
* Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2019 CTCaer
*
* 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
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
#define MAX77620_REG_CNFGGLBL1 0x00
#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_100 (0 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4)
#define MAX77620_CNFGGLBL1_LBDAC_MASK 0x0E
#define MAX77620_CNFGGLBL1_LBDAC_2700 (0 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_2800 (1 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_2900 (2 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3000 (3 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3100 (4 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3200 (5 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3300 (6 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3400 (7 << 1)
#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0)
#define MAX77620_REG_CNFGGLBL2 0x01
#define MAX77620_REG_CNFGGLBL3 0x02
#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_REG_CNFG1_32K 0x03
#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2)
#define MAX77620_REG_CNFGBBC 0x04
#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_CNFGBBC_RESISTOR_100 (0 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_CNFGBBC_RESISTOR_1K (1 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_CNFGBBC_RESISTOR_3K (2 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_REG_IRQTOP 0x05
#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_REG_INTLBT 0x06
#define MAX77620_REG_IRQTOPM 0x0D
#define MAX77620_IRQ_LBM_MASK (1 << 3)
#define MAX77620_IRQ_TJALRM1_MASK (1 << 2)
#define MAX77620_IRQ_TJALRM2_MASK (1 << 1)
#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_INTENLBT 0x0E
#define MAX77620_GLBLM_MASK (1 << 0)
#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_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_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_LDO_POWER_MODE_MASK 0xC0
#define MAX77620_LDO_POWER_MODE_SHIFT 6
#define MAX77620_POWER_MODE_NORMAL 3
#define MAX77620_POWER_MODE_LPM 2
#define MAX77620_POWER_MODE_GLPM 1
#define MAX77620_POWER_MODE_DISABLE 0
#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2)
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
#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_REG_LDO_CFG3 0x35
#define MAX77620_TRACK4_MASK (1 << 5)
#define MAX77620_TRACK4_SHIFT 5
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
#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_CNFG_GPIO_DRV_MASK (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0)
#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_OUTPUT (0 << 1)
#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 << 3)
#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_REG_ONOFFCNFG1 0x41
#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_REG_ONOFFCNFG2 0x42
#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)
/* 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
/* Minimum and maximum FPS period time (in microseconds) are
* different for MAX77620 and Max20024.
*/
#define MAX77620_FPS_COUNT 3
#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_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
#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)
#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)
/* 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_ */

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _MAX7762X_H_
#define _MAX7762X_H_
/*
* Switch Power domains (max77620):
* Name | Usage | uV step | uV min | uV default | uV max | Init
*-------+---------------+---------+--------+------------+---------+------------------
* sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 |
* ldo5 | GC ASIC | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
*/
/*
* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode
* MAX77620_REG_GPIOx: 0x9 sets output and enable
*/
/*! MAX77620 partitions. */
#define REGULATOR_SD0 0
#define REGULATOR_SD1 1
#define REGULATOR_SD2 2
#define REGULATOR_SD3 3
#define REGULATOR_LDO0 4
#define REGULATOR_LDO1 5
#define REGULATOR_LDO2 6
#define REGULATOR_LDO3 7
#define REGULATOR_LDO4 8
#define REGULATOR_LDO5 9
#define REGULATOR_LDO6 10
#define REGULATOR_LDO7 11
#define REGULATOR_LDO8 12
#define REGULATOR_MAX 12
#define MAX77621_CPU_I2C_ADDR 0x1B
#define MAX77621_GPU_I2C_ADDR 0x1C
#define MAX77621_VOUT_REG 0
#define MAX77621_VOUT_DVC_REG 1
#define MAX77621_CONTROL1_REG 2
#define MAX77621_CONTROL2_REG 3
/* MAX77621_VOUT */
#define MAX77621_VOUT_DISABLE (0 << 7)
#define MAX77621_VOUT_ENABLE (1 << 7)
#define MAX77621_VOUT_MASK 0x7F
#define MAX77621_VOUT_0_95V 0x37
#define MAX77621_VOUT_1_09V 0x4F
/* MAX77621_VOUT_DVC_DVS */
#define MAX77621_DVS_VOUT_MASK 0x7F
/* MAX77621_CONTROL1 */
#define MAX77621_SNS_ENABLE (1 << 7)
#define MAX77621_FPWM_EN_M (1 << 6)
#define MAX77621_NFSR_ENABLE (1 << 5)
#define MAX77621_AD_ENABLE (1 << 4)
#define MAX77621_BIAS_ENABLE (1 << 3)
#define MAX77621_FREQSHIFT_9PER (1 << 2)
#define MAX77621_RAMP_12mV_PER_US 0x0
#define MAX77621_RAMP_25mV_PER_US 0x1
#define MAX77621_RAMP_50mV_PER_US 0x2
#define MAX77621_RAMP_200mV_PER_US 0x3
#define MAX77621_RAMP_MASK 0x3
/* MAX77621_CONTROL2 */
#define MAX77621_WDTMR_ENABLE (1 << 6)
#define MAX77621_DISCH_ENBABLE (1 << 5)
#define MAX77621_FT_ENABLE (1 << 4)
#define MAX77621_T_JUNCTION_120 (1 << 7)
#define MAX77621_CKKADV_TRIP_DISABLE 0xC
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0
#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8
#define MAX77621_INDUCTOR_MIN_30_PER 0x0
#define MAX77621_INDUCTOR_NOMINAL 0x1
#define MAX77621_INDUCTOR_PLUS_30_PER 0x2
#define MAX77621_INDUCTOR_PLUS_60_PER 0x3
#endif

View File

@ -0,0 +1,135 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "max77620.h"
#include "max7762x.h"
namespace ams::pmic {
namespace {
constexpr inline int I2cAddressEristaMax77621 = 0x1B;
constexpr inline int I2cAddressMarikoMax77812_A = 0x31;
constexpr inline int I2cAddressMarikoMax77812_B = 0x33;
/* https://github.com/Atmosphere-NX/Atmosphere/blob/master/emummc/source/power/max7762x.h */
/* TODO: Find datasheet, link to it instead. */
/* NOTE: Tentatively, Max77620 "mostly" matches https://datasheets.maximintegrated.com/en/ds/MAX77863.pdf. */
/* This does not contain Max77621 documentation, though. */
constexpr inline int Max77620RegisterGpio0 = 0x36;
constexpr inline int Max77620RegisterAmeGpio = 0x40;
constexpr inline int Max77621RegisterVOut = 0x00;
constexpr inline int Max77621RegisterVOutDvc = 0x01;
constexpr inline int Max77621RegisterControl1 = 0x02;
constexpr inline int Max77621RegisterControl2 = 0x03;
/* https://datasheets.maximintegrated.com/en/ds/MAX77812.pdf */
constexpr inline int Max77812RegisterEnCtrl = 0x06;
constexpr inline int Max77812RegisterM4VOut = 0x26;
void Max77620EnableGpio(int gpio) {
u8 val;
/* Clear the AE for the GPIO */
if (i2c::Query(std::addressof(val), sizeof(val), i2c::Port_5, I2cAddressEristaMax77621, Max77620RegisterAmeGpio)) {
val &= ~(1 << gpio);
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77620RegisterAmeGpio, val);
}
/* Set GPIO_DRV_PUSHPULL (bit 0), GPIO_OUTPUT_VAL_HIGH (bit 3). */
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77620RegisterGpio0 + gpio, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
}
void EnableVddCpuErista() {
/* Enable GPIO 5. */
/* TODO: What does this control? */
Max77620EnableGpio(5);
/* Configure Max77621 control registers. */
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77621RegisterControl1, MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US);
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77621RegisterControl2, MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL);
/* Configure Max77621 VOut to 0.95v */
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77621RegisterVOut, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77621RegisterVOutDvc, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
}
void DisableVddCpuErista() {
/* Disable Max77621 VOut. */
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77621RegisterVOut, MAX77621_VOUT_DISABLE);
}
int GetI2cAddressForMarikoMax77812(Regulator regulator) {
switch (regulator) {
case Regulator_Mariko_Max77812_A: return I2cAddressMarikoMax77812_A;
case Regulator_Mariko_Max77812_B: return I2cAddressMarikoMax77812_B;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
void EnableVddCpuMariko(Regulator regulator) {
const int address = GetI2cAddressForMarikoMax77812(regulator);
/* Set EN_M3_LPM to enable BUCK Master 3 low power mode. */
u8 ctrl;
if (i2c::Query(std::addressof(ctrl), sizeof(ctrl), i2c::Port_5, address, Max77812RegisterEnCtrl)) {
ctrl |= 0x40;
i2c::SendByte(i2c::Port_5, address, Max77812RegisterEnCtrl, ctrl);
}
/* Set BUCK Master 4 output voltage to 110. */
i2c::SendByte(i2c::Port_5, address, Max77812RegisterM4VOut, 110);
}
void DisableVddCpuMariko(Regulator regulator) {
const int address = GetI2cAddressForMarikoMax77812(regulator);
/* Clear EN_M3_LPM to disable BUCK Master 3 low power mode. */
u8 ctrl;
if (i2c::Query(std::addressof(ctrl), sizeof(ctrl), i2c::Port_5, address, Max77812RegisterEnCtrl)) {
ctrl &= ~0x40;
i2c::SendByte(i2c::Port_5, address, Max77812RegisterEnCtrl, ctrl);
}
}
}
void EnableVddCpu(Regulator regulator) {
switch (regulator) {
case Regulator_Erista_Max77621:
return EnableVddCpuErista();
case Regulator_Mariko_Max77812_A:
case Regulator_Mariko_Max77812_B:
return EnableVddCpuMariko(regulator);
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
void DisableVddCpu(Regulator regulator) {
switch (regulator) {
case Regulator_Erista_Max77621:
return DisableVddCpuErista();
case Regulator_Mariko_Max77812_A:
case Regulator_Mariko_Max77812_B:
return DisableVddCpuMariko(regulator);
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}

View File

@ -0,0 +1,209 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "se_execute.hpp"
namespace ams::se {
namespace {
constexpr inline int AesKeySizeMax = 256 / BITSIZEOF(u8);
enum AesMode {
AesMode_Aes128 = ((SE_CONFIG_ENC_MODE_AESMODE_KEY128 << SE_CONFIG_ENC_MODE_OFFSET) | (SE_CONFIG_DEC_MODE_AESMODE_KEY128 << SE_CONFIG_DEC_MODE_OFFSET)) >> SE_CONFIG_DEC_MODE_OFFSET,
AesMode_Aes192 = ((SE_CONFIG_ENC_MODE_AESMODE_KEY192 << SE_CONFIG_ENC_MODE_OFFSET) | (SE_CONFIG_DEC_MODE_AESMODE_KEY192 << SE_CONFIG_DEC_MODE_OFFSET)) >> SE_CONFIG_DEC_MODE_OFFSET,
AesMode_Aes256 = ((SE_CONFIG_ENC_MODE_AESMODE_KEY256 << SE_CONFIG_ENC_MODE_OFFSET) | (SE_CONFIG_DEC_MODE_AESMODE_KEY256 << SE_CONFIG_DEC_MODE_OFFSET)) >> SE_CONFIG_DEC_MODE_OFFSET,
};
enum MemoryInterface {
MemoryInterface_Ahb = SE_CRYPTO_CONFIG_MEMIF_AHB,
MemoryInterface_Mc = SE_CRYPTO_CONFIG_MEMIF_MCCIF,
};
constexpr inline u32 AesConfigEcb = reg::Encode(SE_REG_BITS_VALUE(CRYPTO_CONFIG_CTR_CNTN, 0),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_KEYSCH_BYPASS, DISABLE),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_IV_SELECT, ORIGINAL),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_VCTRAM_SEL, MEMORY),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_INPUT_SEL, MEMORY),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_XOR_POS, BYPASS),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_HASH_ENB, DISABLE));
void SetConfig(volatile SecurityEngineRegisters *SE, bool encrypt, SE_CONFIG_DST dst) {
reg::Write(SE->SE_CONFIG, SE_REG_BITS_ENUM (CONFIG_ENC_MODE, AESMODE_KEY128),
SE_REG_BITS_ENUM (CONFIG_DEC_MODE, AESMODE_KEY128),
SE_REG_BITS_ENUM_SEL(CONFIG_ENC_ALG, encrypt, AES_ENC, NOP),
SE_REG_BITS_ENUM_SEL(CONFIG_DEC_ALG, encrypt, NOP, AES_DEC),
SE_REG_BITS_VALUE (CONFIG_DST, dst));
}
void SetAesConfig(volatile SecurityEngineRegisters *SE, int slot, bool encrypt, u32 config) {
const u32 encoded = reg::Encode(SE_REG_BITS_ENUM (CRYPTO_CONFIG_MEMIF, AHB),
SE_REG_BITS_VALUE (CRYPTO_CONFIG_KEY_INDEX, slot),
SE_REG_BITS_ENUM_SEL(CRYPTO_CONFIG_CORE_SEL, encrypt, ENCRYPT, DECRYPT));
reg::Write(SE->SE_CRYPTO_CONFIG, (config | encoded));
}
void SetBlockCount(volatile SecurityEngineRegisters *SE, int count) {
reg::Write(SE->SE_CRYPTO_LAST_BLOCK, count - 1);
}
void UpdateAesMode(volatile SecurityEngineRegisters *SE, AesMode mode) {
reg::ReadWrite(SE->SE_CONFIG, REG_BITS_VALUE(16, 16, mode));
}
// void UpdateMemoryInterface(volatile SecurityEngineRegisters *SE, MemoryInterface memif) {
// reg::ReadWrite(SE->SE_CRYPTO_CONFIG, SE_REG_BITS_VALUE(CRYPTO_CONFIG_MEMIF, memif));
// }
void SetEncryptedAesKey(int dst_slot, int kek_slot, const void *key, size_t key_size, AesMode mode) {
AMS_ABORT_UNLESS(key_size <= AesKeySizeMax);
AMS_ABORT_UNLESS(0 <= dst_slot && dst_slot < AesKeySlotCount);
AMS_ABORT_UNLESS(0 <= kek_slot && kek_slot < AesKeySlotCount);
/* Get the engine. */
auto *SE = GetRegisters();
/* Configure for single AES ECB decryption to key table. */
SetConfig(SE, false, SE_CONFIG_DST_KEYTABLE);
SetAesConfig(SE, kek_slot, false, AesConfigEcb);
UpdateAesMode(SE, mode);
SetBlockCount(SE, 1);
/* Select the destination keyslot. */
reg::Write(SE->SE_CRYPTO_KEYTABLE_DST, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_DST_KEY_INDEX, dst_slot), SE_REG_BITS_ENUM(CRYPTO_KEYTABLE_DST_WORD_QUAD, KEYS_0_3));
/* Ensure that the se sees the keydata we want it to. */
hw::FlushDataCache(key, key_size);
hw::DataSynchronizationBarrierInnerShareable();
/* Execute the operation. */
ExecuteOperation(SE, SE_OPERATION_OP_START, nullptr, 0, key, key_size);
}
void EncryptAes(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, AesMode mode) {
/* If nothing to decrypt, succeed. */
if (src_size == 0) { return; }
/* Validate input. */
AMS_ABORT_UNLESS(dst_size == AesBlockSize);
AMS_ABORT_UNLESS(src_size == AesBlockSize);
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
/* Get the engine. */
auto *SE = GetRegisters();
/* Configure for AES-ECB encryption to memory. */
SetConfig(SE, true, SE_CONFIG_DST_MEMORY);
SetAesConfig(SE, slot, true, AesConfigEcb);
UpdateAesMode(SE, mode);
/* Execute the operation. */
ExecuteOperationSingleBlock(SE, dst, dst_size, src, src_size);
}
}
void ClearAesKeySlot(int slot) {
/* Validate the key slot. */
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
/* Get the engine. */
auto *SE = GetRegisters();
for (int i = 0; i < 16; ++i) {
/* Select the keyslot. */
reg::Write(SE->SE_CRYPTO_KEYTABLE_ADDR, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_SLOT, slot), SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_WORD, i));
/* Write the data. */
SE->SE_CRYPTO_KEYTABLE_DATA = 0;
}
}
void LockAesKeySlot(int slot, u32 flags) {
/* Validate the key slot. */
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
/* Get the engine. */
auto *SE = GetRegisters();
/* Set non per-key flags. */
if ((flags & ~KeySlotLockFlags_PerKey) != 0) {
/* TODO: KeySlotLockFlags_DstKeyTableOnly is Mariko-only. How should we handle this? */
/* TODO: Mariko bit support. */
reg::ReadWrite(SE->SE_CRYPTO_KEYTABLE_ACCESS[slot], REG_BITS_VALUE(0, 7, ~flags));
}
/* Set per-key flag. */
if ((flags & KeySlotLockFlags_PerKey) != 0) {
reg::ReadWrite(SE->SE_CRYPTO_SECURITY_PERKEY, REG_BITS_VALUE(slot, 1, 0));
}
}
void SetAesKey(int slot, const void *key, size_t key_size) {
/* Validate the key slot and key size. */
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
AMS_ABORT_UNLESS(key_size <= AesKeySizeMax);
/* Get the engine. */
auto *SE = GetRegisters();
/* Set each key word in order. */
const u32 *key_u32 = static_cast<const u32 *>(key);
const int num_words = key_size / sizeof(u32);
for (int i = 0; i < num_words; ++i) {
/* Select the keyslot. */
reg::Write(SE->SE_CRYPTO_KEYTABLE_ADDR, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_SLOT, slot),
SE_REG_BITS_ENUM (CRYPTO_KEYTABLE_ADDR_KEYIV_KEYIV_SEL, KEY),
SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_WORD, i));
/* Set the key word. */
SE->SE_CRYPTO_KEYTABLE_DATA = *(key_u32++);
}
}
void SetEncryptedAesKey128(int dst_slot, int kek_slot, const void *key, size_t key_size) {
return SetEncryptedAesKey(dst_slot, kek_slot, key, key_size, AesMode_Aes128);
}
void SetEncryptedAesKey256(int dst_slot, int kek_slot, const void *key, size_t key_size) {
return SetEncryptedAesKey(dst_slot, kek_slot, key, key_size, AesMode_Aes256);
}
void EncryptAes128(void *dst, size_t dst_size, int slot, const void *src, size_t src_size) {
return EncryptAes(dst, dst_size, slot, src, src_size, AesMode_Aes128);
}
void DecryptAes128(void *dst, size_t dst_size, int slot, const void *src, size_t src_size) {
/* If nothing to decrypt, succeed. */
if (src_size == 0) { return; }
/* Validate input. */
AMS_ABORT_UNLESS(dst_size == AesBlockSize);
AMS_ABORT_UNLESS(src_size == AesBlockSize);
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
/* Get the engine. */
auto *SE = GetRegisters();
/* Configure for AES-ECB decryption to memory. */
SetConfig(SE, false, SE_CONFIG_DST_MEMORY);
SetAesConfig(SE, slot, false, AesConfigEcb);
ExecuteOperationSingleBlock(SE, dst, dst_size, src, src_size);
}
}

View File

@ -0,0 +1,138 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "se_execute.hpp"
namespace ams::se {
namespace {
struct LinkedListEntry {
u32 zero;
u32 address;
u32 size;
};
static_assert(util::is_pod<LinkedListEntry>::value);
uintptr_t GetPhysicalAddress(const void *ptr) {
const uintptr_t virt_address = reinterpret_cast<uintptr_t>(ptr);
#if defined(ATMOSPHERE_ARCH_ARM64)
u64 phys_address;
__asm__ __volatile__("at s1e3r, %[virt]; mrs %[phys], par_el1" : [phys]"=r"(phys_address) : [virt]"r"(virt_address) : "memory", "cc");
return (phys_address & 0x0000FFFFFFFFF000ul) | (virt_address & 0x0000000000000FFFul);
#elif defined(ATMOSPHERE_ARCH_ARM)
return virt_address;
#else
#error "Unknown architecture for Tegra Security Engine physical address translation"
#endif
}
constexpr void SetLinkedListEntry(LinkedListEntry *entry, const void *ptr, size_t size) {
/* Clear the zero field. */
entry->zero = 0;
/* Set the address. */
if (ptr != nullptr) {
entry->address = GetPhysicalAddress(ptr);
entry->size = static_cast<u32>(size);
} else {
entry->address = 0;
entry->size = 0;
}
}
void StartOperation(volatile SecurityEngineRegisters *SE, SE_OPERATION_OP op) {
/* Write back the current values of the error and interrupt status. */
reg::Write(SE->SE_ERR_STATUS, reg::Read(SE->SE_ERR_STATUS));
reg::Write(SE->SE_INT_STATUS, reg::Read(SE->SE_INT_STATUS));
/* Write the operation. */
reg::Write(SE->SE_OPERATION, SE_REG_BITS_VALUE(OPERATION_OP, op));
}
void WaitForOperationComplete(volatile SecurityEngineRegisters *SE) {
/* Spin until the operation is done. */
while (reg::HasValue(SE->SE_INT_STATUS, SE_REG_BITS_ENUM(INT_STATUS_SE_OP_DONE, CLEAR))) { /* ... */ }
/* Check for operation success. */
ValidateAesOperationResult(SE);
}
}
void ExecuteOperation(volatile SecurityEngineRegisters *SE, SE_OPERATION_OP op, void *dst, size_t dst_size, const void *src, size_t src_size) {
/* Set the linked list entries. */
LinkedListEntry src_entry;
LinkedListEntry dst_entry;
SetLinkedListEntry(std::addressof(src_entry), src, src_size);
SetLinkedListEntry(std::addressof(dst_entry), dst, dst_size);
/* Ensure the linked list entry data is seen correctly. */
hw::FlushDataCache(std::addressof(src_entry), sizeof(src_entry));
hw::FlushDataCache(std::addressof(dst_entry), sizeof(dst_entry));
hw::DataSynchronizationBarrierInnerShareable();
/* Configure the linked list addresses. */
reg::Write(SE->SE_IN_LL_ADDR, static_cast<u32>(GetPhysicalAddress(std::addressof(src_entry))));
reg::Write(SE->SE_OUT_LL_ADDR, static_cast<u32>(GetPhysicalAddress(std::addressof(dst_entry))));
/* Start the operation. */
StartOperation(SE, op);
/* Wait for the operation to complete. */
WaitForOperationComplete(SE);
}
void ExecuteOperationSingleBlock(volatile SecurityEngineRegisters *SE, void *dst, size_t dst_size, const void *src, size_t src_size) {
/* Validate sizes. */
AMS_ABORT_UNLESS(dst_size <= AesBlockSize);
AMS_ABORT_UNLESS(src_size == AesBlockSize);
/* Set the block count to 1. */
reg::Write(SE->SE_CRYPTO_LAST_BLOCK, 0);
/* Create an aligned buffer. */
util::AlignedBuffer<hw::DataCacheLineSize, AesBlockSize> aligned;
std::memcpy(aligned, src, AesBlockSize);
hw::FlushDataCache(aligned, AesBlockSize);
hw::DataSynchronizationBarrierInnerShareable();
/* Execute the operation. */
ExecuteOperation(SE, SE_OPERATION_OP_START, aligned, AesBlockSize, aligned, AesBlockSize);
/* Ensure that the CPU will see the correct output. */
hw::DataSynchronizationBarrierInnerShareable();
hw::FlushDataCache(aligned, AesBlockSize);
hw::DataSynchronizationBarrierInnerShareable();
/* Copy the output to the destination. */
std::memcpy(dst, aligned, dst_size);
}
void ValidateAesOperationResult(volatile SecurityEngineRegisters *SE) {
/* Ensure no error occurred. */
AMS_ABORT_UNLESS(reg::HasValue(SE->SE_INT_STATUS, SE_REG_BITS_ENUM(INT_STATUS_ERR_STAT, CLEAR)));
/* Ensure the security engine is idle. */
AMS_ABORT_UNLESS(reg::HasValue(SE->SE_STATUS, SE_REG_BITS_ENUM(STATUS_STATE, IDLE)));
/* Ensure there is no error status. */
AMS_ABORT_UNLESS(reg::Read(SE->SE_ERR_STATUS) == 0);
}
}

View File

@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "se_registers.hpp"
namespace ams::se {
volatile SecurityEngineRegisters *GetRegisters();
void ExecuteOperation(volatile SecurityEngineRegisters *SE, SE_OPERATION_OP op, void *dst, size_t dst_size, const void *src, size_t src_size);
void ExecuteOperationSingleBlock(volatile SecurityEngineRegisters *SE, void *dst, size_t dst_size, const void *src, size_t src_size);
void ValidateAesOperationResult(volatile SecurityEngineRegisters *SE);
}

View File

@ -0,0 +1,114 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "se_execute.hpp"
namespace ams::se {
namespace {
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceSecurityEngine.GetAddress();
constinit DoneHandler g_done_handler = nullptr;
}
volatile SecurityEngineRegisters *GetRegisters() {
return reinterpret_cast<volatile SecurityEngineRegisters *>(g_register_address);
}
void SetRegisterAddress(uintptr_t address) {
g_register_address = address;
}
void Initialize() {
auto *SE = GetRegisters();
AMS_ABORT_UNLESS(reg::HasValue(SE->SE_STATUS, SE_REG_BITS_ENUM(STATUS_STATE, IDLE)));
}
void SetSecure(bool secure) {
auto *SE = GetRegisters();
/* Set the security software setting. */
if (secure) {
reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, SECURE));
} else {
reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, NONSECURE));
}
/* Read the status register to force an update. */
reg::Read(SE->SE_SE_SECURITY);
}
void SetTzramSecure() {
auto *SE = GetRegisters();
/* Set the TZRAM setting to secure. */
SE->SE_TZRAM_SECURITY = SE_TZRAM_SETTING_SECURE;
}
void SetPerKeySecure() {
auto *SE = GetRegisters();
/* Clear AES PerKey security. */
SE->SE_CRYPTO_SECURITY_PERKEY = 0;
/* Clear RSA PerKey security. */
SE->SE_RSA_SECURITY_PERKEY = 0;
/* Update PERKEY_SETTING to secure. */
reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_PERKEY_SETTING, SECURE));
}
void Lockout() {
auto *SE = GetRegisters();
/* Lock access to the AES keyslots. */
for (int i = 0; i < AesKeySlotCount; ++i) {
SE->SE_CRYPTO_KEYTABLE_ACCESS[i] = 0;
}
/* Lock access to the RSA keyslots. */
for (int i = 0; i < RsaKeySlotCount; ++i) {
SE->SE_RSA_KEYTABLE_ACCESS[i] = 0;
}
/* Set Per Key secure. */
SetPerKeySecure();
/* Configure SE_SECURITY. */
{
reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_HARD_SETTING, SECURE),
SE_REG_BITS_ENUM(SECURITY_ENG_DIS, DISABLE),
SE_REG_BITS_ENUM(SECURITY_PERKEY_SETTING, SECURE),
SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, SECURE));
}
}
void HandleInterrupt() {
/* Get the registers. */
auto *SE = GetRegisters();
/* Disable the SE interrupt. */
reg::Write(SE->SE_INT_ENABLE, 0);
/* Execute the handler if we have one. */
if (const auto handler = g_done_handler; handler != nullptr) {
g_done_handler = nullptr;
handler();
}
}
}

View File

@ -0,0 +1,249 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::se {
struct SecurityEngineRegisters {
u32 SE_SE_SECURITY;
u32 SE_TZRAM_SECURITY;
u32 SE_OPERATION;
u32 SE_INT_ENABLE;
u32 SE_INT_STATUS;
u32 SE_CONFIG;
u32 SE_IN_LL_ADDR;
u32 SE_IN_CUR_BYTE_ADDR;
u32 SE_IN_CUR_LL_ID;
u32 SE_OUT_LL_ADDR;
u32 SE_OUT_CUR_BYTE_ADDR;
u32 SE_OUT_CUR_LL_ID;
u32 SE_HASH_RESULT[0x10];
u32 SE_CTX_SAVE_CONFIG;
u32 _0x74[0x63];
u32 SE_SHA_CONFIG;
u32 SE_SHA_MSG_LENGTH[0x4];
u32 SE_SHA_MSG_LEFT[0x4];
u32 _0x224[0x17];
u32 SE_CRYPTO_SECURITY_PERKEY;
u32 SE_CRYPTO_KEYTABLE_ACCESS[0x10];
u32 _0x2C4[0x10];
u32 SE_CRYPTO_CONFIG;
u32 SE_CRYPTO_LINEAR_CTR[0x4];
u32 SE_CRYPTO_LAST_BLOCK;
u32 SE_CRYPTO_KEYTABLE_ADDR;
u32 SE_CRYPTO_KEYTABLE_DATA;
u32 _0x324[0x3];
u32 SE_CRYPTO_KEYTABLE_DST;
u32 _0x334[0x3];
u32 SE_RNG_CONFIG;
u32 SE_RNG_SRC_CONFIG;
u32 SE_RNG_RESEED_INTERVAL;
u32 _0x34C[0x2D];
u32 SE_RSA_CONFIG;
u32 SE_RSA_KEY_SIZE;
u32 SE_RSA_EXP_SIZE;
u32 SE_RSA_SECURITY_PERKEY;
u32 SE_RSA_KEYTABLE_ACCESS[0x2];
u32 _0x418[0x2];
u32 SE_RSA_KEYTABLE_ADDR;
u32 SE_RSA_KEYTABLE_DATA;
u32 SE_RSA_OUTPUT[0x40];
u32 _0x528[0xB6];
u32 SE_STATUS;
u32 SE_ERR_STATUS;
u32 SE_MISC;
u32 SE_SPARE;
u32 SE_ENTROPY_DEBUG_COUNTER;
u32 _0x814;
u32 _0x818;
u32 _0x81C;
u32 _0x820[0x5F8];
};
static_assert(util::is_pod<SecurityEngineRegisters>::value);
static_assert(sizeof(SecurityEngineRegisters) == secmon::MemoryRegionPhysicalDeviceSecurityEngine.GetSize());
static_assert(AesKeySlotCount == util::size(SecurityEngineRegisters{}.SE_CRYPTO_KEYTABLE_ACCESS));
static_assert(RsaKeySlotCount == util::size(SecurityEngineRegisters{}.SE_RSA_KEYTABLE_ACCESS));
#define SE_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (SE, NAME)
#define SE_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (SE, NAME, VALUE)
#define SE_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (SE, NAME, ENUM)
#define SE_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(SE, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
#define DEFINE_SE_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (SE, NAME, __OFFSET__, __WIDTH__)
#define DEFINE_SE_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (SE, NAME, __OFFSET__, ZERO, ONE)
#define DEFINE_SE_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (SE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
#define DEFINE_SE_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(SE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
#define DEFINE_SE_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (SE, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
#define DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(NAME, __OFFSET__) \
REG_DEFINE_NAMED_REG(SE, NAME, __OFFSET__, 1); \
\
enum SE_##NAME { \
SE_##NAME##_##CLEAR = 0, \
SE_##NAME##_##ACTIVE = 1, \
SE_##NAME##_##SW_CLEAR = 1, \
};
/* SE_STATUS. */
DEFINE_SE_REG_TWO_BIT_ENUM(STATUS_STATE, 0, IDLE, BUSY, WAIT_OUT, WAIT_IN);
/* SE_SECURITY */
DEFINE_SE_REG_BIT_ENUM(SECURITY_HARD_SETTING, 0, SECURE, NONSECURE);
DEFINE_SE_REG_BIT_ENUM(SECURITY_ENG_DIS, 1, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(SECURITY_PERKEY_SETTING, 2, SECURE, NONSECURE);
DEFINE_SE_REG_BIT_ENUM(SECURITY_SOFT_SETTING, 16, SECURE, NONSECURE);
/* SE_TZRAM_SECURITY */
DEFINE_SE_REG(TZRAM_SETTING, 0, BITSIZEOF(u32));
constexpr inline u32 SE_TZRAM_SETTING_SECURE = 0;
/* SE_OPERATION */
DEFINE_SE_REG_THREE_BIT_ENUM(OPERATION_OP, 0, ABORT, START, RESTART_OUT, CTX_SAVE, RESTART_IN, RESERVED_5, RESERVED_6, RESERVED_7);
/* SE_INT_ENABLE */
DEFINE_SE_REG_BIT_ENUM(INT_ENABLE_IN_LL_BUF_RD, 0, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(INT_ENABLE_IN_DONE, 1, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(INT_ENABLE_OUT_LL_BUF_WR, 2, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(INT_ENABLE_OUT_DONE, 3, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(INT_ENABLE_SE_OP_DONE, 4, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(INT_ENABLE_RESEED_CNTR_EXHAUSTED, 5, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(INT_ENABLE_ERR_STAT, 16, DISABLE, ENABLE);
/* SE_INT_STATUS */
DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(INT_STATUS_IN_LL_BUF_RD, 0);
DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(INT_STATUS_IN_DONE, 1);
DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(INT_STATUS_OUT_LL_BUF_WR, 2);
DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(INT_STATUS_OUT_DONE, 3);
DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(INT_STATUS_SE_OP_DONE, 4);
DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(INT_STATUS_RESEED_CNTR_EXHAUSTED, 5);
DEFINE_SE_REG_BIT_ENUM_WITH_SW_CLEAR(INT_STATUS_ERR_STAT, 16);
/* SE_CONFIG */
DEFINE_SE_REG(CONFIG_DST, 2, 3);
DEFINE_SE_REG(CONFIG_DEC_ALG, 8, 4);
DEFINE_SE_REG(CONFIG_ENC_ALG, 12, 4);
DEFINE_SE_REG(CONFIG_DEC_MODE, 16, 8);
DEFINE_SE_REG(CONFIG_ENC_MODE, 24, 8);
enum SE_CONFIG_DST {
SE_CONFIG_DST_MEMORY = 0,
SE_CONFIG_DST_HASH_REG = 1,
SE_CONFIG_DST_KEYTABLE = 2,
SE_CONFIG_DST_SRK = 3,
SE_CONFIG_DST_RSA_REG = 4,
};
enum SE_CONFIG_DEC_ALG {
SE_CONFIG_DEC_ALG_NOP = 0,
SE_CONFIG_DEC_ALG_AES_DEC = 1,
};
enum SE_CONFIG_ENC_ALG {
SE_CONFIG_ENC_ALG_NOP = 0,
SE_CONFIG_ENC_ALG_AES_ENC = 1,
SE_CONFIG_ENC_ALG_RNG = 2,
SE_CONFIG_ENC_ALG_SHA = 3,
SE_CONFIG_ENC_ALG_RSA = 4,
};
enum SE_CONFIG_DEC_MODE {
SE_CONFIG_DEC_MODE_AESMODE_KEY128 = 0,
SE_CONFIG_DEC_MODE_AESMODE_KEY192 = 1,
SE_CONFIG_DEC_MODE_AESMODE_KEY256 = 2,
};
enum SE_CONFIG_ENC_MODE {
SE_CONFIG_ENC_MODE_AESMODE_KEY128 = 0,
SE_CONFIG_ENC_MODE_AESMODE_KEY192 = 1,
SE_CONFIG_ENC_MODE_AESMODE_KEY256 = 2,
SE_CONFIG_ENC_MODE_AESMODE_SHA1 = 1,
SE_CONFIG_ENC_MODE_AESMODE_SHA224 = 4,
SE_CONFIG_ENC_MODE_AESMODE_SHA256 = 5,
SE_CONFIG_ENC_MODE_AESMODE_SHA384 = 6,
SE_CONFIG_ENC_MODE_AESMODE_SHA512 = 7,
};
/* SE_CRYPTO_KEYTABLE_ADDR */
DEFINE_SE_REG(CRYPTO_KEYTABLE_ADDR_KEYIV_WORD, 0, 4);
DEFINE_SE_REG(CRYPTO_KEYTABLE_ADDR_KEYIV_IV_WORD, 0, 2);
DEFINE_SE_REG(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_WORD, 0, 3);
enum SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD {
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_0 = 0u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_1 = 1u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_2 = 2u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_3 = 3u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_4 = 4u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_5 = 5u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_6 = 6u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_KEY_7 = 7u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_OIV_0 = 8u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_OIV_1 = 9u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_OIV_2 = 10u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_OIV_3 = 11u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_UIV_0 = 12u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_UIV_1 = 13u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_UIV_2 = 14u,
SE_CRYPTO_KEYTABLE_ADDR_KEYIV_WORD_UIV_3 = 15u,
};
DEFINE_SE_REG_BIT_ENUM(CRYPTO_KEYTABLE_ADDR_KEYIV_IV_SEL, 2, ORIGINAL_IV, UPDATED_IV);
DEFINE_SE_REG_BIT_ENUM(CRYPTO_KEYTABLE_ADDR_KEYIV_KEYIV_SEL, 3, KEY, IV);
DEFINE_SE_REG(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_SLOT, 4, 4);
/* SE_RSA_KEYTABLE_ADDR */
DEFINE_SE_REG(RSA_KEYTABLE_ADDR_WORD_ADDR, 0, 6);
DEFINE_SE_REG_BIT_ENUM(RSA_KEYTABLE_ADDR_EXPMOD_SEL, 6, EXPONENT, MODULUS);
DEFINE_SE_REG(RSA_KEYTABLE_ADDR_KEY_SLOT, 7, 1);
DEFINE_SE_REG_BIT_ENUM(RSA_KEYTABLE_ADDR_INPUT_MODE, 8, REGISTER, MEMORY);
/* SE_RSA_KEYTABLE_ACCESS */
DEFINE_SE_REG_BIT_ENUM(RSA_KEYTABLE_ACCESS_KEYREAD, 0, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(RSA_KEYTABLE_ACCESS_KEYUPDATE, 1, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(RSA_KEYTABLE_ACCESS_KEYUSE, 2, DISABLE, ENABLE);
/* SE_CRYPTO_CONFIG */
DEFINE_SE_REG_BIT_ENUM(CRYPTO_CONFIG_HASH_ENB, 0, DISABLE, ENABLE);
DEFINE_SE_REG_TWO_BIT_ENUM(CRYPTO_CONFIG_XOR_POS, 1, BYPASS, RESERVED, TOP, BOTTOM);
DEFINE_SE_REG_TWO_BIT_ENUM(CRYPTO_CONFIG_INPUT_SEL, 3, MEMORY, RANDOM, INIT_AESOUT, LINEAR_CTR);
DEFINE_SE_REG_TWO_BIT_ENUM(CRYPTO_CONFIG_VCTRAM_SEL, 5, MEMORY, RESERVED, INIT_AESOUT, INIT_PREV_MEMORY);
DEFINE_SE_REG_BIT_ENUM(CRYPTO_CONFIG_IV_SELECT, 7, ORIGINAL, UPDATED);
DEFINE_SE_REG_BIT_ENUM(CRYPTO_CONFIG_CORE_SEL, 8, DECRYPT, ENCRYPT);
DEFINE_SE_REG_BIT_ENUM(CRYPTO_CONFIG_KEYSCH_BYPASS, 10, DISABLE, ENABLE);
DEFINE_SE_REG(CRYPTO_CONFIG_CTR_CNTN, 11, 8);
DEFINE_SE_REG(CRYPTO_CONFIG_KEY_INDEX, 24, 4);
DEFINE_SE_REG_BIT_ENUM(CRYPTO_CONFIG_MEMIF, 31, AHB, MCCIF);
/* SE_CRYPTO_KEYTABLE_DST */
DEFINE_SE_REG_TWO_BIT_ENUM(CRYPTO_KEYTABLE_DST_WORD_QUAD, 0, KEYS_0_3, KEYS_4_7, ORIGINAL_IV, UPDATED_IV);
DEFINE_SE_REG(CRYPTO_KEYTABLE_DST_KEY_INDEX, 8, 4);
/* SE_RNG_CONFIG */
DEFINE_SE_REG_TWO_BIT_ENUM(RNG_CONFIG_MODE, 0, NORMAL, FORCE_INSTANTIATION, FORCE_RESEED, RESERVED3);
DEFINE_SE_REG_TWO_BIT_ENUM(RNG_CONFIG_SRC, 2, NONE, ENTROPY, LFSR, RESERVED3);
/* SE_RNG_SRC_CONFIG */
DEFINE_SE_REG_BIT_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE_LOCK, 0, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE, 1, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(RNG_SRC_CONFIG_HW_DISABLE_CYA, 2, DISABLE, ENABLE);
DEFINE_SE_REG(RNG_SRC_CONFIG_RO_ENTROPY_SUBSAMPLE, 4, 3);
DEFINE_SE_REG(RNG_SRC_CONFIG_RO_ENTROPY_DATA_FLUSH, 8, 1);
}

View File

@ -0,0 +1,146 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "se_execute.hpp"
namespace ams::se {
namespace {
constexpr inline int RngReseedInterval = 70001;
void ConfigRng(volatile SecurityEngineRegisters *SE, SE_CONFIG_DST dst, SE_RNG_CONFIG_MODE mode) {
/* Configure the engine to do RNG encryption. */
reg::Write(SE->SE_CONFIG, SE_REG_BITS_ENUM (CONFIG_ENC_MODE, AESMODE_KEY128),
SE_REG_BITS_ENUM (CONFIG_DEC_MODE, AESMODE_KEY128),
SE_REG_BITS_ENUM (CONFIG_ENC_ALG, RNG),
SE_REG_BITS_ENUM (CONFIG_DEC_ALG, NOP),
SE_REG_BITS_VALUE(CONFIG_DST, dst));
reg::Write(SE->SE_CRYPTO_CONFIG, SE_REG_BITS_ENUM (CRYPTO_CONFIG_MEMIF, AHB),
SE_REG_BITS_VALUE(CRYPTO_CONFIG_CTR_CNTN, 0),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_KEYSCH_BYPASS, DISABLE),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_CORE_SEL, ENCRYPT),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_IV_SELECT, ORIGINAL),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_VCTRAM_SEL, MEMORY),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_INPUT_SEL, RANDOM),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_XOR_POS, BYPASS),
SE_REG_BITS_ENUM (CRYPTO_CONFIG_HASH_ENB, DISABLE));
/* Configure the RNG to use Entropy as source. */
reg::Write(SE->SE_RNG_CONFIG, SE_REG_BITS_ENUM(RNG_CONFIG_SRC, ENTROPY), SE_REG_BITS_VALUE(RNG_CONFIG_MODE, mode));
}
}
void InitializeRandom() {
/* Get the engine. */
auto *SE = GetRegisters();
/* Lock the entropy source. */
reg::Write(SE->SE_RNG_SRC_CONFIG, SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE, ENABLE),
SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE_LOCK, ENABLE));
/* Set the reseed interval to force a reseed every 70000 blocks. */
SE->SE_RNG_RESEED_INTERVAL = RngReseedInterval;
/* Initialize the DRBG. */
{
u8 dummy_buf[AesBlockSize];
/* Configure the engine to force drbg instantiation by writing random to memory. */
ConfigRng(SE, SE_CONFIG_DST_MEMORY, SE_RNG_CONFIG_MODE_FORCE_INSTANTIATION);
/* Configure to do a single RNG block operation to trigger DRBG init. */
SE->SE_CRYPTO_LAST_BLOCK = 0;
/* Execute the operation. */
ExecuteOperation(SE, SE_OPERATION_OP_START, dummy_buf, sizeof(dummy_buf), nullptr, 0);
}
}
void GenerateRandomBytes(void *dst, size_t size) {
/* If we're not generating any bytes, there's nothing to do. */
if (size == 0) {
return;
}
/* Get the engine. */
auto *SE = GetRegisters();
/* Determine how many blocks to generate. */
const size_t num_blocks = size / AesBlockSize;
const size_t aligned_size = num_blocks * AesBlockSize;
const size_t fractional = size - aligned_size;
/* Configure the RNG to generate random to memory. */
ConfigRng(SE, SE_CONFIG_DST_MEMORY, SE_RNG_CONFIG_MODE_NORMAL);
/* Generate as many aligned blocks as we can. */
if (aligned_size > 0) {
/* Configure the engine to generate the right number of blocks. */
SE->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
/* Execute the operation. */
ExecuteOperation(SE, SE_OPERATION_OP_START, dst, aligned_size, nullptr, 0);
}
/* Generate a single block to output. */
if (fractional > 0) {
ExecuteOperationSingleBlock(SE, static_cast<u8 *>(dst) + aligned_size, fractional, nullptr, 0);
}
}
void SetRandomKey(int slot) {
/* NOTE: Nintendo does not validate the destination keyslot here. */
/* Get the engine. */
auto *SE = GetRegisters();
/* Configure the RNG to output to the keytable. */
ConfigRng(SE, SE_CONFIG_DST_KEYTABLE, SE_RNG_CONFIG_MODE_NORMAL);
/* Configure the keytable destination to be the low part of the key. */
reg::Write(SE->SE_CRYPTO_KEYTABLE_DST, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_DST_KEY_INDEX, slot), SE_REG_BITS_ENUM(CRYPTO_KEYTABLE_DST_WORD_QUAD, KEYS_0_3));
/* Configure a single block operation. */
SE->SE_CRYPTO_LAST_BLOCK = 0;
/* Execute the operation to generate a random low-part of the key. */
ExecuteOperation(SE, SE_OPERATION_OP_START, nullptr, 0, nullptr, 0);
/* Configure the keytable destination to be the high part of the key. */
reg::Write(SE->SE_CRYPTO_KEYTABLE_DST, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_DST_KEY_INDEX, slot), SE_REG_BITS_ENUM(CRYPTO_KEYTABLE_DST_WORD_QUAD, KEYS_4_7));
/* Execute the operation to generate a random high-part of the key. */
ExecuteOperation(SE, SE_OPERATION_OP_START, nullptr, 0, nullptr, 0);
}
void GenerateSrk() {
/* Get the engine. */
auto *SE = GetRegisters();
/* Configure the RNG to output to SRK and force a reseed. */
ConfigRng(SE, SE_CONFIG_DST_SRK, SE_RNG_CONFIG_MODE_FORCE_RESEED);
/* Configure a single block operation. */
SE->SE_CRYPTO_LAST_BLOCK = 0;
/* Execute the operation. */
ExecuteOperation(SE, SE_OPERATION_OP_START, nullptr, 0, nullptr, 0);
}
}

View File

@ -0,0 +1,125 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "se_execute.hpp"
namespace ams::se {
namespace {
struct RsaKeyInfo {
int modulus_size_val;
int exponent_size_val;
};
constinit RsaKeyInfo g_rsa_key_infos[RsaKeySlotCount] = {};
void ClearRsaKeySlot(int slot, SE_RSA_KEYTABLE_ADDR_EXPMOD_SEL expmod) {
/* Get the engine. */
auto *SE = GetRegisters();
constexpr int NumWords = se::RsaSize / sizeof(u32);
for (int i = 0; i < NumWords; ++i) {
/* Select the keyslot word. */
reg::Write(SE->SE_RSA_KEYTABLE_ADDR, SE_REG_BITS_ENUM (RSA_KEYTABLE_ADDR_INPUT_MODE, REGISTER),
SE_REG_BITS_VALUE(RSA_KEYTABLE_ADDR_KEY_SLOT, slot),
SE_REG_BITS_VALUE(RSA_KEYTABLE_ADDR_EXPMOD_SEL, expmod),
SE_REG_BITS_VALUE(RSA_KEYTABLE_ADDR_WORD_ADDR, i));
/* Clear the keyslot word. */
SE->SE_RSA_KEYTABLE_DATA = 0;
}
}
void SetRsaKey(int slot, SE_RSA_KEYTABLE_ADDR_EXPMOD_SEL expmod, const void *key, size_t key_size) {
/* Get the engine. */
auto *SE = GetRegisters();
const int num_words = key_size / sizeof(u32);
for (int i = 0; i < num_words; ++i) {
/* Select the keyslot word. */
reg::Write(SE->SE_RSA_KEYTABLE_ADDR, SE_REG_BITS_ENUM (RSA_KEYTABLE_ADDR_INPUT_MODE, REGISTER),
SE_REG_BITS_VALUE(RSA_KEYTABLE_ADDR_KEY_SLOT, slot),
SE_REG_BITS_VALUE(RSA_KEYTABLE_ADDR_EXPMOD_SEL, expmod),
SE_REG_BITS_VALUE(RSA_KEYTABLE_ADDR_WORD_ADDR, i));
/* Get the word. */
const u32 word = util::LoadBigEndian(static_cast<const u32 *>(key) + (num_words - 1 - i));
/* Write the keyslot word. */
SE->SE_RSA_KEYTABLE_DATA = word;
}
}
}
void ClearRsaKeySlot(int slot) {
/* Validate the key slot. */
AMS_ABORT_UNLESS(0 <= slot && slot < RsaKeySlotCount);
/* Clear the info. */
g_rsa_key_infos[slot] = {};
/* Clear the modulus. */
ClearRsaKeySlot(slot, SE_RSA_KEYTABLE_ADDR_EXPMOD_SEL_MODULUS);
/* Clear the exponent. */
ClearRsaKeySlot(slot, SE_RSA_KEYTABLE_ADDR_EXPMOD_SEL_EXPONENT);
}
void LockRsaKeySlot(int slot, u32 flags) {
/* Validate the key slot. */
AMS_ABORT_UNLESS(0 <= slot && slot < RsaKeySlotCount);
/* Get the engine. */
auto *SE = GetRegisters();
/* Set non per-key flags. */
if ((flags & ~KeySlotLockFlags_PerKey) != 0) {
/* Pack the flags into the expected format. */
u32 value = 0;
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 0) : 0;
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 1) : 0;
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 2) : 0;
reg::Write(SE->SE_RSA_KEYTABLE_ACCESS[slot], SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYREAD, (flags & KeySlotLockFlags_KeyRead) != 0, DISABLE, ENABLE),
SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUPDATE, (flags & KeySlotLockFlags_KeyWrite) != 0, DISABLE, ENABLE),
SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUSE, (flags & KeySlotLockFlags_KeyUse) != 0, DISABLE, ENABLE));
}
/* Set per-key flag. */
if ((flags & KeySlotLockFlags_PerKey) != 0) {
reg::ReadWrite(SE->SE_RSA_SECURITY_PERKEY, REG_BITS_VALUE(slot, 1, 0));
}
}
void SetRsaKey(int slot, const void *mod, size_t mod_size, const void *exp, size_t exp_size) {
/* Validate the key slot and sizes. */
AMS_ABORT_UNLESS(0 <= slot && slot < RsaKeySlotCount);
AMS_ABORT_UNLESS(mod_size <= RsaSize);
AMS_ABORT_UNLESS(exp_size <= RsaSize);
/* Set the sizes in the info. */
auto &info = g_rsa_key_infos[slot];
info.modulus_size_val = (mod_size / 64) - 1;
info.exponent_size_val = (exp_size / 4);
/* Set the modulus and exponent. */
SetRsaKey(slot, SE_RSA_KEYTABLE_ADDR_EXPMOD_SEL_MODULUS, mod, mod_size);
SetRsaKey(slot, SE_RSA_KEYTABLE_ADDR_EXPMOD_SEL_EXPONENT, exp, exp_size);
}
}

View File

@ -0,0 +1,59 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "se_execute.hpp"
namespace ams::se {
namespace {
bool TestRegister(volatile u32 &r, u16 v) {
return (static_cast<u16>(reg::Read(r))) == v;
}
}
bool ValidateStickyBits(const StickyBits &bits) {
/* Get the registers. */
auto *SE = GetRegisters();
/* Check SE_SECURITY. */
if (!TestRegister(SE->SE_SE_SECURITY, bits.se_security)) { return false; }
/* Check TZRAM_SECURITY. */
if (!TestRegister(SE->SE_TZRAM_SECURITY, bits.tzram_security)) { return false; }
/* Check CRYPTO_SECURITY_PERKEY. */
if (!TestRegister(SE->SE_CRYPTO_SECURITY_PERKEY, bits.crypto_security_perkey)) { return false; }
/* Check CRYPTO_KEYTABLE_ACCESS. */
for (int i = 0; i < AesKeySlotCount; ++i) {
if (!TestRegister(SE->SE_CRYPTO_KEYTABLE_ACCESS[i], bits.crypto_keytable_access[i])) { return false; }
}
/* Test RSA_SCEURITY_PERKEY */
if (!TestRegister(SE->SE_CRYPTO_SECURITY_PERKEY, bits.rsa_security_perkey)) { return false; }
/* Check RSA_KEYTABLE_ACCESS. */
for (int i = 0; i < RsaKeySlotCount; ++i) {
if (!TestRegister(SE->SE_RSA_KEYTABLE_ACCESS[i], bits.rsa_keytable_access[i])) { return false; }
}
/* All sticky bits are valid. */
return true;
}
}

View File

@ -0,0 +1,35 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::tsec {
namespace {
}
void Lock() {
/* Set the tsec host1x syncpoint (160) to be secure. */
/* TODO: constexpr value. */
reg::ReadWrite(0x500038F8, REG_BITS_VALUE(0, 1, 0));
/* Clear the tsec host1x syncpoint. */
reg::Write(0x50003300, 0);
}
}

View File

@ -0,0 +1,113 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "uart_registers.hpp"
namespace ams::uart {
namespace {
constexpr inline const u16 UartRegisterOffsets[Port_Count] = {
secmon::MemoryRegionPhysicalDeviceUartA.GetAddress() - secmon::MemoryRegionPhysicalDeviceUart.GetAddress(),
secmon::MemoryRegionPhysicalDeviceUartB.GetAddress() - secmon::MemoryRegionPhysicalDeviceUart.GetAddress(),
secmon::MemoryRegionPhysicalDeviceUartC.GetAddress() - secmon::MemoryRegionPhysicalDeviceUart.GetAddress(),
};
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceUart.GetAddress();
volatile UartRegisters *GetRegisters(Port port) {
return reinterpret_cast<volatile UartRegisters *>(g_register_address + UartRegisterOffsets[port]);
}
void WaitSymbols(int baud, u32 num) {
util::WaitMicroSeconds(util::DivideUp(1'000'000, baud) * num);
}
void WaitCycles(int baud, u32 num) {
util::WaitMicroSeconds(util::DivideUp(1'000'000, 16 * baud) * num);
}
ALWAYS_INLINE void WaitFifoNotFull(volatile UartRegisters *uart) {
while ((uart->lsr & UART_LSR_TX_FIFO_FULL) != 0) { /* ... */ }
}
ALWAYS_INLINE void WaitFifoNotEmpty(volatile UartRegisters *uart) {
while ((uart->lsr & UART_LSR_RX_FIFO_EMPTY) != 0) { /* ... */ }
}
void WaitIdle(volatile UartRegisters *uart, u32 vendor_state) {
if (vendor_state & UART_VENDOR_STATE_TX_IDLE) {
while ((uart->lsr & UART_LSR_TMTY) == 0) { /* ... */ }
}
if (vendor_state & UART_VENDOR_STATE_RX_IDLE) {
while ((uart->lsr & UART_LSR_RDR) != 0) { /* ... */ }
}
}
}
void SetRegisterAddress(uintptr_t address) {
g_register_address = address;
}
void Initialize(Port port, int baud_rate, u32 flags) {
/* Get the registers. */
auto *uart = GetRegisters(port);
/* Parse flags. */
const bool inverted = (flags & Flag_Inverted) != 0;
/* Calculate the baud rate divisor. */
constexpr u32 UartClock = 408000000;
const u32 divisor = (UartClock + (baud_rate * 16) / 2) / (baud_rate * 16);
/* Disable DLAB and all interrupts. */
uart->lcr = uart->lcr & ~UART_LCR_DLAB;
uart->ier = 0;
uart->mcr = 0;
/* Setup the uart in FIFO mode. */
uart->lcr = UART_LCR_DLAB | UART_LCR_WD_LENGTH_8;
uart->dll = static_cast<u8>(divisor);
uart->dlh = static_cast<u8>(divisor >> 8);
uart->lcr = uart->lcr & ~UART_LCR_DLAB;
reg::Read(std::addressof(uart->spr));
/* Wait three symbols. */
WaitSymbols(baud_rate, 3);
/* Enable FIFO with default settings. */
uart->fcr = UART_FCR_FCR_EN_FIFO;
uart->irda_csr = inverted ? UART_IRDA_CSR_INVERT_TXD : 0;
reg::Read(std::addressof(uart->spr));
/* Wait three cycles. */
WaitCycles(baud_rate, 3);
/* Flush the FIFO. */
WaitIdle(uart, UART_VENDOR_STATE_TX_IDLE);
uart->fcr = uart->fcr | UART_FCR_RX_CLR | UART_FCR_TX_CLR;
WaitCycles(baud_rate, 32);
/* Wait for idle state. */
WaitIdle(uart, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE);
/* Set scratch register to 0. */
uart->spr = 0;
}
}

View File

@ -0,0 +1,180 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::uart {
struct UartRegisters {
union {
u32 thr;
u32 rbr;
u32 dll;
};
union {
u32 ier;
u32 dlh;
};
union {
u32 iir;
u32 fcr;
};
u32 lcr;
u32 mcr;
u32 lsr;
u32 msr;
u32 spr;
u32 irda_csr;
u32 rx_fifo_cfg;
u32 mie;
u32 vendor_status;
u32 reserved_30;
u32 reserved_34;
u32 reserved_38;
u32 asr;
};
static_assert(util::is_pod<UartRegisters>::value);
static_assert(sizeof(UartRegisters) == 0x40);
/* 36.3.12 UART_VENDOR_STATUS_0_0 */
enum UartVendorStatus {
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 */
};
/* 36.3.6 UART_LSR_0 */
enum UartLineStatus {
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 */
};
/* 36.3.4 UART_LCR_0 */
enum UartLineControl {
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) */
};
/* 36.3.3 UART_IIR_FCR_0 */
enum UartFifoControl {
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,
};
/* 36.3.2 UART_IER_DLAB_0_0 */
enum UartInterruptEnable {
UART_IER_IE_RHR = 1 << 0, /* Interrupt enable for Received Data Interrupt */
UART_IER_IE_THR = 1 << 1, /* Interrupt enable for Transmitter Holding Register Empty interrupt */
UART_IER_IE_RXS = 1 << 2, /* Interrupt enable for Receiver Line Status Interrupt */
UART_IER_IE_MSI = 1 << 3, /* Interrupt enable for Modem Status Interrupt */
UART_IER_IE_RX_TIMEOUT = 1 << 4, /* Interrupt enable for RX FIFO timeout */
UART_IER_IE_EORD = 1 << 5, /* Interrupt enable for Interrupt Enable for End of Received Data */
};
/* 36.3.3 UART_IIR_FCR_0 */
enum UartInterruptIdentification {
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,
};
/* 36.3.9 UART_IRDA_CSR_0 */
enum UartIrDAPulseCodingCSR {
UART_IRDA_CSR_INVERT_RXD = 1 << 0,
UART_IRDA_CSR_INVERT_TXD = 1 << 1,
UART_IRDA_CSR_INVERT_CTS = 1 << 2,
UART_IRDA_CSR_INVERT_RTS = 1 << 3,
UART_IRDA_CSR_PWT_A_BAUD_PULSE_3_14 = 0 << 6,
UART_IRDA_CSR_PWT_A_BAUD_PULSE_4_14 = 1 << 6,
UART_IRDA_CSR_SIR_A = 1 << 7,
};
}

View File

@ -0,0 +1,50 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::util {
namespace {
constinit uintptr_t g_timer_register_address = secmon::MemoryRegionPhysicalDeviceTimer.GetAddress();
ALWAYS_INLINE uintptr_t GetCurrentTimeRegisterAddress() {
return g_timer_register_address + 0x10;
}
}
void SetRegisterAddress(uintptr_t address) {
g_timer_register_address = address;
}
u32 GetMicroSeconds() {
return reg::Read(GetCurrentTimeRegisterAddress());
}
void WaitMicroSeconds(int us) {
const u32 start = reg::Read(GetCurrentTimeRegisterAddress());
u32 cur = start;
while ((cur - start) <= static_cast<u32>(us)) {
cur = reg::Read(GetCurrentTimeRegisterAddress());
}
}
void ClearMemory(void *ptr, size_t size) {
std::memset(ptr, 0, size);
}
}

View File

@ -0,0 +1,99 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
namespace ams::wdt {
namespace {
volatile uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceTimer.GetAddress();
#if defined(ATMOSPHERE_ARCH_ARM64)
NOINLINE void Reboot(uintptr_t registers) {
__asm__ __volatile__(
/* Get the current core. */
"mrs x12, mpidr_el1\n"
"and x12, x12, #0xFF\n"
/* Get the offsets of the registers we want to write */
"mov x10, #0x8\n"
"mov x11, #0x20\n"
"madd x10, x10, x12, %[registers]\n"
"madd x11, x11, x12, %[registers]\n"
"add x10, x10, #0x60\n"
"add x11, x11, #0x100\n"
/* Write the magic unlock pattern. */
"mov w9, #0xC45A\n"
"str w9, [x11, #0xC]\n"
/* Disable the counters. */
"mov w9, #0x2\n"
"str w9, [x11, #0x8]\n"
/* Start periodic timer. */
"mov w9, #0xC0000000\n"
"str w9, [x10]\n"
/* Set reboot source to the timer we started. */
"mov w9, #0x8015\n"
"add w9, w9, w12\n"
"str w9, [x11]\n"
/* Enable the counters. */
"mov w9, #0x1\n"
"str w9, [x11, #0x8]\n"
/* Wait forever. */
"1: b 1b"
: [registers]"=&r"(registers)
:
: "x9", "x10", "x11", "x12", "memory"
);
}
#elif defined(ATMOSPHERE_ARCH_ARM)
NOINLINE void Reboot(uintptr_t registers) {
/* Write the magic unlock pattern. */
reg::Write(registers + 0x18C, 0xC45A);
/* Disable the counters. */
reg::Write(registers + 0x188, 0x2);
/* Start periodic timer. */
reg::Write(registers + 0x080, 0xC0000000);
/* Set reboot source to the timer we started. */
reg::Write(registers + 0x180, 0x8019);
/* Enable the counters. */
reg::Write(registers + 0x188, 0x1);
while (true) { /* ... */ }
}
#endif
}
void SetRegisterAddress(uintptr_t address) {
g_register_address = address;
}
NOINLINE void Reboot() {
const uintptr_t registers = g_register_address;
Reboot(registers);
}
}

View File

@ -132,4 +132,8 @@ namespace ams::diag {
AbortWithValue(value); AbortWithValue(value);
} }
NORETURN WEAK_SYMBOL void AbortImpl() {
AbortWithValue(0);
}
} }

View File

@ -32,6 +32,7 @@ namespace ams::diag {
NORETURN NOINLINE void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) __attribute__((format(printf, 6, 7))); NORETURN NOINLINE void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) __attribute__((format(printf, 6, 7)));
NORETURN NOINLINE void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value); NORETURN NOINLINE void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value);
NORETURN NOINLINE void AbortImpl();
} }
@ -42,7 +43,7 @@ namespace ams::diag {
#define AMS_CALL_ABORT_IMPL(cond, ...) ::ams::diag::AbortImpl(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, 0, ## __VA_ARGS__) #define AMS_CALL_ABORT_IMPL(cond, ...) ::ams::diag::AbortImpl(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, 0, ## __VA_ARGS__)
#else #else
#define AMS_CALL_ASSERT_FAIL_IMPL(cond, ...) ::ams::diag::AssertionFailureImpl("", 0, "", "", 0) #define AMS_CALL_ASSERT_FAIL_IMPL(cond, ...) ::ams::diag::AssertionFailureImpl("", 0, "", "", 0)
#define AMS_CALL_ABORT_IMPL(cond, ...) ::ams::diag::AbortImpl("", 0, "", "", 0) #define AMS_CALL_ABORT_IMPL(cond, ...) ::ams::diag::AbortImpl()
#endif #endif
#ifdef AMS_ENABLE_ASSERTIONS #ifdef AMS_ENABLE_ASSERTIONS

View File

@ -142,7 +142,7 @@ namespace ams::crypto::impl {
u64 _block[IvSize / sizeof(u64)] = {}; u64 _block[IvSize / sizeof(u64)] = {};
util::StoreBigEndian(std::addressof(_block[(IvSize / sizeof(u64)) - 1]), count); util::StoreBigEndian(std::addressof(_block[(IvSize / sizeof(u64)) - 1]), count);
u16 acc; u16 acc = 0;
const u8 *block = reinterpret_cast<const u8 *>(_block); const u8 *block = reinterpret_cast<const u8 *>(_block);
for (s32 i = IvSize - 1; i >= 0; --i) { for (s32 i = IvSize - 1; i >= 0; --i) {
acc += (this->counter[i] + block[i]); acc += (this->counter[i] + block[i]);

View File

@ -59,4 +59,6 @@
#define AMS_LIKELY(expr) AMS_PREDICT_TRUE(expr, 1.0) #define AMS_LIKELY(expr) AMS_PREDICT_TRUE(expr, 1.0)
#define AMS_UNLIKELY(expr) AMS_PREDICT_FALSE(expr, 1.0) #define AMS_UNLIKELY(expr) AMS_PREDICT_FALSE(expr, 1.0)
#define AMS_ASSUME(expr) do { if (!static_cast<bool>((expr))) { __builtin_unreachable(); } } while (0)
#define AMS_CURRENT_FUNCTION_NAME __FUNCTION__ #define AMS_CURRENT_FUNCTION_NAME __FUNCTION__

View File

@ -19,16 +19,16 @@
namespace ams { inline namespace literals { namespace ams { inline namespace literals {
constexpr ALWAYS_INLINE size_t operator ""_KB(unsigned long long n) { constexpr ALWAYS_INLINE u64 operator ""_KB(unsigned long long n) {
return static_cast<size_t>(n) * size_t(1024); return static_cast<u64>(n) * UINT64_C(1024);
} }
constexpr ALWAYS_INLINE size_t operator ""_MB(unsigned long long n) { constexpr ALWAYS_INLINE u64 operator ""_MB(unsigned long long n) {
return operator ""_KB(n) * size_t(1024); return operator ""_KB(n) * UINT64_C(1024);
} }
constexpr ALWAYS_INLINE size_t operator ""_GB(unsigned long long n) { constexpr ALWAYS_INLINE u64 operator ""_GB(unsigned long long n) {
return operator ""_MB(n) * size_t(1024); return operator ""_MB(n) * UINT64_C(1024);
} }
} } } }

Some files were not shown because too many files have changed in this diff Show More