Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46146bd71c | ||
|
|
f7d4960cd3 | ||
|
|
a6c6a95053 | ||
|
|
5120b70231 | ||
|
|
96476a227b | ||
|
|
4586dce57b | ||
|
|
e3900de6c0 | ||
|
|
22fb4ff095 | ||
|
|
9a41e19004 | ||
|
|
b2f4e0c1b4 | ||
|
|
a0f1971353 | ||
|
|
37704d670b | ||
|
|
397d0c4295 | ||
|
|
3981527bb8 | ||
|
|
631de13133 | ||
|
|
2c7f32bbde | ||
|
|
443d43ed7e | ||
|
|
2532ceea2a | ||
|
|
0e8efbb9e9 | ||
|
|
9340183541 | ||
|
|
bd9b01e405 | ||
|
|
53957bb5c7 | ||
|
|
2b84a49ed7 | ||
|
|
895b332a86 | ||
|
|
88b81e5fb0 | ||
|
|
ac04e02a08 | ||
|
|
1c71d12d9d | ||
|
|
37738699f2 | ||
|
|
e973ef7533 | ||
|
|
2ee2a4f1ac | ||
|
|
2a2bffeb35 | ||
|
|
d04046ecaf | ||
|
|
f24171dc41 | ||
|
|
5b02c77400 | ||
|
|
2e7214b6fa | ||
|
|
d52179c708 | ||
|
|
388f9e6455 | ||
|
|
c547c7f0e7 | ||
|
|
4138abbefa | ||
|
|
1275eb0bf3 | ||
|
|
5ac9e45d86 | ||
|
|
feba788bc6 | ||
|
|
f4d10a4481 | ||
|
|
ff310a0647 | ||
|
|
85505db9b7 | ||
|
|
48b4dd48a4 | ||
|
|
8d46d901d9 | ||
|
|
1930880270 |
10
Makefile
10
Makefile
@@ -70,8 +70,8 @@ dist-no-debug: all
|
||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/config
|
||||
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
||||
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
|
||||
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
|
||||
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
|
||||
@@ -99,9 +99,13 @@ dist-no-debug: all
|
||||
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
|
||||
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
||||
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
|
||||
cd atmosphere-$(AMSVER); zip -r ../atmosphere-EXPERIMENTAL-$(AMSVER).zip ./*; cd ../;
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
|
||||
rm -r atmosphere-$(AMSVER)
|
||||
mkdir out
|
||||
mv atmosphere-EXPERIMENTAL-$(AMSVER).zip out/atmosphere-EXPERIMENTAL-$(AMSVER).zip
|
||||
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
|
||||
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
|
||||
|
||||
@@ -120,7 +124,7 @@ dist: dist-no-debug
|
||||
mkdir atmosphere-$(AMSVER)-debug
|
||||
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
|
||||
cp fusee/fusee-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
|
||||
cp fusee/fusee-secondary/fusee-secondary.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
||||
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
||||
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
|
||||
cp sept/sept-secondary/sept-secondary.elf atmosphere-$(AMSVER)-debug/sept-secondary.elf
|
||||
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf
|
||||
|
||||
@@ -9,4 +9,4 @@ stage2_entrypoint = 0xF0000000
|
||||
; To force-enable nogc, add nogc = 1
|
||||
; To force-disable nogc, add nogc = 0
|
||||
|
||||
; To opt in to using Atmosphere's NCM reimplementation, add enable_ncm = 1
|
||||
; To opt out of using Atmosphere's NCM reimplementation, add disable_ncm = 1
|
||||
|
||||
@@ -4,7 +4,7 @@ Building Atmosphère is a very straightforward process that relies almost exclus
|
||||
## Dependencies
|
||||
+ [devkitA64](https://devkitpro.org)
|
||||
+ [devkitARM](https://devkitpro.org)
|
||||
+ [Python 2 or 3](https://www.python.org) (optional)
|
||||
+ [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed)
|
||||
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
||||
|
||||
## Instructions
|
||||
|
||||
@@ -1,4 +1,31 @@
|
||||
# Changelog
|
||||
## 0.15.0
|
||||
+ fusee-primary's panic display was updated to automatically identify and give suggestions to resolve many of the most common errors users encounter.
|
||||
+ Having been tested as well as I can alone, `mesosphere` (atmosphère's reimplementation of the Nintendo Switch kernel) is now available for users interested in trying it.
|
||||
+ Beginning in this release and until it is stable and well-tested, atmosphère will distribute two zips.
|
||||
+ Users who wish to opt-in to mesosphere should download and extract the "cool kids" zip ("atmosphere-EXPERIMENTAL-").
|
||||
+ Users who do not wish to use mesosphere should continue using the normal zip ("atmosphere-").
|
||||
+ Users may detect whether mesosphere is active in system settings.
|
||||
+ When mesosphere is active, the system version string will display "M.15.0" rather than "0.15.0", and so on for future releases.
|
||||
+ Crash reports and the like will contain information on whether or not the user is using mesosphere, as well.
|
||||
+ There are "probably" no material user-facing benefits to using mesosphere at this time.
|
||||
+ Developers may be interested in the fact that mesosphere provides many newer SVC APIs even when on lower firmware versions.
|
||||
+ The primary benefit to using mesosphere is that any issues you may encounter and report to me will be fixed.
|
||||
+ All users who choose to opt in to using mesosphere have my deepest gratitude.
|
||||
+ **Note:** If using hekate instead of fusee-primary, you will have to wait for the next hekate release for mesosphere to function, as hekate's support has not yet been included in an official release build.
|
||||
+ This will be updated in the release notes when hekate provides a new release.
|
||||
+ As mentioned in previous release notes, when mesosphere is stable and well-tested, it will be enabled by default and atmosphère's version will transition to 1.0.0.
|
||||
+ Having been tested sufficiently over the last half-year, Atmosphere's NCM implementation is now opt-out, rather than opt in.
|
||||
+ In the unlikely event that any issues are encountered, please report them to @SciresM.
|
||||
+ Users interested in opting out of using our implementation should set `stratosphere!disable_ncm = 1` in BCT.ini.
|
||||
+ The NCM implementation will stop being opt-out in a future update, probably around the same time that mesosphere becomes opt-out instead of opt-in.
|
||||
+ Several bugs were fixed, including:
|
||||
+ Loader now sets HBL's thread priority to a higher value when loading it in applet mode.
|
||||
+ This fixes an extremely-slow launch ("hang") when using applet-HBL with certain games that do not suspend while inactive (e.g. Super Mario Sunshine).
|
||||
+ set.mitm now caches user language configuration much more heavily.
|
||||
+ This severely reduces lag in certain games which misuse the "nn::oe::GetDesiredLanguage()" API.
|
||||
+ A bug was fixed that could cause erpt to fatal when loading an official save file that had error report attachments in it.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 0.14.4
|
||||
+ Several bugs were fixed involving the official jit sysmodule added in 10.0.0.
|
||||
+ A Process handle leak was fixed when JitPlugin NRRs were registered with the `ro` sysmodule.
|
||||
|
||||
@@ -9,7 +9,7 @@ This file is located under the `/atmosphere/config/` folder on your SD card and
|
||||
Atmosphère provides its own default splashscreen which is displayed at boot time. However, this can be replaced at will.
|
||||
|
||||
The boot splashscreen must be a BMP file, it must be 720x1280 (1280x720 rotated 90 degrees left/counterclockwise/anti-clockwise) resolution, and be in 32-bit ARGB format. You can use image editing software such as GIMP or Photoshop to export the image in this format.
|
||||
|
||||
|
||||
Add the following lines to BCT.ini and change the value of `custom_splash` to the actual path and filename of your boot splashscreen:
|
||||
```
|
||||
[stage2]
|
||||
@@ -29,11 +29,11 @@ nogc = X
|
||||
0 = force-disable nogc, so Atmosphère will always enable the Game Card reader.
|
||||
```
|
||||
|
||||
### NCM opt-in
|
||||
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module, but currently this is not enabled by default. If you wish to enable this reimplementation add the following line to the `stratosphere` section:
|
||||
### NCM opt-out
|
||||
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module. If you wish to disable this reimplementation add the following line to the `stratosphere` section:
|
||||
```
|
||||
[stratosphere]
|
||||
enable_ncm = 1
|
||||
disable_ncm = 1
|
||||
```
|
||||
|
||||
### Logging
|
||||
|
||||
@@ -96,10 +96,6 @@ namespace ams::secmon {
|
||||
util::ClearMemory(reinterpret_cast<void *>(address + size / 2), size / 2);
|
||||
}
|
||||
|
||||
bool IsPhysicalMemoryAddress(uintptr_t address) {
|
||||
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ClearBootCodeHigh() {
|
||||
@@ -130,6 +126,10 @@ namespace ams::secmon {
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPhysicalMemoryAddress(uintptr_t address) {
|
||||
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
|
||||
}
|
||||
|
||||
void UnmapTzram() {
|
||||
/* Get the tables. */
|
||||
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
namespace ams::secmon {
|
||||
|
||||
bool IsPhysicalMemoryAddress(uintptr_t address);
|
||||
size_t GetPhysicalMemorySize();
|
||||
|
||||
void UnmapTzram();
|
||||
|
||||
@@ -648,7 +648,7 @@ namespace ams::secmon {
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||
@@ -907,7 +907,7 @@ namespace ams::secmon {
|
||||
reg::Write(MC + MC_SMMU_PPCS1_ASID, MC_REG_BITS_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_PPCS1_ASID_PPCS1_ASID, BpmpAsid));
|
||||
|
||||
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||
|
||||
@@ -22,7 +22,7 @@ SetRegisterAllowed(MC_SMMU_CONFIG); /* 0x010 */
|
||||
SetRegisterAllowed(MC_SMMU_PTB_ASID); /* 0x01C */
|
||||
SetRegisterAllowed(MC_SMMU_PTB_DATA); /* 0x020 */
|
||||
SetRegisterAllowed(MC_SMMU_TLB_FLUSH); /* 0x030 */
|
||||
SetRegisterAllowed(MC_SMMU_PTC_FLUSH); /* 0x034 */
|
||||
SetRegisterAllowed(MC_SMMU_PTC_FLUSH_0); /* 0x034 */
|
||||
SetRegisterAllowed(MC_EMEM_CFG); /* 0x050 */
|
||||
SetRegisterAllowed(MC_EMEM_ADR_CFG); /* 0x054 */
|
||||
SetRegisterAllowed(MC_EMEM_ARB_CFG); /* 0x090 */
|
||||
@@ -53,7 +53,7 @@ SetRegisterAllowed(MC_SMMU_DCB_ASID); /* 0x244 */
|
||||
SetRegisterAllowed(MC_SMMU_HC_ASID); /* 0x250 */
|
||||
SetRegisterAllowed(MC_SMMU_HDA_ASID); /* 0x254 */
|
||||
SetRegisterAllowed(MC_SMMU_ISP2_ASID); /* 0x258 */
|
||||
SetRegisterAllowed(MC_SMMU_NVENC_ASID); /* 0x264 */
|
||||
SetRegisterAllowed(MC_SMMU_MSENC_NVENC_ASID); /* 0x264 */
|
||||
SetRegisterAllowed(MC_SMMU_NV_ASID); /* 0x268 */
|
||||
SetRegisterAllowed(MC_SMMU_NV2_ASID); /* 0x26C */
|
||||
SetRegisterAllowed(MC_SMMU_PPCS_ASID); /* 0x270 */
|
||||
|
||||
@@ -141,6 +141,9 @@ namespace ams::secmon::smc {
|
||||
{ 0xC3000006, Restriction_Normal, SmcShowError },
|
||||
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
|
||||
{ 0xC3000008, Restriction_Normal, SmcReadWriteRegister },
|
||||
|
||||
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
|
||||
{ 0xC3000409, Restriction_Normal, SmcSetConfig },
|
||||
};
|
||||
|
||||
constinit HandlerInfo g_ams_handlers[] = {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
#include "../secmon_error.hpp"
|
||||
#include "../secmon_map.hpp"
|
||||
#include "../secmon_misc.hpp"
|
||||
#include "../secmon_page_mapper.hpp"
|
||||
#include "../secmon_user_power_management.hpp"
|
||||
@@ -157,6 +158,8 @@ namespace ams::secmon::smc {
|
||||
return value.value;
|
||||
}
|
||||
|
||||
constinit u64 g_payload_address = 0;
|
||||
|
||||
SmcResult GetConfig(SmcArguments &args, bool kern) {
|
||||
switch (static_cast<ConfigItem>(args.r[1])) {
|
||||
case ConfigItem::DisableProgramVerification:
|
||||
@@ -267,6 +270,14 @@ namespace ams::secmon::smc {
|
||||
/* NOTE: This may return values other than 1 in the future. */
|
||||
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0);
|
||||
break;
|
||||
case ConfigItem::ExospherePayloadAddress:
|
||||
/* Gets the physical address of the reboot payload buffer, if one exists. */
|
||||
if (g_payload_address != 0) {
|
||||
args.r[1] = g_payload_address;
|
||||
} else {
|
||||
return SmcResult::NotInitialized;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return SmcResult::InvalidArgument;
|
||||
}
|
||||
@@ -309,6 +320,17 @@ namespace ams::secmon::smc {
|
||||
return SmcResult::NotImplemented;
|
||||
}
|
||||
break;
|
||||
case ConfigItem::ExospherePayloadAddress:
|
||||
if (g_payload_address == 0) {
|
||||
if (secmon::IsPhysicalMemoryAddress(args.r[2])) {
|
||||
g_payload_address = args.r[2];
|
||||
} else {
|
||||
return SmcResult::InvalidArgument;
|
||||
}
|
||||
} else {
|
||||
return SmcResult::Busy;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return SmcResult::InvalidArgument;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace ams::secmon::smc {
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
};
|
||||
|
||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||
|
||||
108
exosphere/sdmmc_test/Makefile
Normal file
108
exosphere/sdmmc_test/Makefile
Normal file
@@ -0,0 +1,108 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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))))/../../libraries/config/templates/exosphere.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),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 OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES))))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I.
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib -L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD) check_libexo
|
||||
|
||||
$(BUILD): check_libexo
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
check_libexo:
|
||||
@$(MAKE) --no-print-directory -C ../../libraries/libexosphere arm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf *.lz4
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).bin
|
||||
|
||||
$(OUTPUT).bin : $(OUTPUT).elf
|
||||
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).elf : $(OFILES) ../../../libraries/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/libexosphere.a
|
||||
|
||||
%.elf:
|
||||
@echo linking $(notdir $@)
|
||||
$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h: %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
194
exosphere/sdmmc_test/sdmmc_test.ld
Normal file
194
exosphere/sdmmc_test/sdmmc_test.ld
Normal file
@@ -0,0 +1,194 @@
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_ZN3ams10sdmmc_test5StartEv)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
NULL : ORIGIN = 0, LENGTH = 4K
|
||||
test_fw : ORIGIN = 0x40010000, LENGTH = 32K
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* =========== CODE section =========== */
|
||||
PROVIDE(__start__ = ORIGIN(test_fw));
|
||||
. = __start__;
|
||||
__code_start = . ;
|
||||
|
||||
.crt0 :
|
||||
{
|
||||
KEEP (*(.crt0 .crt0.*))
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.vectors :
|
||||
{
|
||||
KEEP (*(.vectors .vectors.*))
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.plt :
|
||||
{
|
||||
*(.plt)
|
||||
*(.iplt)
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
|
||||
/* =========== RODATA section =========== */
|
||||
. = ALIGN(8);
|
||||
__rodata_start = . ;
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >test_fw
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >test_fw
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >test_fw
|
||||
|
||||
.hash : { *(.hash) } >test_fw
|
||||
|
||||
/* =========== DATA section =========== */
|
||||
. = ALIGN(8);
|
||||
__data_start = . ;
|
||||
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >test_fw
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >test_fw
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >test_fw
|
||||
|
||||
.preinit_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >test_fw
|
||||
|
||||
.init_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >test_fw
|
||||
|
||||
.fini_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >test_fw
|
||||
|
||||
.ctors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >test_fw
|
||||
|
||||
.dtors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >test_fw
|
||||
|
||||
__got_start__ = .;
|
||||
|
||||
.got : { *(.got) *(.igot) } >test_fw
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) } >test_fw
|
||||
|
||||
__got_end__ = .;
|
||||
|
||||
.data ALIGN(8) :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
} >test_fw
|
||||
|
||||
__bss_start__ = .;
|
||||
.bss ALIGN(8) :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(16);
|
||||
} >test_fw
|
||||
__bss_end__ = .;
|
||||
|
||||
__end__ = ABSOLUTE(.) ;
|
||||
|
||||
__total_size__ = (__end__ - __start__);
|
||||
|
||||
__stack_top__ = 0x40031000;
|
||||
__stack_bottom__ = 0x40030000;
|
||||
|
||||
/* ==================
|
||||
==== Metadata ====
|
||||
================== */
|
||||
|
||||
/* Discard sections that difficult post-processing */
|
||||
/DISCARD/ : { *(.group .comment .note .interp) }
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
}
|
||||
7
exosphere/sdmmc_test/sdmmc_test.specs
Normal file
7
exosphere/sdmmc_test/sdmmc_test.specs
Normal file
@@ -0,0 +1,7 @@
|
||||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -T %:getenv(TOPDIR /sdmmc_test.ld) --gc-sections --nmagic -nostdlib -nostartfiles
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
||||
146
exosphere/sdmmc_test/source/sdmmc_test_main.cpp
Normal file
146
exosphere/sdmmc_test/source/sdmmc_test_main.cpp
Normal 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>
|
||||
|
||||
namespace ams::sdmmc_test {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||
|
||||
constexpr inline auto Port = sdmmc::Port_SdCard0;
|
||||
alignas(8) constinit u8 g_sd_work_buffer[sdmmc::SdCardWorkBufferSize];
|
||||
|
||||
constexpr inline u32 SectorIndex = 0;
|
||||
constexpr inline u32 SectorCount = 2;
|
||||
|
||||
NORETURN void PmcMainReboot() {
|
||||
/* Write enable to MAIN_RESET. */
|
||||
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
|
||||
|
||||
/* Wait forever until we're reset. */
|
||||
AMS_INFINITE_LOOP();
|
||||
}
|
||||
|
||||
void CheckResult(const Result result) {
|
||||
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
|
||||
if (R_FAILED(result)) {
|
||||
DEBUG[1] = result.GetValue();
|
||||
PmcMainReboot();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Perform butchered hwinit. */
|
||||
/* TODO: replace with simpler, non-C logic. */
|
||||
/* nx_hwinit(); */
|
||||
|
||||
/* Clear output buffer for debug. */
|
||||
std::memset((void *)0x40038000, 0xAA, 0x400);
|
||||
|
||||
/* Normally, these pins get configured by boot sysmodule during initial pinmux config. */
|
||||
/* However, they're required to access the SD card. */
|
||||
{
|
||||
const uintptr_t apb_misc = dd::QueryIoMapping(0x70000000, 0x4000);
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CLK, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CLK_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CMD, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CMD_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT3, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT3_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT2, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT2_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT1, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT1_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT0, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_DMIC3_CLK, PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, RSVD2));
|
||||
}
|
||||
|
||||
/* Debug signaler. */
|
||||
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
|
||||
DEBUG[0] = 0;
|
||||
DEBUG[1] = 0xAAAAAAAA;
|
||||
|
||||
/* Initialize sdmmc library. */
|
||||
sdmmc::Initialize(Port);
|
||||
DEBUG[0] = 1;
|
||||
|
||||
sdmmc::SetSdCardWorkBuffer(Port, g_sd_work_buffer, sizeof(g_sd_work_buffer));
|
||||
DEBUG[0] = 2;
|
||||
|
||||
Result result = sdmmc::Activate(Port);
|
||||
DEBUG[0] = 3;
|
||||
CheckResult(result);
|
||||
|
||||
/* Read the first two sectors from disk. */
|
||||
void * const sector_dst = reinterpret_cast<void *>(0x40038000);
|
||||
result = sdmmc::Read(sector_dst, SectorCount * sdmmc::SectorSize, Port, SectorIndex, SectorCount);
|
||||
DEBUG[0] = 4;
|
||||
CheckResult(result);
|
||||
|
||||
/* Get the connection status. */
|
||||
sdmmc::SpeedMode speed_mode;
|
||||
sdmmc::BusWidth bus_width;
|
||||
result = sdmmc::CheckSdCardConnection(std::addressof(speed_mode), std::addressof(bus_width), Port);
|
||||
|
||||
/* Save status for debug. */
|
||||
DEBUG[0] = 5;
|
||||
DEBUG[1] = result.GetValue();
|
||||
DEBUG[2] = static_cast<u32>(speed_mode);
|
||||
DEBUG[3] = static_cast<u32>(bus_width);
|
||||
|
||||
/* Perform a reboot. */
|
||||
PmcMainReboot();
|
||||
}
|
||||
|
||||
NORETURN void ExceptionHandler() {
|
||||
PmcMainReboot();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams::diag {
|
||||
|
||||
void AbortImpl() {
|
||||
sdmmc_test::ExceptionHandler();
|
||||
}
|
||||
|
||||
}
|
||||
37
exosphere/sdmmc_test/source/sdmmc_test_start.s
Normal file
37
exosphere/sdmmc_test/source/sdmmc_test_start.s
Normal 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/>.
|
||||
*/
|
||||
|
||||
.section .crt0.text._ZN3ams10sdmmc_test5StartEv, "ax", %progbits
|
||||
.align 3
|
||||
.global _ZN3ams10sdmmc_test5StartEv
|
||||
_ZN3ams10sdmmc_test5StartEv:
|
||||
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||
msr cpsr_cxsf, #0xDF
|
||||
|
||||
/* Set the stack pointer. */
|
||||
ldr sp, =__stack_top__
|
||||
|
||||
/* Set our link register to the exception handler. */
|
||||
ldr lr, =_ZN3ams10sdmmc_test16ExceptionHandlerEv
|
||||
|
||||
/* Call init array functions. */
|
||||
bl __libc_init_array
|
||||
|
||||
/* Invoke main. */
|
||||
b _ZN3ams10sdmmc_test4MainEv
|
||||
|
||||
/* Infinite loop. */
|
||||
2: b 2b
|
||||
@@ -30,7 +30,7 @@ _ZN3ams8warmboot5StartEv:
|
||||
|
||||
/* Invoke main. */
|
||||
ldr r0, =_metadata
|
||||
bl _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
||||
b _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
||||
|
||||
/* Infinite loop. */
|
||||
1: b 1b
|
||||
@@ -24,6 +24,9 @@
|
||||
#include "lib/log.h"
|
||||
#include "display/video_fb.h"
|
||||
|
||||
#define PROGRAM_ID_AMS_MITM 0x010041544D530000ull
|
||||
#define PROGRAM_ID_BOOT 0x0100000000000005ull
|
||||
|
||||
static uint32_t g_panic_code = 0;
|
||||
|
||||
static const char *get_error_desc_str(uint32_t error_desc) {
|
||||
@@ -53,6 +56,61 @@ static const char *get_error_desc_str(uint32_t error_desc) {
|
||||
}
|
||||
}
|
||||
|
||||
static void _try_suggest_fix(const atmosphere_fatal_error_ctx *ctx) {
|
||||
/* Try to recognize certain errors automatically, and suggest fixes for them. */
|
||||
const char *suggestion = NULL;
|
||||
|
||||
if (ctx->error_desc == 0xFFE) {
|
||||
if (ctx->program_id == PROGRAM_ID_AMS_MITM) {
|
||||
/* When a user has archive bits set improperly, attempting to create an automatic backup will fail */
|
||||
/* to create the file path with error 0x202 (fs::ResultPathNotFound()) */
|
||||
if (ctx->gprs[0] == 0x202) {
|
||||
/* When the archive bit error is occurring, it manifests as failure to create automatic backup. */
|
||||
/* Thus, we can search the stack for the automatic backups path. */
|
||||
const char * const automatic_backups_prefix = "automatic_backups/X" /* ..... */;
|
||||
const int prefix_len = strlen(automatic_backups_prefix);
|
||||
|
||||
for (size_t i = 0; i + prefix_len < ctx->stack_dump_size; ++i) {
|
||||
if (memcmp(&ctx->stack_dump[i], automatic_backups_prefix, prefix_len) == 0) {
|
||||
suggestion = "The atmosphere directory may improperly have archive\n"
|
||||
"bits set. Please try running an archive bit fixer tool\n"
|
||||
"(for example, the one in Hekate).\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (ctx->gprs[0] == 0x249A02) { /* fs::ResultResultExFatUnavailable() */
|
||||
/* When a user installs non-exFAT firm but has an exFAT formatted SD card, this error will */
|
||||
/* be returned on attempt to access the SD card. */
|
||||
suggestion = "Your console has non-exFAT firmware installed, but your SD card\n"
|
||||
"is formatted as exFAT. Format your SD card as FAT32, or manually\n"
|
||||
"flash exFAT firmware to package2.\n";
|
||||
}
|
||||
} else if (ctx->program_id == PROGRAM_ID_BOOT) {
|
||||
/* 9.x -> 10.x updated the API for SvcQueryIoMapping. */
|
||||
/* This can cause the kernel to reject incorrect-ABI calls by boot when a partial update is applied */
|
||||
/* (older kernel in package2, for some reason). */
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
if (ctx->gprs[i] == 0xF201) {
|
||||
suggestion = "A partial update may have been improperly performed.\n"
|
||||
"To fix, try manually flashing latest package2 to MMC.\n"
|
||||
"\n"
|
||||
"For help doing this, seek support in the ReSwitched or\n"
|
||||
"Nintendo Homebrew discord servers.\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ctx->error_desc == 0xF00) { /* Kernel Panic */
|
||||
suggestion = "Please contact SciresM#0524 on Discord, or create an issue\n"
|
||||
"on the Atmosphere GitHub issue tracker. Thank you very much\n"
|
||||
"for helping to test mesosphere.\n";
|
||||
}
|
||||
|
||||
if (suggestion != NULL) {
|
||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n%s", suggestion);
|
||||
}
|
||||
}
|
||||
|
||||
static void _check_and_display_atmosphere_fatal_error(void) {
|
||||
/* Check for valid magic. */
|
||||
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
|
||||
@@ -86,7 +144,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
||||
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic = 0xCCCCCCCC;
|
||||
|
||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "A fatal error occurred when running Atmosph\xe8re.\n");
|
||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Title ID: %016llx\n", ctx.title_id);
|
||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Program ID: %016llx\n", ctx.program_id);
|
||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc);
|
||||
|
||||
/* Save context to the SD card. */
|
||||
@@ -101,6 +159,9 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to print a fix suggestion via automatic error detection. */
|
||||
_try_suggest_fix(&ctx);
|
||||
|
||||
/* Display error. */
|
||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nPress POWER to reboot\n");
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t error_desc;
|
||||
uint64_t title_id;
|
||||
uint64_t program_id;
|
||||
union {
|
||||
uint64_t gprs[32];
|
||||
struct {
|
||||
|
||||
@@ -186,11 +186,15 @@ DEPENDS := $(OFILES:.o=.d)
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).bin
|
||||
|
||||
$(OUTPUT).bin : $(OUTPUT).elf
|
||||
$(OUTPUT).bin : $(OUTPUT)-experimental.bin
|
||||
@python $(TOPDIR)/fusee_make_standard.py $(OUTPUT)-experimental.bin $(OUTPUT).bin
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT)-experimental.bin : $(OUTPUT)-experimental.elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
$(OUTPUT)-experimental.elf : $(OFILES)
|
||||
|
||||
%.elf: $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
|
||||
37
fusee/fusee-secondary/fusee_make_standard.py
Normal file
37
fusee/fusee-secondary/fusee_make_standard.py
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
import sys, os
|
||||
from struct import pack as pk, unpack as up
|
||||
|
||||
def make_standard(exp):
|
||||
std = exp[:]
|
||||
_, metadata_offset, is_exp = up('<III', exp[:12])
|
||||
assert is_exp == 1
|
||||
|
||||
# Patch the experimental flag to zero.
|
||||
std = std[:8] + pk('<I', 0) + std[12:]
|
||||
|
||||
# Locate the mesosphere content header, patch to be experimental.
|
||||
magic, size, code_ofs, content_ofs, num_contents, ver, sup_ver, rev = up('<IIIIIIII', exp[metadata_offset:metadata_offset + 0x20])
|
||||
for i in range(num_contents):
|
||||
start, size, cnt_type, flag0, flag1, flag2, pad = up('<IIBBBBI', exp[content_ofs + 0x20 * i:content_ofs + 0x20 * i + 0x10])
|
||||
if cnt_type == 10: # CONTENT_TYPE_KRN
|
||||
assert exp[content_ofs + 0x20 * i + 0x10:content_ofs + 0x20 * i + 0x10 + len(b'mesosphere') + 1] == (b'mesosphere\x00')
|
||||
assert flag0 == 0 and flag1 == 0 and flag2 == 0
|
||||
std = std[:content_ofs + 0x20 * i] + pk('<IIBBBBI', start, size, cnt_type, flag0 | 0x1, flag1, flag2, pad) + std[content_ofs + 0x20 * i + 0x10:]
|
||||
|
||||
return std
|
||||
|
||||
|
||||
def main(argc, argv):
|
||||
if argc != 3:
|
||||
print('Usage: %s input output' % argv[0])
|
||||
return 1
|
||||
with open(argv[1], 'rb') as f:
|
||||
experimental = f.read()
|
||||
with open(argv[2], 'wb') as f:
|
||||
f.write(make_standard(experimental))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(len(sys.argv), sys.argv))
|
||||
@@ -254,4 +254,6 @@ SECTIONS
|
||||
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
|
||||
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
|
||||
PROVIDE(__kernel_ldr_bin_size__ = kernel_ldr_bin_end - kernel_ldr_bin);
|
||||
PROVIDE(__mesosphere_bin_start__ = mesosphere_bin - __start__);
|
||||
PROVIDE(__mesosphere_bin_size__ = mesosphere_bin_end - mesosphere_bin);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "exosphere_bin.h"
|
||||
#include "mesosphere_bin.h"
|
||||
#include "sept_secondary_00_enc.h"
|
||||
#include "sept_secondary_01_enc.h"
|
||||
#include "sept_secondary_dev_00_enc.h"
|
||||
@@ -66,6 +67,8 @@
|
||||
|
||||
extern const uint8_t warmboot_bin[];
|
||||
|
||||
extern int fusee_is_experimental(void);
|
||||
|
||||
static const uint8_t retail_pkc_modulus[0x100] = {
|
||||
0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD,
|
||||
0xCB, 0x4E, 0x4A, 0x52, 0x0B, 0x1A, 0x8E, 0xDE, 0x41, 0x87, 0x6F, 0xB7, 0x31, 0x05, 0x5F, 0xAA,
|
||||
@@ -209,11 +212,11 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
|
||||
strat_cfg->has_nogc_config = true;
|
||||
sscanf(value, "%d", &tmp);
|
||||
strat_cfg->enable_nogc = tmp != 0;
|
||||
} else if (strcmp(name, STRATOSPHERE_ENABLE_NCM_KEY) == 0) {
|
||||
} else if (strcmp(name, STRATOSPHERE_DISABLE_NCM_KEY) == 0) {
|
||||
sscanf(value, "%d", &tmp);
|
||||
strat_cfg->ncm_enabled = tmp != 0;
|
||||
if (strat_cfg->ncm_enabled) {
|
||||
stratosphere_enable_ncm();
|
||||
strat_cfg->ncm_disabled = tmp != 0;
|
||||
if (strat_cfg->ncm_disabled) {
|
||||
stratosphere_disable_ncm();
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
@@ -624,6 +627,7 @@ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
||||
uint32_t nxboot_main(void) {
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||
const bool is_experimental = fusee_is_experimental();
|
||||
package2_header_t *package2;
|
||||
size_t package2_size;
|
||||
void *tsec_fw;
|
||||
@@ -933,7 +937,6 @@ uint32_t nxboot_main(void) {
|
||||
}
|
||||
|
||||
/* Configure mesosphere. */
|
||||
/* TODO: Support non-SD/embedded mesosphere. */
|
||||
{
|
||||
size_t sd_meso_size = get_file_size("atmosphere/mesosphere.bin");
|
||||
if (sd_meso_size != 0) {
|
||||
@@ -948,6 +951,20 @@ uint32_t nxboot_main(void) {
|
||||
fatal_error("Error: failed to read atmosphere/mesosphere.bin!\n");
|
||||
}
|
||||
mesosphere_size = sd_meso_size;
|
||||
} else if (is_experimental) {
|
||||
mesosphere_size = mesosphere_bin_size;
|
||||
|
||||
mesosphere = malloc(mesosphere_size);
|
||||
|
||||
if (mesosphere == NULL) {
|
||||
fatal_error("[NXBOOT] Out of memory!\n");
|
||||
}
|
||||
|
||||
memcpy(mesosphere, mesosphere_bin, mesosphere_size);
|
||||
|
||||
if (mesosphere_size == 0) {
|
||||
fatal_error("[NXBOOT] Could not read embedded mesosphere!\n");
|
||||
}
|
||||
} else {
|
||||
mesosphere = NULL;
|
||||
mesosphere_size = 0;
|
||||
|
||||
@@ -30,6 +30,9 @@ _start:
|
||||
|
||||
.word (_metadata - _start)
|
||||
|
||||
_is_experimental:
|
||||
.word 0x00000001 /* is experimental */
|
||||
|
||||
_crt0:
|
||||
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||
msr cpsr_cxsf, #0xDF
|
||||
@@ -68,6 +71,14 @@ _crt0:
|
||||
ldr r1, [r1]
|
||||
b main
|
||||
|
||||
.arm
|
||||
.global fusee_is_experimental
|
||||
.type fusee_is_experimental, %function
|
||||
fusee_is_experimental:
|
||||
ldr r0, =_is_experimental
|
||||
ldr r0, [r0]
|
||||
bx lr
|
||||
|
||||
/* Fusee-secondary header. */
|
||||
.align 5
|
||||
_metadata:
|
||||
@@ -135,6 +146,17 @@ _content_headers:
|
||||
.asciz "exosphere"
|
||||
.align 5
|
||||
|
||||
/* mesosphere content header */
|
||||
.word __mesosphere_bin_start__
|
||||
.word __mesosphere_bin_size__
|
||||
.byte CONTENT_TYPE_KRN
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "mesosphere"
|
||||
.align 5
|
||||
|
||||
/* fusee_primary content header */
|
||||
.word __fusee_primary_bin_start__
|
||||
.word __fusee_primary_bin_size__
|
||||
@@ -249,7 +271,7 @@ _content_headers:
|
||||
.word __ncm_kip_start__
|
||||
.word __ncm_kip_size__
|
||||
.byte CONTENT_TYPE_KIP
|
||||
.byte CONTENT_FLAG0_EXPERIMENTAL
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.word 0xCCCCCCCC
|
||||
@@ -267,17 +289,6 @@ _content_headers:
|
||||
.asciz "emummc"
|
||||
.align 5
|
||||
|
||||
/* kernel_ldr content header */
|
||||
.word __kernel_ldr_bin_start__
|
||||
.word __kernel_ldr_bin_size__
|
||||
.byte CONTENT_TYPE_KLD
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "kernel_ldr"
|
||||
.align 5
|
||||
|
||||
/* splash_screen content header */
|
||||
.word __splash_screen_bmp_start__
|
||||
.word __splash_screen_bmp_size__
|
||||
|
||||
@@ -48,7 +48,7 @@ static bool g_stratosphere_pm_enabled = true;
|
||||
static bool g_stratosphere_ams_mitm_enabled = true;
|
||||
static bool g_stratosphere_spl_enabled = true;
|
||||
static bool g_stratosphere_boot_enabled = true;
|
||||
static bool g_stratosphere_ncm_enabled = false;
|
||||
static bool g_stratosphere_ncm_enabled = true;
|
||||
|
||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
|
||||
|
||||
@@ -58,17 +58,17 @@ emummc_fs_ver_t stratosphere_get_fs_version(void) {
|
||||
return g_fs_ver;
|
||||
}
|
||||
|
||||
void stratosphere_enable_ncm(void) {
|
||||
void stratosphere_disable_ncm(void) {
|
||||
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
|
||||
/* and does not think it likely there is any possibility of undesirable behavior */
|
||||
/* when using the NCM reimplementation. However, because NCM manages critical save games */
|
||||
/* the implementation will default to off for some time, until the code has been thoroughly */
|
||||
/* tested in practice. */
|
||||
/* the implementation may be optionally disabled for those not comfortable using it. */
|
||||
|
||||
/* PLEASE NOTE: The default behavior will be NCM on in a future atmosphere release, */
|
||||
/* and this opt-in functionality will be removed at that time. */
|
||||
|
||||
g_stratosphere_ncm_enabled = true;
|
||||
/* PLEASE NOTE: The NCM reimplementation has been well-tested, and correspondingly opt-out */
|
||||
/* functionality will be removed in Atmosphere 1.0.0. */
|
||||
|
||||
g_stratosphere_ncm_enabled = false;
|
||||
}
|
||||
|
||||
/* GCC doesn't consider the size as const... we have to write it ourselves. */
|
||||
|
||||
@@ -30,7 +30,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware);
|
||||
ini1_header_t *stratosphere_get_sd_files_ini1(void);
|
||||
void stratosphere_free_ini1(void);
|
||||
|
||||
void stratosphere_enable_ncm(void);
|
||||
void stratosphere_disable_ncm(void);
|
||||
|
||||
emummc_fs_ver_t stratosphere_get_fs_version(void);
|
||||
|
||||
@@ -39,10 +39,10 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_in
|
||||
typedef struct {
|
||||
bool has_nogc_config;
|
||||
bool enable_nogc;
|
||||
bool ncm_enabled;
|
||||
bool ncm_disabled;
|
||||
} stratosphere_cfg_t;
|
||||
|
||||
#define STRATOSPHERE_NOGC_KEY "nogc"
|
||||
#define STRATOSPHERE_ENABLE_NCM_KEY "enable_ncm"
|
||||
#define STRATOSPHERE_DISABLE_NCM_KEY "disable_ncm"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = f6dac1e67793233cc916f317cf517244dd348a5e
|
||||
parent = 909a1767a6080bab7ea6032c00e1ff4cec993af0
|
||||
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
||||
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
||||
method = merge
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -15,8 +15,10 @@ endif
|
||||
|
||||
endif
|
||||
|
||||
ATMOSPHERE_BUILD_SETTINGS ?=
|
||||
|
||||
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
||||
export ATMOSPHERE_SETTINGS := -fPIE -g
|
||||
export ATMOSPHERE_SETTINGS := -fPIE -g $(ATMOSPHERE_BUILD_SETTINGS)
|
||||
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
|
||||
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
|
||||
-Wno-format-truncation -Wno-format-zero-length -Wno-stringop-truncation
|
||||
@@ -132,10 +134,15 @@ FIND_SOURCE_FILES=$(foreach dir,$1,$(filter-out $(notdir $(wildcard $(dir)/*.arc
|
||||
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),os,$(ATMOSPHERE_OS_NAME),$2)) \
|
||||
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES_EX,$(dir),cpu,$(ATMOSPHERE_CPU_NAME) $(ATMOSPHERE_CPU_EXTENSIONS),$2))
|
||||
|
||||
ATMOSPHERE_GCH_IDENTIFIER ?= ams_placeholder_gch_identifier
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Rules for compiling pre-compiled headers
|
||||
#---------------------------------------------------------------------------------
|
||||
%.gch: %.hpp
|
||||
@echo $<
|
||||
$(CXX) -w -x c++-header -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||
@cp $@ $(<).gch
|
||||
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
|
||||
@echo Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
|
||||
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||
|
||||
%.hpp.gch: %.hpp
|
||||
@echo Precompiling $(notdir $<)
|
||||
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||
|
||||
@@ -29,7 +29,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
|
||||
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
|
||||
|
||||
export LIBS := -lmesosphere
|
||||
export LIBS := -l$(LIBMESOSPHERE_NAME)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
|
||||
@@ -112,6 +112,7 @@ $(OFILES) : $(GCH_FILES)
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
libc.o: CFLAGS += -fno-builtin -fno-lto
|
||||
libgcc_division.arch.arm.o: CFLAGS += -fno-builtin -fno-lto
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <vapours.hpp>
|
||||
|
||||
#include <exosphere/common.hpp>
|
||||
#include <exosphere/reg.hpp>
|
||||
#include <exosphere/hw.hpp>
|
||||
#include <exosphere/util.hpp>
|
||||
#include <exosphere/mmu.hpp>
|
||||
@@ -41,4 +40,3 @@
|
||||
#include <exosphere/actmon.hpp>
|
||||
#include <exosphere/pmc.hpp>
|
||||
#include <exosphere/secmon.hpp>
|
||||
#include <exosphere/tegra.hpp>
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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_clkrst.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_pinmux.hpp>
|
||||
#include <exosphere/tegra/tegra_pg_up.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>
|
||||
@@ -20,14 +20,6 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
27
libraries/libexosphere/source/libc/libexo_cxx.cpp
Normal file
27
libraries/libexosphere/source/libc/libexo_cxx.cpp
Normal 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/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* cxx implementation details to be stubbed here, as needed. */
|
||||
void __cxa_pure_virtual() { AMS_ABORT("pure virtual function call"); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
160
libraries/libexosphere/source/libc/libgcc_division.arch.arm.c
Normal file
160
libraries/libexosphere/source/libc/libgcc_division.arch.arm.c
Normal file
@@ -0,0 +1,160 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
* Copyright (c) 2014, STMicroelectronics International N.V.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Form ABI specifications:
|
||||
* int __aeabi_idiv(int numerator, int denominator);
|
||||
* unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
|
||||
*
|
||||
* typedef struct { int quot; int rem; } idiv_return;
|
||||
* typedef struct { unsigned quot; unsigned rem; } uidiv_return;
|
||||
*
|
||||
* __value_in_regs idiv_return __aeabi_idivmod(int numerator,
|
||||
* int *denominator);
|
||||
* __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator,
|
||||
* unsigned denominator);
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */
|
||||
struct qr {
|
||||
unsigned q; /* computed quotient */
|
||||
unsigned r; /* computed remainder */
|
||||
unsigned q_n; /* specficies if quotient shall be negative */
|
||||
unsigned r_n; /* specficies if remainder shall be negative */
|
||||
};
|
||||
|
||||
static void uint_div_qr(unsigned numerator, unsigned denominator,
|
||||
struct qr *qr);
|
||||
|
||||
/* returns in R0 and R1 by tail calling an asm function */
|
||||
unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator);
|
||||
|
||||
unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
|
||||
|
||||
/* returns in R0 and R1 by tail calling an asm function */
|
||||
signed __aeabi_idivmod(signed numerator, signed denominator);
|
||||
|
||||
signed __aeabi_idiv(signed numerator, signed denominator);
|
||||
|
||||
/*
|
||||
* __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator)
|
||||
* Numerator and Denominator are received in R0 and R1.
|
||||
* Where __ste_idivmod_ret_t is returned in R0 and R1.
|
||||
*
|
||||
* __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator,
|
||||
* unsigned denominator)
|
||||
* Numerator and Denominator are received in R0 and R1.
|
||||
* Where __ste_uidivmod_ret_t is returned in R0 and R1.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
signed ret_idivmod_values(signed quotient, signed remainder);
|
||||
unsigned ret_uidivmod_values(unsigned quotient, unsigned remainder);
|
||||
#else
|
||||
#error "Compiler not supported"
|
||||
#endif
|
||||
|
||||
static void division_qr(unsigned n, unsigned p, struct qr *qr)
|
||||
{
|
||||
unsigned i = 1, q = 0;
|
||||
if (p == 0) {
|
||||
qr->r = 0xFFFFFFFF; /* division by 0 */
|
||||
return;
|
||||
}
|
||||
|
||||
while ((p >> 31) == 0) {
|
||||
i = i << 1; /* count the max division steps */
|
||||
p = p << 1; /* increase p until it has maximum size*/
|
||||
}
|
||||
|
||||
while (i > 0) {
|
||||
q = q << 1; /* write bit in q at index (size-1) */
|
||||
if (n >= p)
|
||||
{
|
||||
n -= p;
|
||||
q++;
|
||||
}
|
||||
p = p >> 1; /* decrease p */
|
||||
i = i >> 1; /* decrease remaining size in q */
|
||||
}
|
||||
qr->r = n;
|
||||
qr->q = q;
|
||||
}
|
||||
|
||||
static void uint_div_qr(unsigned numerator, unsigned denominator, struct qr *qr)
|
||||
{
|
||||
|
||||
division_qr(numerator, denominator, qr);
|
||||
|
||||
/* negate quotient and/or remainder according to requester */
|
||||
if (qr->q_n)
|
||||
qr->q = -qr->q;
|
||||
if (qr->r_n)
|
||||
qr->r = -qr->r;
|
||||
}
|
||||
|
||||
unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
|
||||
{
|
||||
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||
|
||||
uint_div_qr(numerator, denominator, &qr);
|
||||
|
||||
return qr.q;
|
||||
}
|
||||
|
||||
unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator)
|
||||
{
|
||||
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||
|
||||
uint_div_qr(numerator, denominator, &qr);
|
||||
|
||||
return ret_uidivmod_values(qr.q, qr.r);
|
||||
}
|
||||
|
||||
signed __aeabi_idiv(signed numerator, signed denominator)
|
||||
{
|
||||
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||
|
||||
if (((numerator < 0) && (denominator > 0)) ||
|
||||
((numerator > 0) && (denominator < 0)))
|
||||
qr.q_n = 1; /* quotient shall be negate */
|
||||
if (numerator < 0) {
|
||||
numerator = -numerator;
|
||||
qr.r_n = 1; /* remainder shall be negate */
|
||||
}
|
||||
if (denominator < 0)
|
||||
denominator = -denominator;
|
||||
|
||||
uint_div_qr(numerator, denominator, &qr);
|
||||
|
||||
return qr.q;
|
||||
}
|
||||
|
||||
signed __aeabi_idivmod(signed numerator, signed denominator)
|
||||
{
|
||||
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||
|
||||
if (((numerator < 0) && (denominator > 0)) ||
|
||||
((numerator > 0) && (denominator < 0)))
|
||||
qr.q_n = 1; /* quotient shall be negate */
|
||||
if (numerator < 0) {
|
||||
numerator = -numerator;
|
||||
qr.r_n = 1; /* remainder shall be negate */
|
||||
}
|
||||
if (denominator < 0)
|
||||
denominator = -denominator;
|
||||
|
||||
uint_div_qr(numerator, denominator, &qr);
|
||||
|
||||
return ret_idivmod_values(qr.q, qr.r);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (c) 2014, STMicroelectronics International N.V.
|
||||
*/
|
||||
|
||||
/*
|
||||
* signed ret_idivmod_values(signed quot, signed rem);
|
||||
* return quotient and remaining the EABI way (regs r0,r1)
|
||||
*/
|
||||
.section .text.ret_idivmod_values, "ax", %progbits
|
||||
.globl ret_idivmod_values
|
||||
.align 0
|
||||
.syntax unified
|
||||
ret_idivmod_values:
|
||||
bx lr
|
||||
.type ret_idivmod_values, %function
|
||||
.size ret_idivmod_values, .-ret_idivmod_values
|
||||
|
||||
/*
|
||||
* unsigned ret_uidivmod_values(unsigned quot, unsigned rem);
|
||||
* return quotient and remaining the EABI way (regs r0,r1)
|
||||
*/
|
||||
.section .text.ret_uidivmod_values, "ax", %progbits
|
||||
.globl ret_uidivmod_values
|
||||
.align 0
|
||||
.syntax unified
|
||||
ret_uidivmod_values:
|
||||
bx lr
|
||||
.type ret_uidivmod_values, %function
|
||||
.size ret_uidivmod_values, .-ret_uidivmod_values
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
|
||||
This file is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any
|
||||
later version.
|
||||
This file is distributed in the hope that 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.
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
.section .text.__gnu_thumb1_case_uqi, "ax", %progbits
|
||||
.globl __gnu_thumb1_case_uqi
|
||||
.align 0
|
||||
.thumb_func
|
||||
.syntax unified
|
||||
__gnu_thumb1_case_uqi:
|
||||
push {r1}
|
||||
mov r1, lr
|
||||
lsrs r1, r1, #1
|
||||
lsls r1, r1, #1
|
||||
ldrb r1, [r1, r0]
|
||||
lsls r1, r1, #1
|
||||
add lr, lr, r1
|
||||
pop {r1}
|
||||
bx lr
|
||||
.type __gnu_thumb1_case_uqi, %function
|
||||
.size __gnu_thumb1_case_uqi, .-__gnu_thumb1_case_uqi
|
||||
@@ -1,12 +1,14 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# pull in common atmosphere configuration
|
||||
#---------------------------------------------------------------------------------
|
||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
||||
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||
include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
|
||||
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
||||
|
||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
@@ -28,7 +30,7 @@ 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)))
|
||||
ifneq ($(__RECURSIVE__),1)
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
||||
@@ -54,7 +56,7 @@ 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 GCH_DIRS := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
@@ -62,41 +64,70 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I.
|
||||
|
||||
.PHONY: clean all
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ATMOSPHERE_BUILD_CONFIGS :=
|
||||
all: release
|
||||
|
||||
define ATMOSPHERE_ADD_TARGET
|
||||
|
||||
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
|
||||
|
||||
$(strip $1): $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||
|
||||
$$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2) : $$(ATMOSPHERE_LIBRARY_DIR) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(SOURCES) $$(INCLUDES) $$(GCH_DIRS)
|
||||
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(CURDIR)/$$@ $(3) \
|
||||
ATMOSPHERE_GCH_IDENTIFIER="$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1)" \
|
||||
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||
-f $$(THIS_MAKEFILE)
|
||||
|
||||
clean-$(strip $1):
|
||||
@echo clean $(strip $1) ...
|
||||
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
|
||||
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
|
||||
ATMOSPHERE_BUILD_SETTINGS="" \
|
||||
))
|
||||
|
||||
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, $(TARGET)_debug.a, \
|
||||
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
|
||||
))
|
||||
|
||||
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
|
||||
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
|
||||
))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: lib/$(TARGET).a
|
||||
|
||||
lib:
|
||||
-include $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME).mk
|
||||
|
||||
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
|
||||
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
|
||||
|
||||
.PHONY: clean all $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||
|
||||
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
release:
|
||||
$(ATMOSPHERE_BUILD_DIR)/%:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
|
||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
||||
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
|
||||
DEPSDIR=$(CURDIR)/release \
|
||||
--no-print-directory -C release \
|
||||
-f $(CURDIR)/Makefile
|
||||
|
||||
dist-bin: all
|
||||
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib
|
||||
|
||||
dist-src:
|
||||
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile
|
||||
|
||||
dist: dist-src dist-bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr release lib *.bz2
|
||||
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2 $(ALL_GCH_FILES)
|
||||
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
|
||||
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
|
||||
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES),$(notdir $(patsubst %.hpp.gch/,%.d,$(dir $(hdr)))))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace ams::kern {
|
||||
private:
|
||||
friend class KScopedSchedulerLock;
|
||||
friend class KScopedSchedulerLockAndSleep;
|
||||
friend class KScopedDisableDispatch;
|
||||
private:
|
||||
SchedulingState state;
|
||||
bool is_active;
|
||||
@@ -161,8 +162,9 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void ScheduleOnInterrupt() {
|
||||
KScopedDisableDispatch dd;
|
||||
GetCurrentThread().DisableDispatch();
|
||||
this->Schedule();
|
||||
GetCurrentThread().EnableDispatch();
|
||||
}
|
||||
|
||||
void RescheduleOtherCores(u64 cores_needing_scheduling);
|
||||
|
||||
@@ -559,20 +559,7 @@ namespace ams::kern {
|
||||
GetCurrentThread().DisableDispatch();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ~KScopedDisableDispatch() {
|
||||
GetCurrentThread().EnableDispatch();
|
||||
}
|
||||
};
|
||||
|
||||
class KScopedEnableDispatch {
|
||||
public:
|
||||
explicit ALWAYS_INLINE KScopedEnableDispatch() {
|
||||
GetCurrentThread().EnableDispatch();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ~KScopedEnableDispatch() {
|
||||
GetCurrentThread().DisableDispatch();
|
||||
}
|
||||
~KScopedDisableDispatch();
|
||||
};
|
||||
|
||||
ALWAYS_INLINE KExceptionContext *GetExceptionContext(KThread *thread) {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mesosphere.hpp>
|
||||
#include "kern_mc_registers.hpp"
|
||||
|
||||
#if defined(MESOSPHERE_BUILD_FOR_DEBUGGING) || defined(MESOSPHERE_BUILD_FOR_AUDITING)
|
||||
#define MESOSPHERE_ENABLE_MEMORY_CONTROLLER_INTERRUPT
|
||||
|
||||
@@ -78,13 +78,11 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
void WaitOtherCpuPowerOff() {
|
||||
constexpr u64 PmcPhysicalAddress = 0x7000E400;
|
||||
constexpr u64 APBDEV_PMC_PWRGATE_STATUS = PmcPhysicalAddress + 0x38;
|
||||
|
||||
constexpr u32 PWRGATE_STATUS_CE123_MASK = ((1u << 3) - 1) << 9;
|
||||
|
||||
u32 value;
|
||||
do {
|
||||
bool res = smc::ReadWriteRegister(std::addressof(value), APBDEV_PMC_PWRGATE_STATUS, 0, 0);
|
||||
bool res = smc::ReadWriteRegister(std::addressof(value), PmcPhysicalAddress + APBDEV_PMC_PWRGATE_STATUS, 0, 0);
|
||||
MESOSPHERE_ASSERT(res);
|
||||
} while ((value & PWRGATE_STATUS_CE123_MASK) != 0);
|
||||
}
|
||||
|
||||
@@ -308,6 +308,15 @@ namespace ams::kern::board::nintendo::nx {
|
||||
g_secure_applet_memory_used = false;
|
||||
}
|
||||
|
||||
u64 GetVersionIdentifier() {
|
||||
u64 value = kern::GetTargetFirmware();
|
||||
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MICRO) << 32;
|
||||
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MINOR) << 40;
|
||||
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MAJOR) << 48;
|
||||
value |= static_cast<u64>('M') << 56;
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Initialization. */
|
||||
@@ -534,10 +543,14 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
void KSystemControl::StopSystem(void *arg) {
|
||||
if (arg != nullptr) {
|
||||
/* Get the address of the legacy IRAM region. */
|
||||
const KVirtualAddress iram_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 64_KB;
|
||||
constexpr size_t RebootPayloadSize = 0x2E000;
|
||||
|
||||
/* NOTE: Atmosphere extension; if we received an exception context from Panic(), */
|
||||
/* generate a fatal error report using it. */
|
||||
const KExceptionContext *e_ctx = static_cast<const KExceptionContext *>(arg);
|
||||
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 0x3E000);
|
||||
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(iram_address + RebootPayloadSize);
|
||||
|
||||
/* Clear the fatal context. */
|
||||
std::memset(f_ctx, 0xCC, sizeof(*f_ctx));
|
||||
@@ -553,6 +566,10 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* Set module base. */
|
||||
f_ctx->module_base = KMemoryLayout::GetKernelCodeRegionExtents().GetAddress();
|
||||
|
||||
/* Set afsr1. */
|
||||
f_ctx->afsr0 = 0;
|
||||
f_ctx->afsr1 = GetVersionIdentifier();
|
||||
|
||||
/* Copy registers. */
|
||||
for (size_t i = 0; i < util::size(e_ctx->x); ++i) {
|
||||
f_ctx->gprs[i] = e_ctx->x[i];
|
||||
@@ -581,8 +598,27 @@ namespace ams::kern::board::nintendo::nx {
|
||||
}
|
||||
}
|
||||
|
||||
/* Trigger a reboot to rcm. */
|
||||
smc::init::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToRcm);
|
||||
/* Try to get a payload address. */
|
||||
const KMemoryRegion *cached_region = nullptr;
|
||||
u64 reboot_payload_paddr = 0;
|
||||
if (smc::TryGetConfig(std::addressof(reboot_payload_paddr), 1, smc::ConfigItem::ExospherePayloadAddress) && KMemoryLayout::IsLinearMappedPhysicalAddress(cached_region, reboot_payload_paddr, RebootPayloadSize)) {
|
||||
/* If we have a payload, reboot to it. */
|
||||
const KVirtualAddress reboot_payload = KMemoryLayout::GetLinearVirtualAddress(KPhysicalAddress(reboot_payload_paddr));
|
||||
|
||||
/* Clear IRAM. */
|
||||
std::memset(GetVoidPointer(iram_address), 0xCC, RebootPayloadSize);
|
||||
|
||||
/* Copy the payload to iram. */
|
||||
for (size_t i = 0; i < RebootPayloadSize / sizeof(u32); ++i) {
|
||||
GetPointer<volatile u32>(iram_address)[i] = GetPointer<volatile u32>(reboot_payload)[i];
|
||||
}
|
||||
|
||||
/* Reboot. */
|
||||
smc::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToPayload);
|
||||
} else {
|
||||
/* If we don't have a payload, reboot to rcm. */
|
||||
smc::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToRcm);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_call_smc_on_panic) {
|
||||
|
||||
@@ -19,11 +19,7 @@
|
||||
|
||||
#include "kern_bpmp_api.hpp"
|
||||
#include "kern_atomics_registers.hpp"
|
||||
#include "kern_clkrst_registers.hpp"
|
||||
#include "kern_evp_registers.hpp"
|
||||
#include "kern_flow_registers.hpp"
|
||||
#include "kern_ictlr_registers.hpp"
|
||||
#include "kern_pmc_registers.hpp"
|
||||
#include "kern_sema_registers.hpp"
|
||||
|
||||
namespace ams::kern::board::nintendo::nx::lps {
|
||||
|
||||
@@ -1,526 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define MC_INTSTATUS 0x0
|
||||
#define MC_INTMASK 0x4
|
||||
#define MC_ERR_STATUS 0x8
|
||||
#define MC_ERR_ADR 0xc
|
||||
#define MC_SMMU_CONFIG 0x10
|
||||
#define MC_SMMU_TLB_CONFIG 0x14
|
||||
#define MC_SMMU_PTC_CONFIG 0x18
|
||||
#define MC_SMMU_PTB_ASID 0x1c
|
||||
#define MC_SMMU_PTB_DATA 0x20
|
||||
#define MC_SMMU_TLB_FLUSH 0x30
|
||||
#define MC_SMMU_PTC_FLUSH_0 0x34
|
||||
#define MC_SMMU_PTC_FLUSH_1 0x9b8
|
||||
#define MC_SMMU_ASID_SECURITY 0x38
|
||||
#define MC_SMMU_ASID_SECURITY_1 0x3c
|
||||
#define MC_SMMU_ASID_SECURITY_2 0x9e0
|
||||
#define MC_SMMU_ASID_SECURITY_3 0x9e4
|
||||
#define MC_SMMU_ASID_SECURITY_4 0x9e8
|
||||
#define MC_SMMU_ASID_SECURITY_5 0x9ec
|
||||
#define MC_SMMU_ASID_SECURITY_6 0x9f0
|
||||
#define MC_SMMU_ASID_SECURITY_7 0x9f4
|
||||
#define MC_SMMU_AFI_ASID 0x238
|
||||
#define MC_SMMU_AVPC_ASID 0x23c
|
||||
#define MC_SMMU_DC_ASID 0x240
|
||||
#define MC_SMMU_DCB_ASID 0x244
|
||||
#define MC_SMMU_HC_ASID 0x250
|
||||
#define MC_SMMU_HDA_ASID 0x254
|
||||
#define MC_SMMU_ISP2_ASID 0x258
|
||||
#define MC_SMMU_MSENC_NVENC_ASID 0x264
|
||||
#define MC_SMMU_NV_ASID 0x268
|
||||
#define MC_SMMU_NV2_ASID 0x26c
|
||||
#define MC_SMMU_PPCS_ASID 0x270
|
||||
#define MC_SMMU_SATA_ASID 0x274
|
||||
#define MC_SMMU_VDE_ASID 0x27c
|
||||
#define MC_SMMU_VI_ASID 0x280
|
||||
#define MC_SMMU_VIC_ASID 0x284
|
||||
#define MC_SMMU_XUSB_HOST_ASID 0x288
|
||||
#define MC_SMMU_XUSB_DEV_ASID 0x28c
|
||||
#define MC_SMMU_TSEC_ASID 0x294
|
||||
#define MC_SMMU_PPCS1_ASID 0x298
|
||||
#define MC_SMMU_DC1_ASID 0xa88
|
||||
#define MC_SMMU_SDMMC1A_ASID 0xa94
|
||||
#define MC_SMMU_SDMMC2A_ASID 0xa98
|
||||
#define MC_SMMU_SDMMC3A_ASID 0xa9c
|
||||
#define MC_SMMU_SDMMC4A_ASID 0xaa0
|
||||
#define MC_SMMU_ISP2B_ASID 0xaa4
|
||||
#define MC_SMMU_GPU_ASID 0xaa8
|
||||
#define MC_SMMU_GPUB_ASID 0xaac
|
||||
#define MC_SMMU_PPCS2_ASID 0xab0
|
||||
#define MC_SMMU_NVDEC_ASID 0xab4
|
||||
#define MC_SMMU_APE_ASID 0xab8
|
||||
#define MC_SMMU_SE_ASID 0xabc
|
||||
#define MC_SMMU_NVJPG_ASID 0xac0
|
||||
#define MC_SMMU_HC1_ASID 0xac4
|
||||
#define MC_SMMU_SE1_ASID 0xac8
|
||||
#define MC_SMMU_AXIAP_ASID 0xacc
|
||||
#define MC_SMMU_ETR_ASID 0xad0
|
||||
#define MC_SMMU_TSECB_ASID 0xad4
|
||||
#define MC_SMMU_TSEC1_ASID 0xad8
|
||||
#define MC_SMMU_TSECB1_ASID 0xadc
|
||||
#define MC_SMMU_NVDEC1_ASID 0xae0
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
|
||||
#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0
|
||||
#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4
|
||||
#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8
|
||||
#define MC_PCFIFO_CLIENT_CONFIG3 0xddc
|
||||
#define MC_PCFIFO_CLIENT_CONFIG4 0xde0
|
||||
#define MC_EMEM_CFG 0x50
|
||||
#define MC_EMEM_ADR_CFG 0x54
|
||||
#define MC_EMEM_ADR_CFG_DEV0 0x58
|
||||
#define MC_EMEM_ADR_CFG_DEV1 0x5c
|
||||
#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60
|
||||
#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64
|
||||
#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68
|
||||
#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c
|
||||
#define MC_SECURITY_CFG0 0x70
|
||||
#define MC_SECURITY_CFG1 0x74
|
||||
#define MC_SECURITY_CFG3 0x9bc
|
||||
#define MC_SECURITY_RSV 0x7c
|
||||
#define MC_EMEM_ARB_CFG 0x90
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
|
||||
#define MC_EMEM_ARB_TIMING_RCD 0x98
|
||||
#define MC_EMEM_ARB_TIMING_RP 0x9c
|
||||
#define MC_EMEM_ARB_TIMING_RC 0xa0
|
||||
#define MC_EMEM_ARB_TIMING_RAS 0xa4
|
||||
#define MC_EMEM_ARB_TIMING_FAW 0xa8
|
||||
#define MC_EMEM_ARB_TIMING_RRD 0xac
|
||||
#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
|
||||
#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
|
||||
#define MC_EMEM_ARB_TIMING_R2R 0xb8
|
||||
#define MC_EMEM_ARB_TIMING_W2W 0xbc
|
||||
#define MC_EMEM_ARB_TIMING_R2W 0xc0
|
||||
#define MC_EMEM_ARB_TIMING_W2R 0xc4
|
||||
#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
|
||||
#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
|
||||
#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
|
||||
#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
|
||||
#define MC_EMEM_ARB_DA_TURNS 0xd0
|
||||
#define MC_EMEM_ARB_DA_COVERS 0xd4
|
||||
#define MC_EMEM_ARB_MISC0 0xd8
|
||||
#define MC_EMEM_ARB_MISC1 0xdc
|
||||
#define MC_EMEM_ARB_MISC2 0xc8
|
||||
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
|
||||
#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
|
||||
#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0
|
||||
#define MC_EMEM_ARB_OVERRIDE 0xe8
|
||||
#define MC_EMEM_ARB_RSV 0xec
|
||||
#define MC_CLKEN_OVERRIDE 0xf4
|
||||
#define MC_TIMING_CONTROL_DBG 0xf8
|
||||
#define MC_TIMING_CONTROL 0xfc
|
||||
#define MC_STAT_CONTROL 0x100
|
||||
#define MC_STAT_STATUS 0x104
|
||||
#define MC_STAT_EMC_CLOCK_LIMIT 0x108
|
||||
#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c
|
||||
#define MC_STAT_EMC_CLOCKS 0x110
|
||||
#define MC_STAT_EMC_CLOCKS_MSBS 0x114
|
||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118
|
||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158
|
||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c
|
||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c
|
||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20
|
||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24
|
||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198
|
||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8
|
||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c
|
||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac
|
||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28
|
||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c
|
||||
#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0
|
||||
#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0
|
||||
#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120
|
||||
#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c
|
||||
#define MC_STAT_EMC_SET0_COUNT 0x138
|
||||
#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c
|
||||
#define MC_STAT_EMC_SET1_COUNT 0x178
|
||||
#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c
|
||||
#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140
|
||||
#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144
|
||||
#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180
|
||||
#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184
|
||||
#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148
|
||||
#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c
|
||||
#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188
|
||||
#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c
|
||||
#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150
|
||||
#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190
|
||||
#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8
|
||||
#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc
|
||||
#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8
|
||||
#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc
|
||||
#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0
|
||||
#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0
|
||||
#define MC_CLIENT_HOTRESET_CTRL 0x200
|
||||
#define MC_CLIENT_HOTRESET_CTRL_1 0x970
|
||||
#define MC_CLIENT_HOTRESET_STATUS 0x204
|
||||
#define MC_CLIENT_HOTRESET_STATUS_1 0x974
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94
|
||||
#define MC_EMEM_ARB_HYSTERESIS_0 0x218
|
||||
#define MC_EMEM_ARB_HYSTERESIS_1 0x21c
|
||||
#define MC_EMEM_ARB_HYSTERESIS_2 0x220
|
||||
#define MC_EMEM_ARB_HYSTERESIS_3 0x224
|
||||
#define MC_EMEM_ARB_HYSTERESIS_4 0xb84
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0
|
||||
#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
|
||||
#define MC_RESERVED_RSV 0x3fc
|
||||
#define MC_DISB_EXTRA_SNAP_LEVELS 0x408
|
||||
#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4
|
||||
#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0
|
||||
#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18
|
||||
#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08
|
||||
#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10
|
||||
#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c
|
||||
#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40
|
||||
#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414
|
||||
#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc
|
||||
#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c
|
||||
#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14
|
||||
#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0
|
||||
#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac
|
||||
#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c
|
||||
#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48
|
||||
#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8
|
||||
#define MC_USBX_EXTRA_SNAP_LEVELS 0x404
|
||||
#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8
|
||||
#define MC_SD_EXTRA_SNAP_LEVELS 0xa04
|
||||
#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c
|
||||
#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8
|
||||
#define MC_GK_EXTRA_SNAP_LEVELS 0xa00
|
||||
#define MC_VE2_EXTRA_SNAP_LEVELS 0x410
|
||||
#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44
|
||||
#define MC_VIDEO_PROTECT_BOM 0x648
|
||||
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
|
||||
#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978
|
||||
#define MC_VIDEO_PROTECT_REG_CTRL 0x650
|
||||
#define MC_ERR_VPR_STATUS 0x654
|
||||
#define MC_ERR_VPR_ADR 0x658
|
||||
#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418
|
||||
#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590
|
||||
#define MC_IRAM_BOM 0x65c
|
||||
#define MC_IRAM_TOM 0x660
|
||||
#define MC_IRAM_ADR_HI 0x980
|
||||
#define MC_IRAM_REG_CTRL 0x964
|
||||
#define MC_EMEM_CFG_ACCESS_CTRL 0x664
|
||||
#define MC_TZ_SECURITY_CTRL 0x668
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4
|
||||
#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc
|
||||
#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8
|
||||
#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80
|
||||
#define MC_SEC_CARVEOUT_BOM 0x670
|
||||
#define MC_SEC_CARVEOUT_SIZE_MB 0x674
|
||||
#define MC_SEC_CARVEOUT_ADR_HI 0x9d4
|
||||
#define MC_SEC_CARVEOUT_REG_CTRL 0x678
|
||||
#define MC_ERR_SEC_STATUS 0x67c
|
||||
#define MC_ERR_SEC_ADR 0x680
|
||||
#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684
|
||||
#define MC_STUTTER_CONTROL 0x688
|
||||
#define MC_RESERVED_RSV_1 0x958
|
||||
#define MC_DVFS_PIPE_SELECT 0x95c
|
||||
#define MC_AHB_PTSA_MIN 0x4e0
|
||||
#define MC_AUD_PTSA_MIN 0x54c
|
||||
#define MC_MLL_MPCORER_PTSA_RATE 0x44c
|
||||
#define MC_RING2_PTSA_RATE 0x440
|
||||
#define MC_USBD_PTSA_RATE 0x530
|
||||
#define MC_USBX_PTSA_MIN 0x528
|
||||
#define MC_USBD_PTSA_MIN 0x534
|
||||
#define MC_APB_PTSA_MAX 0x4f0
|
||||
#define MC_JPG_PTSA_RATE 0x584
|
||||
#define MC_DIS_PTSA_MIN 0x420
|
||||
#define MC_AVP_PTSA_MAX 0x4fc
|
||||
#define MC_AVP_PTSA_RATE 0x4f4
|
||||
#define MC_RING1_PTSA_MIN 0x480
|
||||
#define MC_DIS_PTSA_MAX 0x424
|
||||
#define MC_SD_PTSA_MAX 0x4d8
|
||||
#define MC_MSE_PTSA_RATE 0x4c4
|
||||
#define MC_VICPC_PTSA_MIN 0x558
|
||||
#define MC_PCX_PTSA_MAX 0x4b4
|
||||
#define MC_ISP_PTSA_RATE 0x4a0
|
||||
#define MC_A9AVPPC_PTSA_MIN 0x48c
|
||||
#define MC_RING2_PTSA_MAX 0x448
|
||||
#define MC_AUD_PTSA_RATE 0x548
|
||||
#define MC_HOST_PTSA_MIN 0x51c
|
||||
#define MC_MLL_MPCORER_PTSA_MAX 0x454
|
||||
#define MC_SD_PTSA_MIN 0x4d4
|
||||
#define MC_RING1_PTSA_RATE 0x47c
|
||||
#define MC_JPG_PTSA_MIN 0x588
|
||||
#define MC_HDAPC_PTSA_MIN 0x62c
|
||||
#define MC_AVP_PTSA_MIN 0x4f8
|
||||
#define MC_JPG_PTSA_MAX 0x58c
|
||||
#define MC_VE_PTSA_MAX 0x43c
|
||||
#define MC_DFD_PTSA_MAX 0x63c
|
||||
#define MC_VICPC_PTSA_RATE 0x554
|
||||
#define MC_GK_PTSA_MAX 0x544
|
||||
#define MC_VICPC_PTSA_MAX 0x55c
|
||||
#define MC_SDM_PTSA_MAX 0x624
|
||||
#define MC_SAX_PTSA_RATE 0x4b8
|
||||
#define MC_PCX_PTSA_MIN 0x4b0
|
||||
#define MC_APB_PTSA_MIN 0x4ec
|
||||
#define MC_GK2_PTSA_MIN 0x614
|
||||
#define MC_PCX_PTSA_RATE 0x4ac
|
||||
#define MC_RING1_PTSA_MAX 0x484
|
||||
#define MC_HDAPC_PTSA_RATE 0x628
|
||||
#define MC_MLL_MPCORER_PTSA_MIN 0x450
|
||||
#define MC_GK2_PTSA_MAX 0x618
|
||||
#define MC_AUD_PTSA_MAX 0x550
|
||||
#define MC_GK2_PTSA_RATE 0x610
|
||||
#define MC_ISP_PTSA_MAX 0x4a8
|
||||
#define MC_DISB_PTSA_RATE 0x428
|
||||
#define MC_VE2_PTSA_MAX 0x49c
|
||||
#define MC_DFD_PTSA_MIN 0x638
|
||||
#define MC_FTOP_PTSA_RATE 0x50c
|
||||
#define MC_A9AVPPC_PTSA_RATE 0x488
|
||||
#define MC_VE2_PTSA_MIN 0x498
|
||||
#define MC_USBX_PTSA_MAX 0x52c
|
||||
#define MC_DIS_PTSA_RATE 0x41c
|
||||
#define MC_USBD_PTSA_MAX 0x538
|
||||
#define MC_A9AVPPC_PTSA_MAX 0x490
|
||||
#define MC_USBX_PTSA_RATE 0x524
|
||||
#define MC_FTOP_PTSA_MAX 0x514
|
||||
#define MC_HDAPC_PTSA_MAX 0x630
|
||||
#define MC_SD_PTSA_RATE 0x4d0
|
||||
#define MC_DFD_PTSA_RATE 0x634
|
||||
#define MC_FTOP_PTSA_MIN 0x510
|
||||
#define MC_SDM_PTSA_RATE 0x61c
|
||||
#define MC_AHB_PTSA_RATE 0x4dc
|
||||
#define MC_SMMU_SMMU_PTSA_MAX 0x460
|
||||
#define MC_RING2_PTSA_MIN 0x444
|
||||
#define MC_SDM_PTSA_MIN 0x620
|
||||
#define MC_APB_PTSA_RATE 0x4e8
|
||||
#define MC_MSE_PTSA_MIN 0x4c8
|
||||
#define MC_HOST_PTSA_RATE 0x518
|
||||
#define MC_VE_PTSA_RATE 0x434
|
||||
#define MC_AHB_PTSA_MAX 0x4e4
|
||||
#define MC_SAX_PTSA_MIN 0x4bc
|
||||
#define MC_SMMU_SMMU_PTSA_MIN 0x45c
|
||||
#define MC_ISP_PTSA_MIN 0x4a4
|
||||
#define MC_HOST_PTSA_MAX 0x520
|
||||
#define MC_SAX_PTSA_MAX 0x4c0
|
||||
#define MC_VE_PTSA_MIN 0x438
|
||||
#define MC_GK_PTSA_MIN 0x540
|
||||
#define MC_MSE_PTSA_MAX 0x4cc
|
||||
#define MC_DISB_PTSA_MAX 0x430
|
||||
#define MC_DISB_PTSA_MIN 0x42c
|
||||
#define MC_SMMU_SMMU_PTSA_RATE 0x458
|
||||
#define MC_VE2_PTSA_RATE 0x494
|
||||
#define MC_GK_PTSA_RATE 0x53c
|
||||
#define MC_PTSA_GRANT_DECREMENT 0x960
|
||||
#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
|
||||
#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0
|
||||
#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
|
||||
#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
|
||||
#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8
|
||||
#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
|
||||
#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8
|
||||
#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
|
||||
#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc
|
||||
#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
|
||||
#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694
|
||||
#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
|
||||
#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
|
||||
#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
|
||||
#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0
|
||||
#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698
|
||||
#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec
|
||||
#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0
|
||||
#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4
|
||||
#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
|
||||
#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4
|
||||
#define MC_LATENCY_ALLOWANCE_HC_1 0x314
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
|
||||
#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4
|
||||
#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c
|
||||
#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec
|
||||
#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
|
||||
#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4
|
||||
#define MC_LATENCY_ALLOWANCE_SATA_0 0x350
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690
|
||||
#define MC_LATENCY_ALLOWANCE_HC_0 0x310
|
||||
#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8
|
||||
#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388
|
||||
#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
|
||||
#define MC_LATENCY_ALLOWANCE_HDA_0 0x318
|
||||
#define MC_MIN_LENGTH_APE_0 0xb34
|
||||
#define MC_MIN_LENGTH_DCB_2 0x8a8
|
||||
#define MC_MIN_LENGTH_A9AVP_0 0x950
|
||||
#define MC_MIN_LENGTH_TSEC_0 0x93c
|
||||
#define MC_MIN_LENGTH_DC_1 0x898
|
||||
#define MC_MIN_LENGTH_AXIAP_0 0x94c
|
||||
#define MC_MIN_LENGTH_ISP2B_0 0x930
|
||||
#define MC_MIN_LENGTH_VI2_0 0x944
|
||||
#define MC_MIN_LENGTH_DCB_0 0x8a0
|
||||
#define MC_MIN_LENGTH_DCB_1 0x8a4
|
||||
#define MC_MIN_LENGTH_PPCS_1 0x8f4
|
||||
#define MC_MIN_LENGTH_NVJPG_0 0xb3c
|
||||
#define MC_MIN_LENGTH_HDA_0 0x8c4
|
||||
#define MC_MIN_LENGTH_NVENC_0 0x8d4
|
||||
#define MC_MIN_LENGTH_SDMMC_0 0xb18
|
||||
#define MC_MIN_LENGTH_ISP2B_1 0x934
|
||||
#define MC_MIN_LENGTH_HC_1 0x8c0
|
||||
#define MC_MIN_LENGTH_DC_3 0xb20
|
||||
#define MC_MIN_LENGTH_AVPC_0 0x890
|
||||
#define MC_MIN_LENGTH_VIC_0 0x940
|
||||
#define MC_MIN_LENGTH_ISP2_0 0x91c
|
||||
#define MC_MIN_LENGTH_HC_0 0x8bc
|
||||
#define MC_MIN_LENGTH_SE_0 0xb38
|
||||
#define MC_MIN_LENGTH_NVDEC_0 0xb30
|
||||
#define MC_MIN_LENGTH_SATA_0 0x8fc
|
||||
#define MC_MIN_LENGTH_DC_0 0x894
|
||||
#define MC_MIN_LENGTH_XUSB_1 0x92c
|
||||
#define MC_MIN_LENGTH_DC_2 0x89c
|
||||
#define MC_MIN_LENGTH_SDMMCAA_0 0xb14
|
||||
#define MC_MIN_LENGTH_GPU_0 0xb04
|
||||
#define MC_MIN_LENGTH_ETR_0 0xb44
|
||||
#define MC_MIN_LENGTH_AFI_0 0x88c
|
||||
#define MC_MIN_LENGTH_PPCS_0 0x8f0
|
||||
#define MC_MIN_LENGTH_ISP2_1 0x920
|
||||
#define MC_MIN_LENGTH_XUSB_0 0x928
|
||||
#define MC_MIN_LENGTH_MPCORE_0 0x8cc
|
||||
#define MC_MIN_LENGTH_TSECB_0 0xb48
|
||||
#define MC_MIN_LENGTH_SDMMCA_0 0xb10
|
||||
#define MC_MIN_LENGTH_GPU2_0 0xb40
|
||||
#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c
|
||||
#define MC_MIN_LENGTH_PTC_0 0x8f8
|
||||
#define MC_EMEM_ARB_OVERRIDE_1 0x968
|
||||
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984
|
||||
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988
|
||||
#define MC_EMEM_ARB_STATS_0 0x990
|
||||
#define MC_EMEM_ARB_STATS_1 0x994
|
||||
#define MC_MTS_CARVEOUT_BOM 0x9a0
|
||||
#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4
|
||||
#define MC_MTS_CARVEOUT_ADR_HI 0x9a8
|
||||
#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac
|
||||
#define MC_ERR_MTS_STATUS 0x9b0
|
||||
#define MC_ERR_MTS_ADR 0x9b4
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74
|
||||
#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10
|
||||
#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c
|
||||
#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4
|
||||
#define MC_SECURITY_CARVEOUT2_CFG0 0xc58
|
||||
#define MC_SECURITY_CARVEOUT1_CFG0 0xc08
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68
|
||||
#define MC_SECURITY_CARVEOUT3_BOM 0xcac
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60
|
||||
#define MC_SECURITY_CARVEOUT3_CFG0 0xca8
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88
|
||||
#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64
|
||||
#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50
|
||||
#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14
|
||||
#define MC_SECURITY_CARVEOUT1_BOM 0xc0c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c
|
||||
#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8
|
||||
#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60
|
||||
#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80
|
||||
#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc
|
||||
#define MC_SECURITY_CARVEOUT4_BOM 0xcfc
|
||||
#define MC_SECURITY_CARVEOUT5_CFG0 0xd48
|
||||
#define MC_SECURITY_CARVEOUT2_BOM 0xc5c
|
||||
#define MC_SECURITY_CARVEOUT5_BOM 0xd4c
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0
|
||||
#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
|
||||
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
|
||||
#define MC_DA_CONFIG0 0x9dc
|
||||
@@ -37,6 +37,9 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
FunctionId_Panic = 0xC3000006,
|
||||
FunctionId_ConfigureCarveout = 0xC3000007,
|
||||
FunctionId_ReadWriteRegister = 0xC3000008,
|
||||
|
||||
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
|
||||
FunctionId_SetConfig = 0xC3000409,
|
||||
};
|
||||
|
||||
void CallPrivilegedSecureMonitorFunction(SecureMonitorArguments &args) {
|
||||
@@ -140,35 +143,6 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
args.x[7] = x7;
|
||||
}
|
||||
|
||||
void CallUserSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
|
||||
/* Load arguments into registers. */
|
||||
register u64 x0 asm("x0") = args.x[0];
|
||||
register u64 x1 asm("x1") = args.x[1];
|
||||
register u64 x2 asm("x2") = args.x[2];
|
||||
register u64 x3 asm("x3") = args.x[3];
|
||||
register u64 x4 asm("x4") = args.x[4];
|
||||
register u64 x5 asm("x5") = args.x[5];
|
||||
register u64 x6 asm("x6") = args.x[6];
|
||||
register u64 x7 asm("x7") = args.x[7];
|
||||
|
||||
/* Actually make the call. */
|
||||
__asm__ __volatile__("smc #0"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
|
||||
/* Store arguments to output. */
|
||||
args.x[0] = x0;
|
||||
args.x[1] = x1;
|
||||
args.x[2] = x2;
|
||||
args.x[3] = x3;
|
||||
args.x[4] = x4;
|
||||
args.x[5] = x5;
|
||||
args.x[6] = x6;
|
||||
args.x[7] = x7;
|
||||
}
|
||||
|
||||
/* Global lock for generate random bytes. */
|
||||
KSpinLock g_generate_random_lock;
|
||||
|
||||
@@ -210,21 +184,30 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
||||
}
|
||||
|
||||
bool SetConfig(ConfigItem config_item, u64 value) {
|
||||
SecureMonitorArguments args = { UserFunctionId_SetConfig, static_cast<u32>(config_item), 0, value };
|
||||
CallUserSecureMonitorFunctionForInit(args);
|
||||
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||
bool TryGetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||
SecureMonitorArguments args = { FunctionId_GetConfig, static_cast<u32>(config_item) };
|
||||
CallPrivilegedSecureMonitorFunction(args);
|
||||
MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success));
|
||||
if (static_cast<SmcResult>(args.x[0]) != SmcResult::Success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_qwords && i < 7; i++) {
|
||||
out[i] = args.x[1 + i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||
MESOSPHERE_ABORT_UNLESS(TryGetConfig(out, num_qwords, config_item));
|
||||
}
|
||||
|
||||
bool SetConfig(ConfigItem config_item, u64 value) {
|
||||
SecureMonitorArguments args = { FunctionId_SetConfig, static_cast<u32>(config_item), 0, value };
|
||||
CallPrivilegedSecureMonitorFunction(args);
|
||||
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
||||
}
|
||||
|
||||
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value) {
|
||||
|
||||
@@ -60,6 +60,10 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
};
|
||||
|
||||
enum class SmcResult {
|
||||
@@ -89,12 +93,14 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
UserRebootType_ToPayload = 2,
|
||||
};
|
||||
|
||||
/* TODO: Rest of Secure Monitor API. */
|
||||
void GenerateRandomBytes(void *dst, size_t size);
|
||||
bool TryGetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
||||
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
||||
void ConfigureCarveout(size_t which, uintptr_t address, size_t size);
|
||||
|
||||
bool SetConfig(ConfigItem config_item, u64 value);
|
||||
|
||||
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
|
||||
|
||||
void NORETURN Panic(u32 color);
|
||||
@@ -108,8 +114,6 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
void GenerateRandomBytes(void *dst, size_t size);
|
||||
bool ReadWriteRegister(u32 *out, u64 address, u32 mask, u32 value);
|
||||
|
||||
bool SetConfig(ConfigItem config_item, u64 value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,386 +17,9 @@
|
||||
#include "kern_debug_log_impl.hpp"
|
||||
|
||||
namespace ams::kern {
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-Os")
|
||||
|
||||
namespace {
|
||||
|
||||
/* Useful definitions for our VSNPrintf implementation. */
|
||||
enum FormatSpecifierFlag : u32 {
|
||||
FormatSpecifierFlag_None = 0,
|
||||
FormatSpecifierFlag_EmptySign = (1 << 0),
|
||||
FormatSpecifierFlag_ForceSign = (1 << 1),
|
||||
FormatSpecifierFlag_Hash = (1 << 2),
|
||||
FormatSpecifierFlag_LeftJustify = (1 << 3),
|
||||
FormatSpecifierFlag_ZeroPad = (1 << 4),
|
||||
FormatSpecifierFlag_Char = (1 << 5),
|
||||
FormatSpecifierFlag_Short = (1 << 6),
|
||||
FormatSpecifierFlag_Long = (1 << 7),
|
||||
FormatSpecifierFlag_LongLong = (1 << 8),
|
||||
FormatSpecifierFlag_Uppercase = (1 << 9),
|
||||
FormatSpecifierFlag_HasPrecision = (1 << 10),
|
||||
};
|
||||
|
||||
using FormatSpecifierFlagStorage = std::underlying_type<FormatSpecifierFlag>::type;
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsDigit(char c) {
|
||||
return '0' <= c && c <= '9';
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u32 ParseU32(const char *&str) {
|
||||
u32 value = 0;
|
||||
do {
|
||||
value = (value * 10) + static_cast<u32>(*(str++) - '0');
|
||||
} while (IsDigit(*str));
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE size_t Strnlen(const char *str, size_t max) {
|
||||
const char *cur = str;
|
||||
while (*cur && max--) {
|
||||
cur++;
|
||||
}
|
||||
return static_cast<size_t>(cur - str);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void VSNPrintfImpl(char * const dst, const size_t dst_size, const char *format, ::std::va_list vl) {
|
||||
size_t dst_index = 0;
|
||||
|
||||
auto WriteCharacter = [dst, dst_size, &dst_index](char c) ALWAYS_INLINE_LAMBDA {
|
||||
if (dst_index < dst_size) {
|
||||
dst[dst_index++] = c;
|
||||
}
|
||||
};
|
||||
|
||||
/* Loop over every character in the string, looking for format specifiers. */
|
||||
while (*format) {
|
||||
if (const char c = *(format++); c != '%') {
|
||||
WriteCharacter(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have to parse a format specifier. */
|
||||
/* Start by parsing flags. */
|
||||
FormatSpecifierFlagStorage flags = FormatSpecifierFlag_None;
|
||||
auto SetFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { flags |= f; };
|
||||
auto ClearFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { flags &= ~f; };
|
||||
auto HasFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { return (flags & f) != 0; };
|
||||
{
|
||||
bool parsed_flags = false;
|
||||
while (!parsed_flags) {
|
||||
switch (*format) {
|
||||
case ' ': SetFlag(FormatSpecifierFlag_EmptySign); format++; break;
|
||||
case '+': SetFlag(FormatSpecifierFlag_ForceSign); format++; break;
|
||||
case '#': SetFlag(FormatSpecifierFlag_Hash); format++; break;
|
||||
case '-': SetFlag(FormatSpecifierFlag_LeftJustify); format++; break;
|
||||
case '0': SetFlag(FormatSpecifierFlag_ZeroPad); format++; break;
|
||||
default:
|
||||
parsed_flags = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next, parse width. */
|
||||
u32 width = 0;
|
||||
if (IsDigit(*format)) {
|
||||
/* Integer width. */
|
||||
width = ParseU32(format);
|
||||
} else if (*format == '*') {
|
||||
/* Dynamic width. */
|
||||
const int _width = va_arg(vl, int);
|
||||
if (_width >= 0) {
|
||||
width = static_cast<u32>(_width);
|
||||
} else {
|
||||
SetFlag(FormatSpecifierFlag_LeftJustify);
|
||||
width = static_cast<u32>(-_width);
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
/* Next, parse precision if present. */
|
||||
u32 precision = 0;
|
||||
if (*format == '.') {
|
||||
SetFlag(FormatSpecifierFlag_HasPrecision);
|
||||
format++;
|
||||
|
||||
if (IsDigit(*format)) {
|
||||
/* Integer precision. */
|
||||
precision = ParseU32(format);
|
||||
} else if (*format == '*') {
|
||||
/* Dynamic precision. */
|
||||
const int _precision = va_arg(vl, int);
|
||||
if (_precision > 0) {
|
||||
precision = static_cast<u32>(_precision);
|
||||
}
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse length. */
|
||||
constexpr bool SizeIsLong = sizeof(size_t) == sizeof(long);
|
||||
constexpr bool IntMaxIsLong = sizeof(intmax_t) == sizeof(long);
|
||||
constexpr bool PtrDiffIsLong = sizeof(ptrdiff_t) == sizeof(long);
|
||||
switch (*format) {
|
||||
case 'z':
|
||||
SetFlag(SizeIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
|
||||
format++;
|
||||
break;
|
||||
case 'j':
|
||||
SetFlag(IntMaxIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
|
||||
format++;
|
||||
break;
|
||||
case 't':
|
||||
SetFlag(PtrDiffIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
|
||||
format++;
|
||||
break;
|
||||
case 'h':
|
||||
SetFlag(FormatSpecifierFlag_Short);
|
||||
format++;
|
||||
if (*format == 'h') {
|
||||
SetFlag(FormatSpecifierFlag_Char);
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
SetFlag(FormatSpecifierFlag_Long);
|
||||
format++;
|
||||
if (*format == 'l') {
|
||||
SetFlag(FormatSpecifierFlag_LongLong);
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const char specifier = *(format++);
|
||||
switch (specifier) {
|
||||
case 'p':
|
||||
if constexpr (sizeof(uintptr_t) == sizeof(long long)) {
|
||||
SetFlag(FormatSpecifierFlag_LongLong);
|
||||
} else {
|
||||
SetFlag(FormatSpecifierFlag_Long);
|
||||
}
|
||||
SetFlag(FormatSpecifierFlag_Hash);
|
||||
[[fallthrough]];
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 'b':
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
{
|
||||
/* Determine the base to print with. */
|
||||
u32 base;
|
||||
switch (specifier) {
|
||||
case 'b':
|
||||
base = 2;
|
||||
break;
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
case 'X':
|
||||
SetFlag(FormatSpecifierFlag_Uppercase);
|
||||
[[fallthrough]];
|
||||
case 'p':
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
default:
|
||||
base = 10;
|
||||
ClearFlag(FormatSpecifierFlag_Hash);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Precision implies no zero-padding. */
|
||||
if (HasFlag(FormatSpecifierFlag_HasPrecision)) {
|
||||
ClearFlag(FormatSpecifierFlag_ZeroPad);
|
||||
}
|
||||
|
||||
/* Unsigned types don't get signs. */
|
||||
const bool is_unsigned = base != 10 || specifier == 'u';
|
||||
if (is_unsigned) {
|
||||
ClearFlag(FormatSpecifierFlag_EmptySign);
|
||||
ClearFlag(FormatSpecifierFlag_ForceSign);
|
||||
}
|
||||
|
||||
auto PrintInteger = [&](bool negative, uintmax_t value) {
|
||||
constexpr size_t BufferSize = 64; /* Binary digits for 64-bit numbers may use 64 digits. */
|
||||
char buf[BufferSize];
|
||||
size_t len = 0;
|
||||
|
||||
/* No hash flag for zero. */
|
||||
if (value == 0) {
|
||||
ClearFlag(FormatSpecifierFlag_Hash);
|
||||
}
|
||||
|
||||
if (!HasFlag(FormatSpecifierFlag_HasPrecision) || value != 0) {
|
||||
do {
|
||||
const char digit = static_cast<char>(value % base);
|
||||
buf[len++] = (digit < 10) ? ('0' + digit) : ((HasFlag(FormatSpecifierFlag_Uppercase) ? 'A' : 'a') + digit - 10);
|
||||
value /= base;
|
||||
} while (value);
|
||||
}
|
||||
|
||||
/* Determine our prefix length. */
|
||||
size_t prefix_len = 0;
|
||||
const bool has_sign = negative || HasFlag(FormatSpecifierFlag_ForceSign) || HasFlag(FormatSpecifierFlag_EmptySign);
|
||||
if (has_sign) {
|
||||
prefix_len++;
|
||||
}
|
||||
if (HasFlag(FormatSpecifierFlag_Hash)) {
|
||||
prefix_len += (base != 8) ? 2 : 1;
|
||||
}
|
||||
|
||||
/* Determine zero-padding count. */
|
||||
size_t num_zeroes = (len < precision) ? precision - len : 0;
|
||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify) && HasFlag(FormatSpecifierFlag_ZeroPad)) {
|
||||
num_zeroes = (len + prefix_len < width) ? width - len - prefix_len : 0;
|
||||
}
|
||||
|
||||
/* Print out left padding. */
|
||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
||||
for (size_t i = len + prefix_len + num_zeroes; i < static_cast<size_t>(width); i++) {
|
||||
WriteCharacter(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/* Print out sign. */
|
||||
if (negative) {
|
||||
WriteCharacter('-');
|
||||
} else if (HasFlag(FormatSpecifierFlag_ForceSign)) {
|
||||
WriteCharacter('+');
|
||||
} else if (HasFlag(FormatSpecifierFlag_EmptySign)) {
|
||||
WriteCharacter(' ');
|
||||
}
|
||||
|
||||
/* Print out base prefix. */
|
||||
if (HasFlag(FormatSpecifierFlag_Hash)) {
|
||||
WriteCharacter('0');
|
||||
if (base == 2) {
|
||||
WriteCharacter('b');
|
||||
} else if (base == 16) {
|
||||
WriteCharacter('x');
|
||||
}
|
||||
}
|
||||
|
||||
/* Print out zeroes. */
|
||||
for (size_t i = 0; i < num_zeroes; i++) {
|
||||
WriteCharacter('0');
|
||||
}
|
||||
|
||||
/* Print out digits. */
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
WriteCharacter(buf[len - 1 - i]);
|
||||
}
|
||||
|
||||
/* Print out right padding. */
|
||||
if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
||||
for (size_t i = len + prefix_len + num_zeroes; i < static_cast<size_t>(width); i++) {
|
||||
WriteCharacter(' ');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Output the integer. */
|
||||
if (is_unsigned) {
|
||||
uintmax_t n = 0;
|
||||
if (HasFlag(FormatSpecifierFlag_LongLong)) {
|
||||
n = static_cast<unsigned long long>(va_arg(vl, unsigned long long));
|
||||
} else if (HasFlag(FormatSpecifierFlag_Long)) {
|
||||
n = static_cast<unsigned long>(va_arg(vl, unsigned long));
|
||||
} else if (HasFlag(FormatSpecifierFlag_Char)) {
|
||||
n = static_cast<unsigned char>(va_arg(vl, unsigned int));
|
||||
} else if (HasFlag(FormatSpecifierFlag_Short)) {
|
||||
n = static_cast<unsigned short>(va_arg(vl, unsigned int));
|
||||
} else {
|
||||
n = static_cast<unsigned int>(va_arg(vl, unsigned int));
|
||||
}
|
||||
if (specifier == 'p' && n == 0) {
|
||||
WriteCharacter('(');
|
||||
WriteCharacter('n');
|
||||
WriteCharacter('i');
|
||||
WriteCharacter('l');
|
||||
WriteCharacter(')');
|
||||
} else {
|
||||
PrintInteger(false, n);
|
||||
}
|
||||
} else {
|
||||
intmax_t n = 0;
|
||||
if (HasFlag(FormatSpecifierFlag_LongLong)) {
|
||||
n = static_cast<signed long long>(va_arg(vl, signed long long));
|
||||
} else if (HasFlag(FormatSpecifierFlag_Long)) {
|
||||
n = static_cast<signed long>(va_arg(vl, signed long));
|
||||
} else if (HasFlag(FormatSpecifierFlag_Char)) {
|
||||
n = static_cast<signed char>(va_arg(vl, signed int));
|
||||
} else if (HasFlag(FormatSpecifierFlag_Short)) {
|
||||
n = static_cast<signed short>(va_arg(vl, signed int));
|
||||
} else {
|
||||
n = static_cast<signed int>(va_arg(vl, signed int));
|
||||
}
|
||||
const bool negative = n < 0;
|
||||
const uintmax_t u = (negative) ? static_cast<uintmax_t>(-n) : static_cast<uintmax_t>(n);
|
||||
PrintInteger(negative, u);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
{
|
||||
size_t len = 1;
|
||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
||||
while (len++ < width) {
|
||||
WriteCharacter(' ');
|
||||
}
|
||||
}
|
||||
WriteCharacter(static_cast<char>(va_arg(vl, int)));
|
||||
if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
||||
while (len++ < width) {
|
||||
WriteCharacter(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
const char *str = va_arg(vl, char *);
|
||||
if (str == nullptr) {
|
||||
str = "(null)";
|
||||
}
|
||||
|
||||
size_t len = Strnlen(str, precision > 0 ? precision : std::numeric_limits<size_t>::max());
|
||||
if (HasFlag(FormatSpecifierFlag_HasPrecision)) {
|
||||
len = (len < precision) ? len : precision;
|
||||
}
|
||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
||||
while (len++ < width) {
|
||||
WriteCharacter(' ');
|
||||
}
|
||||
}
|
||||
while (*str && (!HasFlag(FormatSpecifierFlag_HasPrecision) || (precision--) != 0)) {
|
||||
WriteCharacter(*(str++));
|
||||
}
|
||||
if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
||||
while (len++ < width) {
|
||||
WriteCharacter(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
default:
|
||||
WriteCharacter(specifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure null termination. */
|
||||
WriteCharacter('\0');
|
||||
dst[dst_size - 1] = '\0';
|
||||
}
|
||||
|
||||
KSpinLock g_debug_log_lock;
|
||||
bool g_initialized_impl;
|
||||
|
||||
@@ -452,9 +75,6 @@ namespace ams::kern {
|
||||
|
||||
}
|
||||
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
void KDebugLog::Initialize() {
|
||||
if (KTargetSystem::IsDebugLoggingEnabled()) {
|
||||
KScopedInterruptDisable di;
|
||||
@@ -486,7 +106,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
void KDebugLog::VSNPrintf(char *dst, const size_t dst_size, const char *format, ::std::va_list vl) {
|
||||
VSNPrintfImpl(dst, dst_size, format, vl);
|
||||
::ams::util::TVSNPrintf(dst, dst_size, format, vl);
|
||||
}
|
||||
|
||||
Result KDebugLog::PrintUserString(ams::kern::svc::KUserPointer<const char *> user_str, size_t len) {
|
||||
|
||||
@@ -73,15 +73,16 @@ namespace ams::kern {
|
||||
s32 num_waiters = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
|
||||
/* Check the userspace value. */
|
||||
s32 user_value;
|
||||
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
||||
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
@@ -108,26 +109,54 @@ namespace ams::kern {
|
||||
|
||||
/* Determine the updated value. */
|
||||
s32 new_value;
|
||||
if (count <= 0) {
|
||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 1;
|
||||
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {
|
||||
if (count <= 0) {
|
||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 2;
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
auto tmp_it = it;
|
||||
s32 tmp_num_waiters = 0;
|
||||
while ((++tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
|
||||
if ((tmp_num_waiters++) >= count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_num_waiters < count) {
|
||||
new_value = value - 1;
|
||||
} else {
|
||||
new_value = value;
|
||||
}
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto tmp_it = it;
|
||||
int tmp_num_waiters = 0;
|
||||
while ((tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
||||
++tmp_num_waiters;
|
||||
++tmp_it;
|
||||
}
|
||||
|
||||
if (tmp_num_waiters == 0) {
|
||||
new_value = value + 1;
|
||||
} else if (tmp_num_waiters <= count) {
|
||||
new_value = value - 1;
|
||||
if (count <= 0) {
|
||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 1;
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
} else {
|
||||
new_value = value;
|
||||
auto tmp_it = it;
|
||||
s32 tmp_num_waiters = 0;
|
||||
while ((tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
||||
++tmp_num_waiters;
|
||||
++tmp_it;
|
||||
}
|
||||
|
||||
if (tmp_num_waiters == 0) {
|
||||
new_value = value + 1;
|
||||
} else if (tmp_num_waiters <= count) {
|
||||
new_value = value - 1;
|
||||
} else {
|
||||
new_value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,13 +205,8 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Close threads in the list. */
|
||||
if (num_waiters > MaxThreads) {
|
||||
auto it = thread_list.begin();
|
||||
while (it != thread_list.end()) {
|
||||
KThread *thread = std::addressof(*it);
|
||||
thread->Close();
|
||||
it = thread_list.erase(it);
|
||||
}
|
||||
for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) {
|
||||
(*it).Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
KScopedDisableDispatch::~KScopedDisableDispatch() {
|
||||
if (GetCurrentThread().GetDisableDispatchCount() <= 1) {
|
||||
Kernel::GetScheduler().RescheduleCurrentCore();
|
||||
} else {
|
||||
GetCurrentThread().EnableDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# pull in common atmosphere configuration
|
||||
#---------------------------------------------------------------------------------
|
||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
||||
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||
include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# pull in switch rules
|
||||
@@ -15,7 +17,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/stratosphere.hpp
|
||||
PRECOMPILED_HEADERS := $(CURRENT_DIRECTORY)/include/stratosphere.hpp
|
||||
|
||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
||||
@@ -66,7 +68,7 @@ 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 GCH_FILES := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
@@ -103,12 +105,12 @@ dist: dist-src dist-bin
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr release lib *.bz2 include/stratosphere.hpp.gch
|
||||
@rm -fr release lib *.bz2 $(GCH_FILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
|
||||
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES:.gch=.d),$(notdir $(hdr)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <stratosphere/erpt.hpp>
|
||||
#include <stratosphere/err.hpp>
|
||||
#include <stratosphere/fatal.hpp>
|
||||
#include <stratosphere/gpio.hpp>
|
||||
#include <stratosphere/hid.hpp>
|
||||
#include <stratosphere/hos.hpp>
|
||||
#include <stratosphere/kvdb.hpp>
|
||||
@@ -60,7 +61,6 @@
|
||||
#include <stratosphere/pgl.hpp>
|
||||
#include <stratosphere/psc.hpp>
|
||||
#include <stratosphere/pm.hpp>
|
||||
#include <stratosphere/reg.hpp>
|
||||
#include <stratosphere/ro.hpp>
|
||||
#include <stratosphere/settings.hpp>
|
||||
#include <stratosphere/sf.hpp>
|
||||
|
||||
@@ -39,19 +39,21 @@ namespace ams::impl {
|
||||
AMS_DEFINE_SYSTEM_THREAD(21, pm, Main);
|
||||
AMS_DEFINE_SYSTEM_THREAD(21, pm, ProcessTrack);
|
||||
|
||||
|
||||
/* NCM. */
|
||||
AMS_DEFINE_SYSTEM_THREAD(21, ncm, MainWaitThreads);
|
||||
AMS_DEFINE_SYSTEM_THREAD(21, ncm, ContentManagerServerIpcSession);
|
||||
AMS_DEFINE_SYSTEM_THREAD(21, ncm, LocationResolverServerIpcSession);
|
||||
|
||||
/* FS. */
|
||||
AMS_DEFINE_SYSTEM_THREAD(16, fs, WorkerThreadPool);
|
||||
AMS_DEFINE_SYSTEM_THREAD(17, fs, Main);
|
||||
AMS_DEFINE_SYSTEM_THREAD(17, fs, WorkerRealTimeAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(18, fs, WorkerNormalPriorityAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(19, fs, WorkerLowPriorityAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(30, fs, WorkerBackgroundAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(30, fs, PatrolReader);
|
||||
AMS_DEFINE_SYSTEM_THREAD(11, sdmmc, DeviceDetector);
|
||||
AMS_DEFINE_SYSTEM_THREAD(16, fs, WorkerThreadPool);
|
||||
AMS_DEFINE_SYSTEM_THREAD(17, fs, Main);
|
||||
AMS_DEFINE_SYSTEM_THREAD(17, fs, WorkerRealTimeAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(18, fs, WorkerNormalPriorityAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(19, fs, WorkerLowPriorityAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(30, fs, WorkerBackgroundAccess);
|
||||
AMS_DEFINE_SYSTEM_THREAD(30, fs, PatrolReader);
|
||||
|
||||
/* Boot. */
|
||||
AMS_DEFINE_SYSTEM_THREAD(-1, boot, Main);
|
||||
|
||||
@@ -19,16 +19,13 @@
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size);
|
||||
|
||||
u32 ReadRegister(uintptr_t phys_addr);
|
||||
void WriteRegister(uintptr_t phys_addr, u32 value);
|
||||
u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask);
|
||||
u32 ReadRegister(dd::PhysicalAddress phys_addr);
|
||||
void WriteRegister(dd::PhysicalAddress phys_addr, u32 value);
|
||||
u32 ReadWriteRegister(dd::PhysicalAddress phys_addr, u32 value, u32 mask);
|
||||
|
||||
/* Convenience Helper. */
|
||||
|
||||
inline uintptr_t GetIoMapping(uintptr_t phys_addr, size_t size) {
|
||||
const uintptr_t io_mapping = QueryIoMapping(phys_addr, size);
|
||||
inline uintptr_t GetIoMapping(dd::PhysicalAddress phys_addr, size_t size) {
|
||||
const uintptr_t io_mapping = dd::QueryIoMapping(phys_addr, size);
|
||||
AMS_ABORT_UNLESS(io_mapping);
|
||||
return io_mapping;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,6 +13,7 @@
|
||||
* 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
|
||||
|
||||
#define EVP_COP_RESET_VECTOR 0x200
|
||||
#include <stratosphere/ddsf/ddsf_types.hpp>
|
||||
@@ -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::ddsf {
|
||||
|
||||
enum AccessMode {
|
||||
AccessMode_None = (0u << 0),
|
||||
AccessMode_Read = (1u << 0),
|
||||
AccessMode_Write = (1u << 1),
|
||||
|
||||
AccessMode_ReadWrite = AccessMode_Read | AccessMode_Write,
|
||||
};
|
||||
|
||||
}
|
||||
22
libraries/libstratosphere/include/stratosphere/gpio.hpp
Normal file
22
libraries/libstratosphere/include/stratosphere/gpio.hpp
Normal 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 <stratosphere/gpio/gpio_types.hpp>
|
||||
#include <stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp>
|
||||
#include <stratosphere/gpio/sf/gpio_sf_i_manager.hpp>
|
||||
#include <stratosphere/gpio/gpio_api.hpp>
|
||||
#include <stratosphere/gpio/gpio_pad_api.hpp>
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -14,8 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/gpio/gpio_types.hpp>
|
||||
|
||||
#define APBDEV_PMC_DPD_ENABLE 0x024
|
||||
#define APBDEV_PMC_SCRATCH0 0x050
|
||||
#define APBDEV_PMC_SCRATCH4 0x060
|
||||
#define APBDEV_PMC_SCRATCH39 0x138
|
||||
namespace ams::gpio {
|
||||
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 <stratosphere/ddsf/ddsf_types.hpp>
|
||||
#include <stratosphere/gpio/gpio_types.hpp>
|
||||
#include <stratosphere/gpio/gpio_select_pad_name.hpp>
|
||||
|
||||
namespace ams::gpio {
|
||||
|
||||
struct GpioPadSession {
|
||||
void *_session;
|
||||
os::SystemEventType *_event;
|
||||
};
|
||||
|
||||
Result OpenSession(GpioPadSession *out_session, ams::DeviceCode device_code);
|
||||
void CloseSession(GpioPadSession *session);
|
||||
|
||||
Direction GetDirection(GpioPadSession *session);
|
||||
void SetDirection(GpioPadSession *session, Direction direction);
|
||||
|
||||
GpioValue GetValue(GpioPadSession *session);
|
||||
void SetValue(GpioPadSession *session, GpioValue value);
|
||||
|
||||
InterruptMode GetInterruptMode(GpioPadSession *session);
|
||||
void SetInterruptMode(GpioPadSession *session, InterruptMode mode);
|
||||
|
||||
bool GetInterruptEnable(GpioPadSession *session);
|
||||
void SetInterruptEnable(GpioPadSession *session, bool en);
|
||||
|
||||
InterruptStatus GetInterruptStatus(GpioPadSession *session);
|
||||
void ClearInterruptStatus(GpioPadSession *session);
|
||||
|
||||
int GetDebounceTime(GpioPadSession *session);
|
||||
void SetDebounceTime(GpioPadSession *session, int ms);
|
||||
|
||||
bool GetDebounceEnabled(GpioPadSession *session);
|
||||
void SetDebounceEnabled(GpioPadSession *session, bool en);
|
||||
|
||||
Result BindInterrupt(os::SystemEventType *event, GpioPadSession *session);
|
||||
void UnbindInterrupt(GpioPadSession *session);
|
||||
|
||||
Result IsWakeEventActive(bool *out_is_active, ams::DeviceCode device_code);
|
||||
|
||||
}
|
||||
@@ -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 <stratosphere/gpio/gpio_types.hpp>
|
||||
|
||||
namespace ams::gpio {
|
||||
|
||||
enum GpioPadName : u32 {
|
||||
GpioPadName_CodecLdoEnTemp = 1,
|
||||
GpioPadName_ButtonVolUp = 25,
|
||||
GpioPadName_ButtonVolDn = 26,
|
||||
GpioPadName_SdCd = 56,
|
||||
};
|
||||
|
||||
/* TODO: Better place for this? */
|
||||
constexpr inline const DeviceCode DeviceCode_CodecLdoEnTemp = 0x33000002;
|
||||
constexpr inline const DeviceCode DeviceCode_ButtonVolUp = 0x35000002;
|
||||
constexpr inline const DeviceCode DeviceCode_ButtonVolDn = 0x35000003;
|
||||
constexpr inline const DeviceCode DeviceCode_SdCd = 0x3C000002;
|
||||
|
||||
constexpr inline GpioPadName ConvertToGpioPadName(DeviceCode dc) {
|
||||
switch (dc.GetInternalValue()) {
|
||||
case DeviceCode_CodecLdoEnTemp.GetInternalValue(): return GpioPadName_CodecLdoEnTemp;
|
||||
case DeviceCode_ButtonVolUp .GetInternalValue(): return GpioPadName_ButtonVolUp;
|
||||
case DeviceCode_ButtonVolDn .GetInternalValue(): return GpioPadName_ButtonVolDn;
|
||||
case DeviceCode_SdCd .GetInternalValue(): return GpioPadName_SdCd;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline DeviceCode ConvertToDeviceCode(GpioPadName gpn) {
|
||||
switch (gpn) {
|
||||
case GpioPadName_CodecLdoEnTemp: return DeviceCode_CodecLdoEnTemp;
|
||||
case GpioPadName_ButtonVolUp: return DeviceCode_ButtonVolUp;
|
||||
case GpioPadName_ButtonVolDn: return DeviceCode_ButtonVolDn;
|
||||
case GpioPadName_SdCd: return DeviceCode_SdCd;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 <stratosphere/gpio/gpio_types.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||
#include <stratosphere/gpio/gpio_pad_name.board.nintendo_nx.hpp>
|
||||
#else
|
||||
/* Error? */
|
||||
#endif
|
||||
@@ -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::gpio {
|
||||
|
||||
enum InterruptMode : u32 {
|
||||
InterruptMode_LowLevel = 0,
|
||||
InterruptMode_HighLevel = 1,
|
||||
InterruptMode_RisingEdge = 2,
|
||||
InterruptMode_FallingEdge = 3,
|
||||
InterruptMode_AnyEdge = 4,
|
||||
};
|
||||
|
||||
enum Direction : u32 {
|
||||
Direction_Input = 0,
|
||||
Direction_Output = 1,
|
||||
};
|
||||
|
||||
enum GpioValue : u32 {
|
||||
GpioValue_Low = 0,
|
||||
GpioValue_High = 1,
|
||||
};
|
||||
|
||||
enum InterruptStatus : u32 {
|
||||
InterruptStatus_Inactive = 0,
|
||||
InterruptStatus_Active = 1,
|
||||
};
|
||||
|
||||
using WakeBitFlag = util::BitFlagSet<128>;
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
#include <stratosphere/ddsf/ddsf_types.hpp>
|
||||
#include <stratosphere/gpio/gpio_types.hpp>
|
||||
#include <stratosphere/gpio/gpio_select_pad_name.hpp>
|
||||
#include <stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp>
|
||||
|
||||
namespace ams::gpio::sf {
|
||||
|
||||
#define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, s32 pad_descriptor) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTest, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActive, (ams::sf::Out<bool> out, gpio::GpioPadName pad_name), hos::Version_Min, hos::Version_6_2_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 4, Result, GetWakeEventActiveFlagSet, (ams::sf::Out<gpio::WakeBitFlag> out), hos::Version_Min, hos::Version_6_2_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 5, Result, SetWakeEventActiveFlagSetForDebug, (gpio::GpioPadName pad_name, bool is_enabled), hos::Version_Min, hos::Version_6_2_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 6, Result, SetWakePinDebugMode, (s32 mode) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 7, Result, OpenSession2, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, DeviceCode device_code, ddsf::AccessMode access_mode), hos::Version_5_0_0 ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 8, Result, IsWakeEventActive2, (ams::sf::Out<bool> out, DeviceCode device_code), hos::Version_5_0_0 ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 9, Result, SetWakeEventActiveFlagSetForDebug2, (DeviceCode device_code, bool is_enabled), hos::Version_5_0_0 ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, SetRetryValues, (u32 arg0, u32 arg1), hos::Version_6_0_0 )
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(IManager, AMS_GPIO_I_MANAGER_INTERFACE_INFO)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 <stratosphere/gpio/gpio_types.hpp>
|
||||
|
||||
namespace ams::gpio::sf {
|
||||
|
||||
#define AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, SetDirection, (gpio::Direction direction) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 1, Result, GetDirection, (ams::sf::Out<gpio::Direction> out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, SetInterruptMode, (gpio::InterruptMode mode) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, GetInterruptMode, (ams::sf::Out<gpio::InterruptMode> out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 4, Result, SetInterruptEnable, (bool enable) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 5, Result, GetInterruptEnable, (ams::sf::Out<bool> out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out<gpio::InterruptStatus> out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 7, Result, ClearInterruptStatus, () ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 8, Result, SetValue, (gpio::GpioValue value) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 9, Result, GetValue, (ams::sf::Out<gpio::GpioValue> out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, BindInterrupt, (ams::sf::OutCopyHandle out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 11, Result, UnbindInterrupt, () ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 12, Result, SetDebounceEnabled, (bool enable) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 13, Result, GetDebounceEnabled, (ams::sf::Out<bool> out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 14, Result, SetDebounceTime, (s32 ms) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 15, Result, GetDebounceTime, (ams::sf::Out<s32> out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 16, Result, SetValueForSleepState, (gpio::GpioValue value), hos::Version_4_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 16, Result, GetValueForSleepState, (ams::sf::Out<gpio::GpioValue> out), hos::Version_6_0_0)
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(IPadSession, AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO)
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::reg {
|
||||
|
||||
inline void Write(volatile u32 *reg, u32 val) {
|
||||
*reg = val;
|
||||
}
|
||||
|
||||
inline void Write(uintptr_t reg, u32 val) {
|
||||
Write(reinterpret_cast<volatile u32 *>(reg), val);
|
||||
}
|
||||
|
||||
inline u32 Read(volatile u32 *reg) {
|
||||
return *reg;
|
||||
}
|
||||
|
||||
inline u32 Read(uintptr_t reg) {
|
||||
return Read(reinterpret_cast<volatile u32 *>(reg));
|
||||
}
|
||||
|
||||
inline void SetBits(volatile u32 *reg, u32 mask) {
|
||||
*reg = *reg | mask;
|
||||
}
|
||||
|
||||
inline void SetBits(uintptr_t reg, u32 mask) {
|
||||
SetBits(reinterpret_cast<volatile u32 *>(reg), mask);
|
||||
}
|
||||
|
||||
inline void ClearBits(volatile u32 *reg, u32 mask) {
|
||||
*reg = *reg & ~mask;
|
||||
}
|
||||
|
||||
inline void ClearBits(uintptr_t reg, u32 mask) {
|
||||
ClearBits(reinterpret_cast<volatile u32 *>(reg), mask);
|
||||
}
|
||||
|
||||
inline void MaskBits(volatile u32 *reg, u32 mask) {
|
||||
*reg = *reg & mask;
|
||||
}
|
||||
|
||||
inline void MaskBits(uintptr_t reg, u32 mask) {
|
||||
MaskBits(reinterpret_cast<volatile u32 *>(reg), mask);
|
||||
}
|
||||
|
||||
inline void ReadWrite(volatile u32 *reg, u32 val, u32 mask) {
|
||||
*reg = (*reg & (~mask)) | (val & mask);
|
||||
}
|
||||
|
||||
inline void ReadWrite(uintptr_t reg, u32 val, u32 mask) {
|
||||
ReadWrite(reinterpret_cast<volatile u32 *>(reg), val, mask);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ namespace ams::spl::smc {
|
||||
}
|
||||
|
||||
/* Functions. */
|
||||
Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords);
|
||||
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords);
|
||||
Result GetConfig(u64 *out, size_t num_qwords, spl::ConfigItem which);
|
||||
Result GetResult(Result *out, AsyncOperationKey op);
|
||||
Result GetResultData(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op);
|
||||
@@ -59,8 +59,12 @@ namespace ams::spl::smc {
|
||||
Result AtmosphereGetEmummcConfig(void *out_config, void *out_paths, u32 storage_id);
|
||||
|
||||
/* Helpers. */
|
||||
inline Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords) {
|
||||
return SetConfig(which, nullptr, value, num_qwords);
|
||||
}
|
||||
|
||||
inline Result SetConfig(spl::ConfigItem which, const u64 value) {
|
||||
return SetConfig(which, &value, 1);
|
||||
return SetConfig(which, std::addressof(value), 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -222,6 +222,7 @@ namespace ams::spl {
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -235,3 +236,4 @@ constexpr inline SplConfigItem SplConfigItem_ExosphereHasRcmBugPatch = static_ca
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast<SplConfigItem>(65005);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast<SplConfigItem>(65006);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereEmummcType = static_cast<SplConfigItem>(65007);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExospherePayloadAddress = static_cast<SplConfigItem>(65008);
|
||||
|
||||
@@ -74,7 +74,10 @@ namespace ams {
|
||||
ams_ctx.pc = ctx->pc.x;
|
||||
ams_ctx.pstate = ctx->pstate;
|
||||
ams_ctx.afsr0 = ctx->afsr0;
|
||||
ams_ctx.afsr1 = ctx->afsr1;
|
||||
ams_ctx.afsr1 = (static_cast<u64>(::ams::exosphere::GetVersion(ATMOSPHERE_RELEASE_VERSION)) << 32) | static_cast<u64>(hos::GetVersion());
|
||||
if (svc::IsKernelMesosphere()) {
|
||||
ams_ctx.afsr1 |= (static_cast<u64>('M') << (BITSIZEOF(u64) - BITSIZEOF(u8)));
|
||||
}
|
||||
ams_ctx.far = ctx->far.x;
|
||||
ams_ctx.report_identifier = armGetSystemTick();
|
||||
|
||||
|
||||
@@ -167,20 +167,19 @@ namespace ams::boot2 {
|
||||
}
|
||||
}
|
||||
|
||||
bool GetGpioPadLow(GpioPadName pad) {
|
||||
GpioPadSession button;
|
||||
if (R_FAILED(gpioOpenSession(&button, pad))) {
|
||||
bool GetGpioPadLow(DeviceCode device_code) {
|
||||
gpio::GpioPadSession button;
|
||||
if (R_FAILED(gpio::OpenSession(std::addressof(button), device_code))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Ensure we close even on early return. */
|
||||
ON_SCOPE_EXIT { gpioPadClose(&button); };
|
||||
ON_SCOPE_EXIT { gpio::CloseSession(std::addressof(button)); };
|
||||
|
||||
/* Set direction input. */
|
||||
gpioPadSetDirection(&button, GpioDirection_Input);
|
||||
gpio::SetDirection(std::addressof(button), gpio::Direction_Input);
|
||||
|
||||
GpioValue val;
|
||||
return R_SUCCEEDED(gpioPadGetValue(&button, &val)) && val == GpioValue_Low;
|
||||
return gpio::GetValue(std::addressof(button)) == gpio::GpioValue_Low;
|
||||
}
|
||||
|
||||
bool IsForceMaintenance() {
|
||||
@@ -197,7 +196,7 @@ namespace ams::boot2 {
|
||||
|
||||
/* Contact GPIO, read plus/minus buttons. */
|
||||
{
|
||||
return GetGpioPadLow(GpioPadName_ButtonVolUp) && GetGpioPadLow(GpioPadName_ButtonVolDown);
|
||||
return GetGpioPadLow(gpio::DeviceCode_ButtonVolUp) && GetGpioPadLow(gpio::DeviceCode_ButtonVolDn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size) {
|
||||
u64 virtual_addr;
|
||||
const u64 aligned_addr = util::AlignDown(phys_addr, os::MemoryPageSize);
|
||||
const size_t offset = phys_addr - aligned_addr;
|
||||
const u64 aligned_size = size + offset;
|
||||
if (hos::GetVersion() >= hos::Version_10_0_0) {
|
||||
u64 region_size;
|
||||
R_TRY_CATCH(svcQueryIoMapping(&virtual_addr, ®ion_size, aligned_addr, aligned_size)) {
|
||||
/* Official software handles this by returning 0. */
|
||||
R_CATCH(svc::ResultNotFound) { return 0; }
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
AMS_ASSERT(region_size >= aligned_size);
|
||||
} else {
|
||||
R_TRY_CATCH(svcLegacyQueryIoMapping(&virtual_addr, aligned_addr, aligned_size)) {
|
||||
/* Official software handles this by returning 0. */
|
||||
R_CATCH(svc::ResultNotFound) { return 0; }
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
}
|
||||
|
||||
return static_cast<uintptr_t>(virtual_addr + offset);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline u32 ReadWriteRegisterImpl(uintptr_t phys_addr, u32 value, u32 mask) {
|
||||
u32 out_value;
|
||||
R_ABORT_UNLESS(svcReadWriteRegister(&out_value, phys_addr, mask, value));
|
||||
return out_value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u32 ReadRegister(uintptr_t phys_addr) {
|
||||
return ReadWriteRegisterImpl(phys_addr, 0, 0);
|
||||
}
|
||||
|
||||
void WriteRegister(uintptr_t phys_addr, u32 value) {
|
||||
ReadWriteRegisterImpl(phys_addr, value, ~u32());
|
||||
}
|
||||
|
||||
u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask) {
|
||||
return ReadWriteRegisterImpl(phys_addr, value, mask);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace ams::erpt::srv {
|
||||
attachment_id.uuid.ToString(uuid_str, sizeof(uuid_str));
|
||||
|
||||
AttachmentFileName attachment_name;
|
||||
std::snprintf(attachment_name.name, sizeof(attachment_name.name), "%s/%s.att", ReportStoragePath, uuid_str);
|
||||
std::snprintf(attachment_name.name, sizeof(attachment_name.name), "%s:/%s.att", ReportStoragePath, uuid_str);
|
||||
return attachment_name;
|
||||
}
|
||||
|
||||
|
||||
197
libraries/libstratosphere/source/gpio/gpio_client_api.cpp
Normal file
197
libraries/libstratosphere/source/gpio/gpio_client_api.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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 <stratosphere.hpp>
|
||||
#include "gpio_remote_manager_impl.hpp"
|
||||
|
||||
namespace ams::gpio {
|
||||
|
||||
namespace {
|
||||
|
||||
/* TODO: Manager object. */
|
||||
constinit os::SdkMutex g_init_mutex;
|
||||
constinit int g_initialize_count = 0;
|
||||
std::shared_ptr<sf::IManager> g_manager;
|
||||
|
||||
using InternalSession = std::shared_ptr<gpio::sf::IPadSession>;
|
||||
|
||||
InternalSession &GetInterface(GpioPadSession *session) {
|
||||
AMS_ASSERT(session->_session != nullptr);
|
||||
return *static_cast<InternalSession *>(session->_session);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
std::scoped_lock lk(g_init_mutex);
|
||||
|
||||
if ((g_initialize_count++) == 0) {
|
||||
R_ABORT_UNLESS(::gpioInitialize());
|
||||
g_manager = ams::sf::MakeShared<sf::IManager, RemoteManagerImpl>();
|
||||
}
|
||||
}
|
||||
|
||||
void Finalize() {
|
||||
std::scoped_lock lk(g_init_mutex);
|
||||
|
||||
AMS_ASSERT(g_initialize_count > 0);
|
||||
|
||||
if ((--g_initialize_count) == 0) {
|
||||
g_manager.reset();
|
||||
::gpioExit();
|
||||
}
|
||||
}
|
||||
|
||||
Result OpenSession(GpioPadSession *out_session, ams::DeviceCode device_code) {
|
||||
/* Allocate the session. */
|
||||
InternalSession *internal_session = new (std::nothrow) InternalSession;
|
||||
AMS_ABORT_UNLESS(internal_session != nullptr);
|
||||
auto session_guard = SCOPE_GUARD { delete internal_session; };
|
||||
|
||||
/* Get the session. */
|
||||
{
|
||||
ams::sf::cmif::ServiceObjectHolder object_holder;
|
||||
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||
R_TRY(g_manager->OpenSession2(std::addressof(object_holder), device_code, ddsf::AccessMode_ReadWrite));
|
||||
} else {
|
||||
R_TRY(g_manager->OpenSession(std::addressof(object_holder), ConvertToGpioPadName(device_code)));
|
||||
}
|
||||
*internal_session = object_holder.GetServiceObject<sf::IPadSession>();
|
||||
}
|
||||
|
||||
/* Set output. */
|
||||
out_session->_session = internal_session;
|
||||
out_session->_event = nullptr;
|
||||
|
||||
/* We succeeded. */
|
||||
session_guard.Cancel();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void CloseSession(GpioPadSession *session) {
|
||||
AMS_ASSERT(session != nullptr);
|
||||
|
||||
/* Unbind the interrupt, if it's still bound. */
|
||||
if (session->_event != nullptr) {
|
||||
gpio::UnbindInterrupt(session);
|
||||
}
|
||||
|
||||
/* Close the session. */
|
||||
delete std::addressof(GetInterface(session));
|
||||
session->_session = nullptr;
|
||||
}
|
||||
|
||||
Result IsWakeEventActive(bool *out_is_active, ams::DeviceCode device_code) {
|
||||
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||
R_TRY(g_manager->IsWakeEventActive2(out_is_active, device_code));
|
||||
} else {
|
||||
R_TRY(g_manager->IsWakeEventActive(out_is_active, ConvertToGpioPadName(device_code)));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Direction GetDirection(GpioPadSession *session) {
|
||||
Direction out;
|
||||
R_ABORT_UNLESS(GetInterface(session)->GetDirection(std::addressof(out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
void SetDirection(GpioPadSession *session, Direction direction) {
|
||||
R_ABORT_UNLESS(GetInterface(session)->SetDirection(direction));
|
||||
}
|
||||
|
||||
GpioValue GetValue(GpioPadSession *session) {
|
||||
GpioValue out;
|
||||
R_ABORT_UNLESS(GetInterface(session)->GetValue(std::addressof(out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
void SetValue(GpioPadSession *session, GpioValue value) {
|
||||
R_ABORT_UNLESS(GetInterface(session)->SetValue(value));
|
||||
}
|
||||
|
||||
InterruptMode GetInterruptMode(GpioPadSession *session) {
|
||||
InterruptMode out;
|
||||
R_ABORT_UNLESS(GetInterface(session)->GetInterruptMode(std::addressof(out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
void SetInterruptMode(GpioPadSession *session, InterruptMode mode) {
|
||||
R_ABORT_UNLESS(GetInterface(session)->SetInterruptMode(mode));
|
||||
}
|
||||
|
||||
bool GetInterruptEnable(GpioPadSession *session) {
|
||||
bool out;
|
||||
R_ABORT_UNLESS(GetInterface(session)->GetInterruptEnable(std::addressof(out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
void SetInterruptEnable(GpioPadSession *session, bool en) {
|
||||
R_ABORT_UNLESS(GetInterface(session)->SetInterruptEnable(en));
|
||||
}
|
||||
|
||||
InterruptStatus GetInterruptStatus(GpioPadSession *session) {
|
||||
InterruptStatus out;
|
||||
R_ABORT_UNLESS(GetInterface(session)->GetInterruptStatus(std::addressof(out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
void ClearInterruptStatus(GpioPadSession *session) {
|
||||
R_ABORT_UNLESS(GetInterface(session)->ClearInterruptStatus());
|
||||
}
|
||||
|
||||
int GetDebounceTime(GpioPadSession *session) {
|
||||
int out;
|
||||
R_ABORT_UNLESS(GetInterface(session)->GetDebounceTime(std::addressof(out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
void SetDebounceTime(GpioPadSession *session, int ms) {
|
||||
R_ABORT_UNLESS(GetInterface(session)->SetDebounceTime(ms));
|
||||
}
|
||||
|
||||
bool GetDebounceEnabled(GpioPadSession *session) {
|
||||
bool out;
|
||||
R_ABORT_UNLESS(GetInterface(session)->GetDebounceEnabled(std::addressof(out)));
|
||||
return out;
|
||||
}
|
||||
|
||||
void SetDebounceEnabled(GpioPadSession *session, bool en) {
|
||||
R_ABORT_UNLESS(GetInterface(session)->SetDebounceEnabled(en));
|
||||
}
|
||||
|
||||
Result BindInterrupt(os::SystemEventType *event, GpioPadSession *session) {
|
||||
AMS_ASSERT(session->_event == nullptr);
|
||||
|
||||
ams::sf::CopyHandle handle;
|
||||
R_TRY(GetInterface(session)->BindInterrupt(std::addressof(handle)));
|
||||
|
||||
os::AttachReadableHandleToSystemEvent(event, handle.GetValue(), true, os::EventClearMode_ManualClear);
|
||||
|
||||
session->_event = event;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void UnbindInterrupt(GpioPadSession *session) {
|
||||
AMS_ASSERT(session->_event != nullptr);
|
||||
|
||||
R_ABORT_UNLESS(GetInterface(session)->UnbindInterrupt());
|
||||
|
||||
os::DestroySystemEvent(session->_event);
|
||||
session->_event = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 <stratosphere.hpp>
|
||||
#include "gpio_remote_pad_session_impl.hpp"
|
||||
|
||||
namespace ams::gpio {
|
||||
|
||||
class RemoteManagerImpl {
|
||||
public:
|
||||
RemoteManagerImpl() { /* ... */ }
|
||||
|
||||
~RemoteManagerImpl() { /* ... */ }
|
||||
public:
|
||||
/* Actual commands. */
|
||||
Result OpenSessionForDev(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, s32 pad_descriptor) {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result OpenSession(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) {
|
||||
::GpioPadSession p;
|
||||
R_TRY(::gpioOpenSession(std::addressof(p), static_cast<::GpioPadName>(static_cast<u32>(pad_name))));
|
||||
|
||||
out.SetValue(ams::sf::MakeShared<gpio::sf::IPadSession, RemotePadSessionImpl>(p));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result OpenSessionForTest(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result IsWakeEventActive(ams::sf::Out<bool> out, gpio::GpioPadName pad_name) {
|
||||
return ::gpioIsWakeEventActive2(out.GetPointer(), static_cast<::GpioPadName>(static_cast<u32>(pad_name)));
|
||||
}
|
||||
|
||||
Result GetWakeEventActiveFlagSet(ams::sf::Out<gpio::WakeBitFlag> out) {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result SetWakeEventActiveFlagSetForDebug(gpio::GpioPadName pad_name, bool is_enabled) {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result SetWakePinDebugMode(s32 mode) {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result OpenSession2(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, DeviceCode device_code, ddsf::AccessMode access_mode) {
|
||||
::GpioPadSession p;
|
||||
R_TRY(::gpioOpenSession2(std::addressof(p), device_code.GetInternalValue(), access_mode));
|
||||
|
||||
out.SetValue(ams::sf::MakeShared<gpio::sf::IPadSession, RemotePadSessionImpl>(p));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result IsWakeEventActive2(ams::sf::Out<bool> out, DeviceCode device_code) {
|
||||
return ::gpioIsWakeEventActive2(out.GetPointer(), device_code.GetInternalValue());
|
||||
}
|
||||
|
||||
Result SetWakeEventActiveFlagSetForDebug2(DeviceCode device_code, bool is_enabled) {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result SetRetryValues(u32 arg0, u32 arg1) {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
};
|
||||
static_assert(gpio::sf::IsIManager<RemoteManagerImpl>);
|
||||
|
||||
}
|
||||
@@ -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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::gpio {
|
||||
|
||||
class RemotePadSessionImpl {
|
||||
private:
|
||||
::GpioPadSession srv;
|
||||
public:
|
||||
RemotePadSessionImpl(::GpioPadSession &p) : srv(p) { /* ... */ }
|
||||
|
||||
~RemotePadSessionImpl() { ::gpioPadClose(std::addressof(this->srv)); }
|
||||
public:
|
||||
/* Actual commands. */
|
||||
Result SetDirection(gpio::Direction direction) {
|
||||
return ::gpioPadSetDirection(std::addressof(this->srv), static_cast<::GpioDirection>(static_cast<u32>(direction)));
|
||||
}
|
||||
|
||||
Result GetDirection(ams::sf::Out<gpio::Direction> out) {
|
||||
static_assert(sizeof(gpio::Direction) == sizeof(::GpioDirection));
|
||||
return ::gpioPadGetDirection(std::addressof(this->srv), reinterpret_cast<::GpioDirection *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result SetInterruptMode(gpio::InterruptMode mode) {
|
||||
return ::gpioPadSetInterruptMode(std::addressof(this->srv), static_cast<::GpioInterruptMode>(static_cast<u32>(mode)));
|
||||
}
|
||||
|
||||
Result GetInterruptMode(ams::sf::Out<gpio::InterruptMode> out) {
|
||||
static_assert(sizeof(gpio::InterruptMode) == sizeof(::GpioInterruptMode));
|
||||
return ::gpioPadGetInterruptMode(std::addressof(this->srv), reinterpret_cast<::GpioInterruptMode *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result SetInterruptEnable(bool enable) {
|
||||
return ::gpioPadSetInterruptEnable(std::addressof(this->srv), enable);
|
||||
}
|
||||
|
||||
Result GetInterruptEnable(ams::sf::Out<bool> out) {
|
||||
return ::gpioPadGetInterruptEnable(std::addressof(this->srv), out.GetPointer());
|
||||
}
|
||||
|
||||
Result GetInterruptStatus(ams::sf::Out<gpio::InterruptStatus> out) {
|
||||
static_assert(sizeof(gpio::InterruptStatus) == sizeof(::GpioInterruptStatus));
|
||||
return ::gpioPadGetInterruptStatus(std::addressof(this->srv), reinterpret_cast<::GpioInterruptStatus *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result ClearInterruptStatus() {
|
||||
return ::gpioPadClearInterruptStatus(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
Result SetValue(gpio::GpioValue value) {
|
||||
return ::gpioPadSetValue(std::addressof(this->srv), static_cast<::GpioValue>(static_cast<u32>(value)));
|
||||
}
|
||||
|
||||
Result GetValue(ams::sf::Out<gpio::GpioValue> out) {
|
||||
static_assert(sizeof(gpio::GpioValue) == sizeof(::GpioValue));
|
||||
return ::gpioPadGetValue(std::addressof(this->srv), reinterpret_cast<::GpioValue *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result BindInterrupt(ams::sf::OutCopyHandle out) {
|
||||
::Event ev;
|
||||
R_TRY(::gpioPadBindInterrupt(std::addressof(this->srv), std::addressof(ev)));
|
||||
out.SetValue(ev.revent);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result UnbindInterrupt() {
|
||||
return ::gpioPadUnbindInterrupt(std::addressof(this->srv));
|
||||
}
|
||||
|
||||
Result SetDebounceEnabled(bool enable) {
|
||||
return ::gpioPadSetDebounceEnabled(std::addressof(this->srv), enable);
|
||||
}
|
||||
|
||||
Result GetDebounceEnabled(ams::sf::Out<bool> out) {
|
||||
return ::gpioPadGetDebounceEnabled(std::addressof(this->srv), out.GetPointer());
|
||||
}
|
||||
|
||||
Result SetDebounceTime(s32 ms) {
|
||||
return ::gpioPadSetDebounceTime(std::addressof(this->srv), ms);
|
||||
}
|
||||
|
||||
Result GetDebounceTime(ams::sf::Out<s32> out) {
|
||||
return ::gpioPadGetDebounceTime(std::addressof(this->srv), out.GetPointer());
|
||||
}
|
||||
|
||||
Result SetValueForSleepState(gpio::GpioValue value) {
|
||||
/* TODO: libnx bindings. */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result GetValueForSleepState(ams::sf::Out<gpio::GpioValue> out) {
|
||||
/* TODO: libnx bindings. */
|
||||
AMS_ABORT();
|
||||
}
|
||||
};
|
||||
static_assert(gpio::sf::IsIPadSession<RemotePadSessionImpl>);
|
||||
|
||||
}
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
namespace ams::spl::smc {
|
||||
|
||||
Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords) {
|
||||
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::SetConfig);
|
||||
args.X[1] = static_cast<u64>(which);
|
||||
args.X[2] = 0;
|
||||
args.X[2] = reinterpret_cast<u64>(address);
|
||||
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
||||
args.X[3 + i] = value[i];
|
||||
}
|
||||
|
||||
@@ -20,12 +20,22 @@
|
||||
#include <vapours/literals.hpp>
|
||||
|
||||
#include <vapours/allocator.hpp>
|
||||
#include <vapours/device_code.hpp>
|
||||
#include <vapours/timespan.hpp>
|
||||
#include <vapours/span.hpp>
|
||||
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/reg.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||
#include <vapours/tegra.hpp>
|
||||
#endif
|
||||
|
||||
#include <vapours/crypto.hpp>
|
||||
#include <vapours/svc.hpp>
|
||||
|
||||
#include <vapours/ams/ams_fatal_error_context.hpp>
|
||||
|
||||
#include <vapours/dd.hpp>
|
||||
#include <vapours/sdmmc.hpp>
|
||||
@@ -16,8 +16,8 @@
|
||||
#pragma once
|
||||
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 14
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 4
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 15
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0
|
||||
|
||||
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
||||
|
||||
|
||||
24
libraries/libvapours/include/vapours/dd.hpp
Normal file
24
libraries/libvapours/include/vapours/dd.hpp
Normal 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/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
|
||||
#include <vapours/dd/dd_common_types.hpp>
|
||||
#include <vapours/dd/dd_io_mapping.hpp>
|
||||
#include <vapours/dd/dd_cache.hpp>
|
||||
25
libraries/libvapours/include/vapours/dd/dd_cache.hpp
Normal file
25
libraries/libvapours/include/vapours/dd/dd_cache.hpp
Normal 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/dd/dd_common_types.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
void InvalidateDataCache(void *addr, size_t size);
|
||||
void StoreDataCache(void *addr, size_t size);
|
||||
void FlushDataCache(void *addr, size_t size);
|
||||
|
||||
}
|
||||
29
libraries/libvapours/include/vapours/dd/dd_common_types.hpp
Normal file
29
libraries/libvapours/include/vapours/dd/dd_common_types.hpp
Normal 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/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
using PhysicalAddress = u64;
|
||||
using DeviceVirtualAddress = u64;
|
||||
|
||||
static_assert(std::same_as<PhysicalAddress, ams::svc::PhysicalAddress>);
|
||||
|
||||
}
|
||||
26
libraries/libvapours/include/vapours/dd/dd_io_mapping.hpp
Normal file
26
libraries/libvapours/include/vapours/dd/dd_io_mapping.hpp
Normal 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/dd/dd_common_types.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
uintptr_t QueryIoMapping(dd::PhysicalAddress phys_addr, size_t size);
|
||||
|
||||
u32 ReadIoRegister(dd::PhysicalAddress phys_addr);
|
||||
void WriteIoRegister(dd::PhysicalAddress phys_addr, u32 value);
|
||||
|
||||
}
|
||||
49
libraries/libvapours/include/vapours/device_code.hpp
Normal file
49
libraries/libvapours/include/vapours/device_code.hpp
Normal 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/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
|
||||
namespace ams {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using DeviceCodeType = u32;
|
||||
|
||||
}
|
||||
|
||||
/* TODO: Better understand device code components. */
|
||||
class DeviceCode {
|
||||
private:
|
||||
impl::DeviceCodeType inner_value;
|
||||
public:
|
||||
constexpr DeviceCode(impl::DeviceCodeType v) : inner_value(v) { /* ... */ }
|
||||
|
||||
constexpr impl::DeviceCodeType GetInternalValue() const { return this->inner_value; }
|
||||
|
||||
constexpr bool operator==(const DeviceCode &rhs) const {
|
||||
return this->GetInternalValue() == rhs.GetInternalValue();
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const DeviceCode &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr inline const DeviceCode InvalidDeviceCode(0);
|
||||
|
||||
}
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
namespace ams::reg {
|
||||
|
||||
template<typename T>
|
||||
concept UnsignedNonConstIntegral = std::unsigned_integral<T> && !std::is_const<T>::value;
|
||||
|
||||
using BitsValue = std::tuple<u16, u16, u32>;
|
||||
using BitsMask = std::tuple<u16, u16>;
|
||||
|
||||
@@ -48,100 +51,137 @@ namespace ams::reg {
|
||||
return (EncodeValue(values) | ...);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Write(volatile u32 *reg, u32 val) { *reg = val; }
|
||||
ALWAYS_INLINE void Write(volatile u32 ®, u32 val) { reg = val; }
|
||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
constexpr ALWAYS_INLINE u32 EncodeMask(const Masks... masks) {
|
||||
return (EncodeMask(masks) | ...);
|
||||
}
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void Write(volatile IntType *reg, std::type_identity_t<IntType> val) { *reg = val; }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void Write(volatile IntType ®, std::type_identity_t<IntType> 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 IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE void Write(volatile IntType *reg, const Values... values) { return Write(reg, static_cast<IntType>((EncodeValue(values) | ...))); }
|
||||
|
||||
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE void Write(volatile u32 ®, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
|
||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE void Write(volatile IntType ®, const Values... values) { return Write(reg, static_cast<IntType>((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 ®) { return reg; }
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE IntType Read(volatile IntType *reg) { return *reg; }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE IntType Read(volatile IntType ®) { 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 ®, u32 mask) { return reg & mask; }
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE IntType Read(volatile IntType *reg, std::type_identity_t<IntType> mask) { return *reg & mask; }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE IntType Read(volatile IntType ®, std::type_identity_t<IntType> 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 IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE IntType Read(volatile IntType *reg, const Masks... masks) { return Read(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE IntType Read(volatile IntType ®, const Masks... masks) { return Read(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE u32 Read(volatile u32 ®, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
|
||||
ALWAYS_INLINE u32 Read(uintptr_t 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 IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE bool HasValue(volatile IntType *reg, const Values... values) { return Read(reg, static_cast<IntType>((EncodeMask(values) | ...))) == static_cast<IntType>(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(volatile u32 ®, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
|
||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE bool HasValue(volatile IntType ®, const Values... values) { return Read(reg, static_cast<IntType>((EncodeMask(values) | ...))) == static_cast<IntType>(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 u32 GetValue(volatile u32 *reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||
ALWAYS_INLINE u32 GetValue(volatile u32 ®, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||
ALWAYS_INLINE u32 GetValue(uintptr_t reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE IntType GetValue(volatile IntType *reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE IntType GetValue(volatile IntType ®, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||
|
||||
ALWAYS_INLINE u32 GetValue(uintptr_t reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void ReadWrite(volatile IntType *reg, std::type_identity_t<IntType> val, std::type_identity_t<IntType> mask) { *reg = (*reg & (~mask)) | (val & mask); }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void ReadWrite(volatile IntType ®, std::type_identity_t<IntType> val, std::type_identity_t<IntType> 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(volatile u32 ®, 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 IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE void ReadWrite(volatile IntType *reg, const Values... values) { return ReadWrite(reg, static_cast<IntType>((EncodeValue(values) | ...)), static_cast<IntType>((EncodeMask(values) | ...))); }
|
||||
|
||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE void ReadWrite(volatile IntType ®, const Values... values) { return ReadWrite(reg, static_cast<IntType>((EncodeValue(values) | ...)), static_cast<IntType>((EncodeMask(values) | ...))); }
|
||||
|
||||
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||
ALWAYS_INLINE void ReadWrite(volatile u32 ®, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
|
||||
ALWAYS_INLINE void ReadWrite(uintptr_t 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) | ...)); }
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void SetBits(volatile IntType *reg, std::type_identity_t<IntType> mask) { *reg = *reg | mask; }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void SetBits(volatile IntType ®, std::type_identity_t<IntType> mask) { reg = reg | mask; }
|
||||
|
||||
ALWAYS_INLINE void SetBits(volatile u32 *reg, u32 mask) { *reg = *reg | mask; }
|
||||
ALWAYS_INLINE void SetBits(volatile u32 ®, 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 IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void SetBits(volatile IntType *reg, const Masks... masks) { return SetBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void SetBits(volatile IntType ®, const Masks... masks) { return SetBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void SetBits(volatile u32 ®, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
|
||||
ALWAYS_INLINE void SetBits(uintptr_t 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) | ...)); }
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void ClearBits(volatile IntType *reg, std::type_identity_t<IntType> mask) { *reg = *reg & ~mask; }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void ClearBits(volatile IntType ®, std::type_identity_t<IntType> mask) { reg = reg & ~mask; }
|
||||
|
||||
ALWAYS_INLINE void ClearBits(volatile u32 *reg, u32 mask) { *reg = *reg & ~mask; }
|
||||
ALWAYS_INLINE void ClearBits(volatile u32 ®, 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 IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void ClearBits(volatile IntType *reg, const Masks... masks) { return ClearBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void ClearBits(volatile IntType ®, const Masks... masks) { return ClearBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void ClearBits(volatile u32 ®, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
|
||||
ALWAYS_INLINE void ClearBits(uintptr_t 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) | ...)); }
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void MaskBits(volatile IntType *reg, std::type_identity_t<IntType> mask) { *reg = *reg & mask; }
|
||||
|
||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
||||
ALWAYS_INLINE void MaskBits(volatile IntType ®, std::type_identity_t<IntType> mask) { reg = reg & mask; }
|
||||
|
||||
ALWAYS_INLINE void MaskBits(volatile u32 *reg, u32 mask) { *reg = *reg & mask; }
|
||||
ALWAYS_INLINE void MaskBits(volatile u32 ®, 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 IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void MaskBits(volatile IntType *reg, const Masks... masks) { return MaskBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void MaskBits(volatile IntType ®, const Masks... masks) { return MaskBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
||||
|
||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||
ALWAYS_INLINE void MaskBits(volatile u32 ®, 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) | ...)); }
|
||||
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}
|
||||
@@ -41,10 +41,12 @@
|
||||
#include <vapours/results/nim_results.hpp>
|
||||
#include <vapours/results/ns_results.hpp>
|
||||
#include <vapours/results/os_results.hpp>
|
||||
#include <vapours/results/pcv_results.hpp>
|
||||
#include <vapours/results/pgl_results.hpp>
|
||||
#include <vapours/results/pm_results.hpp>
|
||||
#include <vapours/results/psc_results.hpp>
|
||||
#include <vapours/results/ro_results.hpp>
|
||||
#include <vapours/results/sdmmc_results.hpp>
|
||||
#include <vapours/results/settings_results.hpp>
|
||||
#include <vapours/results/sf_results.hpp>
|
||||
#include <vapours/results/sm_results.hpp>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,9 +13,14 @@
|
||||
* 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
|
||||
|
||||
#define FLOW_CTLR_HALT_COP_EVENTS 0x004
|
||||
#define FLOW_CTLR_CC4_HVC_CONTROL 0x060
|
||||
#define FLOW_CTLR_CC4_RETENTION_CONTROL 0x064
|
||||
#define FLOW_CTLR_CC4_HVC_RETRY 0x08C
|
||||
#pragma once
|
||||
#include <vapours/results/results_common.hpp>
|
||||
|
||||
namespace ams::pcv {
|
||||
|
||||
R_DEFINE_NAMESPACE_RESULT_MODULE(133);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(IllegalRequest, 16);
|
||||
|
||||
}
|
||||
105
libraries/libvapours/include/vapours/results/sdmmc_results.hpp
Normal file
105
libraries/libvapours/include/vapours/results/sdmmc_results.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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/results/results_common.hpp>
|
||||
|
||||
namespace ams::sdmmc {
|
||||
|
||||
R_DEFINE_NAMESPACE_RESULT_MODULE(24);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(NoDevice, 1);
|
||||
R_DEFINE_ERROR_RESULT(NotActivated, 2);
|
||||
R_DEFINE_ERROR_RESULT(DeviceRemoved, 3);
|
||||
R_DEFINE_ERROR_RESULT(NotAwakened, 4);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(CommunicationError, 32, 126);
|
||||
R_DEFINE_ERROR_RANGE(CommunicationNotAttained, 33, 46);
|
||||
R_DEFINE_ERROR_RESULT(ResponseIndexError, 34);
|
||||
R_DEFINE_ERROR_RESULT(ResponseEndBitError, 35);
|
||||
R_DEFINE_ERROR_RESULT(ResponseCrcError, 36);
|
||||
R_DEFINE_ERROR_RESULT(ResponseTimeoutError, 37);
|
||||
R_DEFINE_ERROR_RESULT(DataEndBitError, 38);
|
||||
R_DEFINE_ERROR_RESULT(DataCrcError, 39);
|
||||
R_DEFINE_ERROR_RESULT(DataTimeoutError, 40);
|
||||
R_DEFINE_ERROR_RESULT(AutoCommandResponseIndexError, 41);
|
||||
R_DEFINE_ERROR_RESULT(AutoCommandResponseEndBitError, 42);
|
||||
R_DEFINE_ERROR_RESULT(AutoCommandResponseCrcError, 43);
|
||||
R_DEFINE_ERROR_RESULT(AutoCommandResponseTimeoutError, 44);
|
||||
R_DEFINE_ERROR_RESULT(CommandCompleteSoftwareTimeout, 45);
|
||||
R_DEFINE_ERROR_RESULT(TransferCompleteSoftwareTimeout, 46);
|
||||
R_DEFINE_ERROR_RANGE(DeviceStatusHasError, 48, 70);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusAddressOutOfRange, 49);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusAddressMisaligned, 50);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusBlockLenError, 51);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusEraseSeqError, 52);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusEraseParam, 53);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusWpViolation, 54);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusLockUnlockFailed, 55);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusComCrcError, 56);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusIllegalCommand, 57);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusDeviceEccFailed, 58);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusCcError, 59);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusError, 60);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusCidCsdOverwrite, 61);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusWpEraseSkip, 62);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusEraseReset, 63);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusSwitchError, 64);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedDeviceState, 72);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedDeviceCsdValue, 73);
|
||||
R_DEFINE_ERROR_RESULT(AbortTransactionSoftwareTimeout, 74);
|
||||
R_DEFINE_ERROR_RESULT(CommandInhibitCmdSoftwareTimeout, 75);
|
||||
R_DEFINE_ERROR_RESULT(CommandInhibitDatSoftwareTimeout, 76);
|
||||
R_DEFINE_ERROR_RESULT(BusySoftwareTimeout, 77);
|
||||
R_DEFINE_ERROR_RESULT(IssueTuningCommandSoftwareTimeout, 78);
|
||||
R_DEFINE_ERROR_RESULT(TuningFailed, 79);
|
||||
R_DEFINE_ERROR_RESULT(MmcInitializationSoftwareTimeout, 80);
|
||||
R_DEFINE_ERROR_RESULT(MmcNotSupportExtendedCsd, 81);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedMmcExtendedCsdValue, 82);
|
||||
R_DEFINE_ERROR_RESULT(MmcEraseSoftwareTimeout, 83);
|
||||
R_DEFINE_ERROR_RESULT(SdCardValidationError, 84);
|
||||
R_DEFINE_ERROR_RESULT(SdCardInitializationSoftwareTimeout, 85);
|
||||
R_DEFINE_ERROR_RESULT(SdCardGetValidRcaSoftwareTimeout, 86);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedSdCardAcmdDisabled, 87);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotSupportSwitchFunctionStatus, 88);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedSdCardSwitchFunctionStatus, 89);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotSupportAccessMode, 90);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNot4BitBusWidthAtUhsIMode, 91);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotSupportSdr104AndSdr50, 92);
|
||||
R_DEFINE_ERROR_RESULT(SdCardCannotSwitchAccessMode, 93);
|
||||
R_DEFINE_ERROR_RESULT(SdCardFailedSwitchAccessMode, 94);
|
||||
R_DEFINE_ERROR_RESULT(SdCardUnacceptableCurrentConsumption, 95);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotReadyToVoltageSwitch, 96);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotCompleteVoltageSwitch, 97);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(HostControllerUnexpected, 128, 158);
|
||||
R_DEFINE_ERROR_RESULT(InternalClockStableSoftwareTimeout, 129);
|
||||
R_DEFINE_ERROR_RESULT(SdHostStandardUnknownAutoCmdError, 130);
|
||||
R_DEFINE_ERROR_RESULT(SdHostStandardUnknownError, 131);
|
||||
R_DEFINE_ERROR_RESULT(SdmmcDllCalibrationSoftwareTimeout, 132);
|
||||
R_DEFINE_ERROR_RESULT(SdmmcDllApplicationSoftwareTimeout, 133);
|
||||
R_DEFINE_ERROR_RESULT(SdHostStandardFailSwitchTo1_8V, 134);
|
||||
R_DEFINE_ERROR_RESULT(DriveStrengthCalibrationNotCompleted, 135);
|
||||
R_DEFINE_ERROR_RESULT(DriveStrengthCalibrationSoftwareTimeout, 136);
|
||||
R_DEFINE_ERROR_RESULT(SdmmcCompShortToGnd, 137);
|
||||
R_DEFINE_ERROR_RESULT(SdmmcCompOpen, 138);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(InternalError, 160, 190);
|
||||
R_DEFINE_ERROR_RESULT(NoWaitedInterrupt, 161);
|
||||
R_DEFINE_ERROR_RESULT(WaitInterruptSoftwareTimeout, 162);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(NotImplemented, 201);
|
||||
}
|
||||
28
libraries/libvapours/include/vapours/sdmmc.hpp
Normal file
28
libraries/libvapours/include/vapours/sdmmc.hpp
Normal 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/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/svc.hpp>
|
||||
|
||||
#include <vapours/sdmmc/sdmmc_build_config.hpp>
|
||||
#include <vapours/sdmmc/sdmmc_common.hpp>
|
||||
#include <vapours/sdmmc/sdmmc_mmc.hpp>
|
||||
#include <vapours/sdmmc/sdmmc_sd_card.hpp>
|
||||
#include <vapours/sdmmc/sdmmc_gc_asic.hpp>
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/svc.hpp>
|
||||
#include <vapours/dd.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
|
||||
//#define AMS_SDMMC_THREAD_SAFE
|
||||
//#define AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS
|
||||
//#define AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL
|
||||
//#define AMS_SDMMC_USE_DEVICE_DETECTOR
|
||||
//#define AMS_SDMMC_USE_LOGGER
|
||||
//#define AMS_SDMMC_USE_OS_EVENTS
|
||||
//#define AMS_SDMMC_USE_OS_TIMER
|
||||
#define AMS_SDMMC_USE_UTIL_TIMER
|
||||
//#define AMS_SDMMC_ENABLE_MMC_HS400
|
||||
//#define AMS_SDMMC_ENABLE_SD_UHS_I
|
||||
//#define AMS_SDMMC_SET_PLLC4_BASE
|
||||
//#define AMS_SDMMC_USE_SD_CARD_DETECTOR
|
||||
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
|
||||
//#define AMS_SDMMC_THREAD_SAFE
|
||||
//#define AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS
|
||||
//#define AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL
|
||||
//#define AMS_SDMMC_USE_DEVICE_DETECTOR
|
||||
//#define AMS_SDMMC_USE_LOGGER
|
||||
//#define AMS_SDMMC_USE_OS_EVENTS
|
||||
//#define AMS_SDMMC_USE_OS_TIMER
|
||||
#define AMS_SDMMC_USE_UTIL_TIMER
|
||||
//#define AMS_SDMMC_ENABLE_MMC_HS400
|
||||
//#define AMS_SDMMC_ENABLE_SD_UHS_I
|
||||
//#define AMS_SDMMC_SET_PLLC4_BASE
|
||||
//#define AMS_SDMMC_USE_SD_CARD_DETECTOR
|
||||
|
||||
#elif defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
|
||||
#define AMS_SDMMC_THREAD_SAFE
|
||||
#define AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS
|
||||
#define AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL
|
||||
#define AMS_SDMMC_USE_DEVICE_DETECTOR
|
||||
#define AMS_SDMMC_USE_LOGGER
|
||||
#define AMS_SDMMC_USE_OS_EVENTS
|
||||
#define AMS_SDMMC_USE_OS_TIMER
|
||||
//#define AMS_SDMMC_USE_UTIL_TIMER
|
||||
#define AMS_SDMMC_ENABLE_MMC_HS400
|
||||
#define AMS_SDMMC_ENABLE_SD_UHS_I
|
||||
#define AMS_SDMMC_SET_PLLC4_BASE
|
||||
#define AMS_SDMMC_USE_SD_CARD_DETECTOR
|
||||
|
||||
#else
|
||||
#error "Unknown execution context for ams::sdmmc!"
|
||||
#endif
|
||||
114
libraries/libvapours/include/vapours/sdmmc/sdmmc_common.hpp
Normal file
114
libraries/libvapours/include/vapours/sdmmc/sdmmc_common.hpp
Normal 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/sdmmc/sdmmc_build_config.hpp>
|
||||
|
||||
namespace ams::sdmmc {
|
||||
|
||||
enum BusPower {
|
||||
BusPower_Off = 0,
|
||||
BusPower_1_8V = 1,
|
||||
BusPower_3_3V = 2,
|
||||
};
|
||||
|
||||
enum BusWidth {
|
||||
BusWidth_1Bit = 0,
|
||||
BusWidth_4Bit = 1,
|
||||
BusWidth_8Bit = 2,
|
||||
};
|
||||
|
||||
enum SpeedMode {
|
||||
SpeedMode_MmcIdentification = 0,
|
||||
SpeedMode_MmcLegacySpeed = 1,
|
||||
SpeedMode_MmcHighSpeed = 2,
|
||||
SpeedMode_MmcHs200 = 3,
|
||||
SpeedMode_MmcHs400 = 4,
|
||||
SpeedMode_SdCardIdentification = 5,
|
||||
SpeedMode_SdCardDefaultSpeed = 6,
|
||||
SpeedMode_SdCardHighSpeed = 7,
|
||||
SpeedMode_SdCardSdr12 = 8,
|
||||
SpeedMode_SdCardSdr25 = 9,
|
||||
SpeedMode_SdCardSdr50 = 10,
|
||||
SpeedMode_SdCardSdr104 = 11,
|
||||
SpeedMode_SdCardDdr50 = 12,
|
||||
SpeedMode_GcAsicFpgaSpeed = 13,
|
||||
SpeedMode_GcAsicSpeed = 14,
|
||||
};
|
||||
|
||||
enum Port {
|
||||
Port_Mmc0 = 0,
|
||||
Port_SdCard0 = 1,
|
||||
Port_GcAsic0 = 2,
|
||||
};
|
||||
|
||||
struct ErrorInfo {
|
||||
u32 num_activation_failures;
|
||||
u32 num_activation_error_corrections;
|
||||
u32 num_read_write_failures;
|
||||
u32 num_read_write_error_corrections;
|
||||
};
|
||||
|
||||
struct DataTransfer {
|
||||
void *buffer;
|
||||
size_t buffer_size;
|
||||
size_t block_size;
|
||||
u32 num_blocks;
|
||||
bool is_read;
|
||||
};
|
||||
|
||||
using DeviceDetectionEventCallback = void (*)(void *);
|
||||
|
||||
constexpr inline size_t SectorSize = 0x200;
|
||||
|
||||
constexpr inline size_t DeviceCidSize = 0x10;
|
||||
constexpr inline size_t DeviceCsdSize = 0x10;
|
||||
|
||||
constexpr inline size_t BufferDeviceVirtualAddressAlignment = alignof(ams::dd::DeviceVirtualAddress);
|
||||
static_assert(BufferDeviceVirtualAddressAlignment >= 8);
|
||||
|
||||
void Initialize(Port port);
|
||||
void Finalize(Port port);
|
||||
|
||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||
void SwitchToPcvClockResetControl();
|
||||
#endif
|
||||
|
||||
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
||||
void RegisterDeviceVirtualAddress(Port port, uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address);
|
||||
void UnregisterDeviceVirtualAddress(Port port, uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address);
|
||||
#endif
|
||||
|
||||
void ChangeCheckTransferInterval(Port port, u32 ms);
|
||||
void SetDefaultCheckTransferInterval(Port port);
|
||||
|
||||
Result Activate(Port port);
|
||||
void Deactivate(Port port);
|
||||
|
||||
Result Read(void *dst, size_t dst_size, Port port, u32 sector_index, u32 num_sectors);
|
||||
Result Write(Port port, u32 sector_index, u32 num_sectors, const void *src, size_t src_size);
|
||||
|
||||
Result CheckConnection(SpeedMode *out_speed_mode, BusWidth *out_bus_width, Port port);
|
||||
|
||||
Result GetDeviceSpeedMode(SpeedMode *out, Port port);
|
||||
Result GetDeviceMemoryCapacity(u32 *out_num_sectors, Port port);
|
||||
Result GetDeviceStatus(u32 *out_device_status, Port port);
|
||||
Result GetDeviceCid(void *out, size_t out_size, Port port);
|
||||
Result GetDeviceCsd(void *out, size_t out_size, Port port);
|
||||
|
||||
void GetAndClearErrorInfo(ErrorInfo *out_error_info, size_t *out_log_size, char *out_log_buffer, size_t log_buffer_size, Port port);
|
||||
|
||||
}
|
||||
34
libraries/libvapours/include/vapours/sdmmc/sdmmc_gc_asic.hpp
Normal file
34
libraries/libvapours/include/vapours/sdmmc/sdmmc_gc_asic.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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/sdmmc/sdmmc_build_config.hpp>
|
||||
|
||||
namespace ams::sdmmc {
|
||||
|
||||
constexpr inline size_t GcAsicOperationSize = 0x40;
|
||||
|
||||
void PutGcAsicToSleep(Port port);
|
||||
Result AwakenGcAsic(Port port);
|
||||
Result WriteGcAsicOperation(Port port, const void *op_buf, size_t op_buf_size);
|
||||
Result FinishGcAsicOperation(Port port);
|
||||
Result AbortGcAsicOperation(Port port);
|
||||
Result SleepGcAsic(Port port);
|
||||
Result UpdateGcAsicKey(Port port);
|
||||
|
||||
void SignalGcRemovedEvent(Port port);
|
||||
void ClearGcRemovedEvent(Port port);
|
||||
|
||||
}
|
||||
43
libraries/libvapours/include/vapours/sdmmc/sdmmc_mmc.hpp
Normal file
43
libraries/libvapours/include/vapours/sdmmc/sdmmc_mmc.hpp
Normal 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/sdmmc/sdmmc_build_config.hpp>
|
||||
|
||||
|
||||
namespace ams::sdmmc {
|
||||
|
||||
enum MmcPartition {
|
||||
MmcPartition_UserData = 0,
|
||||
MmcPartition_BootPartition1 = 1,
|
||||
MmcPartition_BootPartition2 = 2,
|
||||
MmcPartition_Unknown = 3,
|
||||
};
|
||||
|
||||
constexpr inline size_t MmcExtendedCsdSize = 0x200;
|
||||
constexpr inline size_t MmcWorkBufferSize = MmcExtendedCsdSize;
|
||||
|
||||
void SetMmcWorkBuffer(Port port, void *buffer, size_t buffer_size);
|
||||
void PutMmcToSleep(Port port);
|
||||
void AwakenMmc(Port port);
|
||||
Result SelectMmcPartition(Port port, MmcPartition mmc_partition);
|
||||
Result EraseMmc(Port port);
|
||||
Result GetMmcBootPartitionCapacity(u32 *out_num_sectors, Port port);
|
||||
Result GetMmcExtendedCsd(void *out_buffer, size_t buffer_size, Port port);
|
||||
|
||||
Result CheckMmcConnection(SpeedMode *out_speed_mode, BusWidth *out_bus_width, Port port);
|
||||
|
||||
}
|
||||
53
libraries/libvapours/include/vapours/sdmmc/sdmmc_sd_card.hpp
Normal file
53
libraries/libvapours/include/vapours/sdmmc/sdmmc_sd_card.hpp
Normal 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/sdmmc/sdmmc_build_config.hpp>
|
||||
|
||||
namespace ams::sdmmc {
|
||||
|
||||
enum SdCardSwitchFunction {
|
||||
SdCardSwitchFunction_CheckSupportedFunction = 0,
|
||||
SdCardSwitchFunction_CheckDefault = 1,
|
||||
SdCardSwitchFunction_CheckHighSpeed = 2,
|
||||
SdCardSwitchFunction_CheckSdr50 = 3,
|
||||
SdCardSwitchFunction_CheckSdr104 = 4,
|
||||
SdCardSwitchFunction_CheckDdr50 = 5,
|
||||
};
|
||||
|
||||
constexpr inline size_t SdCardScrSize = 0x08;
|
||||
constexpr inline size_t SdCardSwitchFunctionStatusSize = 0x40;
|
||||
constexpr inline size_t SdCardSdStatusSize = 0x40;
|
||||
|
||||
constexpr inline size_t SdCardWorkBufferSize = SdCardSdStatusSize;
|
||||
|
||||
void SetSdCardWorkBuffer(Port port, void *buffer, size_t buffer_size);
|
||||
void PutSdCardToSleep(Port port);
|
||||
void AwakenSdCard(Port port);
|
||||
Result GetSdCardProtectedAreaCapacity(u32 *out_num_sectors, Port port);
|
||||
Result GetSdCardScr(void *dst, size_t dst_size, Port port);
|
||||
Result GetSdCardSwitchFunctionStatus(void *dst, size_t dst_size, Port port, SdCardSwitchFunction switch_function);
|
||||
Result GetSdCardCurrentConsumption(u16 *out_current_consumption, Port port, SpeedMode speed_mode);
|
||||
Result GetSdCardSdStatus(void *dst, size_t dst_size, Port port);
|
||||
|
||||
Result CheckSdCardConnection(SpeedMode *out_speed_mode, BusWidth *out_bus_width, Port port);
|
||||
|
||||
bool IsSdCardInserted(Port port);
|
||||
bool IsSdCardRemoved(Port port);
|
||||
|
||||
void RegisterSdCardDetectionEventCallback(Port port, DeviceDetectionEventCallback callback, void *arg);
|
||||
void UnregisterSdCardDetectionEventCallback(Port port);
|
||||
|
||||
}
|
||||
39
libraries/libvapours/include/vapours/tegra.hpp
Normal file
39
libraries/libvapours/include/vapours/tegra.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/literals.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/reg.hpp>
|
||||
|
||||
#include <vapours/tegra/tegra_ahb_arbc.hpp>
|
||||
#include <vapours/tegra/tegra_apb_misc.hpp>
|
||||
#include <vapours/tegra/tegra_avp_cache.hpp>
|
||||
#include <vapours/tegra/tegra_clkrst.hpp>
|
||||
#include <vapours/tegra/tegra_emc.hpp>
|
||||
#include <vapours/tegra/tegra_evp.hpp>
|
||||
#include <vapours/tegra/tegra_flow_ctlr.hpp>
|
||||
#include <vapours/tegra/tegra_ictlr.hpp>
|
||||
#include <vapours/tegra/tegra_mc.hpp>
|
||||
#include <vapours/tegra/tegra_mselect.hpp>
|
||||
#include <vapours/tegra/tegra_pinmux.hpp>
|
||||
#include <vapours/tegra/tegra_pg_up.hpp>
|
||||
#include <vapours/tegra/tegra_pmc.hpp>
|
||||
#include <vapours/tegra/tegra_sb.hpp>
|
||||
#include <vapours/tegra/tegra_sysctr0.hpp>
|
||||
#include <vapours/tegra/tegra_timer.hpp>
|
||||
@@ -14,7 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/literals.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/reg.hpp>
|
||||
|
||||
#define AHB_ARBC(x) (0x6000c000 + x)
|
||||
|
||||
@@ -14,11 +14,24 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/literals.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/reg.hpp>
|
||||
|
||||
#define APB_MISC_PP_CONFIG_CTL (0x024)
|
||||
#define APB_MISC_PP_CONFIG_CTL (0x024)
|
||||
|
||||
#define APB_MISC_GP_ASDBGREG (0x810)
|
||||
#define APB_MISC_GP_ASDBGREG (0x810)
|
||||
|
||||
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL (0xA98)
|
||||
|
||||
#define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL (0xA9C)
|
||||
#define APB_MISC_GP_SDMMC2_PAD_CFGPADCTRL (0xA9C)
|
||||
|
||||
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL (0xAB4)
|
||||
#define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL (0xABC)
|
||||
|
||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 (0xc00)
|
||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 (0xc00)
|
||||
@@ -41,6 +54,29 @@ DEFINE_APB_MISC_REG_BIT_ENUM(PP_CONFIG_CTL_TBE, 7, DISABLE, ENABLE);
|
||||
|
||||
DEFINE_APB_MISC_REG(GP_ASDBGREG_CFG2TMC_RAM_SVOP_PDP, 24, 2);
|
||||
|
||||
DEFINE_APB_MISC_REG (GP_SDMMC1_PAD_CFGPADCTRL_CFG2TMC_SDMMC1_PAD_CAL_DRVDN, 12, 7);
|
||||
DEFINE_APB_MISC_REG (GP_SDMMC1_PAD_CFGPADCTRL_CFG2TMC_SDMMC1_PAD_CAL_DRVUP, 20, 7);
|
||||
DEFINE_APB_MISC_REG (GP_SDMMC1_PAD_CFGPADCTRL_CFG2TMC_SDMMC1_CLK_CFG_CAL_DRVDN_SLWR, 28, 2);
|
||||
DEFINE_APB_MISC_REG (GP_SDMMC1_PAD_CFGPADCTRL_CFG2TMC_SDMMC1_CLK_CFG_CAL_DRVDN_SLWF, 30, 2);
|
||||
|
||||
DEFINE_APB_MISC_REG_BIT_ENUM(GP_EMMC2_PAD_CFGPADCTRL_CFG2TMC_EMMC2_PAD_E_SCH, 0, DISABLE, ENABLE);
|
||||
DEFINE_APB_MISC_REG (GP_EMMC2_PAD_CFGPADCTRL_CFG2TMC_EMMC2_PAD_DRVDN_COMP, 2, 6);
|
||||
DEFINE_APB_MISC_REG (GP_EMMC2_PAD_CFGPADCTRL_CFG2TMC_EMMC2_PAD_DRVUP_COMP, 8, 6);
|
||||
DEFINE_APB_MISC_REG (GP_EMMC2_PAD_CFGPADCTRL_MISC2PMC_EMMC2_ALL_PARK, 14, 13);
|
||||
|
||||
DEFINE_APB_MISC_REG (GP_SDMMC2_PAD_CFGPADCTRL_CFG2TMC_SDMMC2_PAD_CAL_DRVDN, 12, 7);
|
||||
DEFINE_APB_MISC_REG (GP_SDMMC2_PAD_CFGPADCTRL_CFG2TMC_SDMMC2_PAD_CAL_DRVUP, 20, 7);
|
||||
|
||||
|
||||
DEFINE_APB_MISC_REG_BIT_ENUM(GP_EMMC4_PAD_CFGPADCTRL_CFG2TMC_EMMC4_PAD_E_SCH, 0, DISABLE, ENABLE);
|
||||
DEFINE_APB_MISC_REG (GP_EMMC4_PAD_CFGPADCTRL_CFG2TMC_EMMC4_PAD_DRVDN_COMP, 2, 6);
|
||||
DEFINE_APB_MISC_REG (GP_EMMC4_PAD_CFGPADCTRL_CFG2TMC_EMMC4_PAD_DRVUP_COMP, 8, 6);
|
||||
DEFINE_APB_MISC_REG (GP_EMMC4_PAD_CFGPADCTRL_MISC2PMC_EMMC4_ALL_PARK, 14, 13);
|
||||
|
||||
DEFINE_APB_MISC_REG(GP_EMMC4_PAD_PUPD_CFGPADCTRL_CFG2TMC_EMMC4_PAD_CMD_PUPD_PULLU, 1, 1);
|
||||
DEFINE_APB_MISC_REG(GP_EMMC4_PAD_PUPD_CFGPADCTRL_CFG2TMC_EMMC4_PAD_CLK_PUPD_PULLD, 2, 1);
|
||||
DEFINE_APB_MISC_REG(GP_EMMC4_PAD_PUPD_CFGPADCTRL_CFG2TMC_EMMC4_PAD_DQS_PUPD_PULLD, 22, 1);
|
||||
|
||||
#define DEFINE_SLAVE_SECURITY_REG(RINDEX, INDEX, NAME) DEFINE_APB_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);
|
||||
@@ -14,7 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/literals.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/reg.hpp>
|
||||
|
||||
#define AVP_CACHE_ADDRESS(x) (0x50040000 + x)
|
||||
|
||||
@@ -14,7 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/literals.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/reg.hpp>
|
||||
|
||||
/* Clock source enums. */
|
||||
#define CLK_RST_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (CLK_RST_CONTROLLER, NAME)
|
||||
@@ -33,13 +38,18 @@
|
||||
|
||||
#define CLK_RST_CONTROLLER_MISC_CLK_ENB (0x048)
|
||||
#define CLK_RST_CONTROLLER_OSC_CTRL (0x050)
|
||||
#define CLK_RST_CONTROLLER_PLLD_BASE (0x0D0)
|
||||
#define CLK_RST_CONTROLLER_PLLD_MISC1 (0x0D8)
|
||||
#define CLK_RST_CONTROLLER_PLLD_MISC (0x0DC)
|
||||
#define CLK_RST_CONTROLLER_PLLX_BASE (0x0E0)
|
||||
#define CLK_RST_CONTROLLER_PLLX_MISC (0x0E4)
|
||||
#define CLK_RST_CONTROLLER_CCLKG_BURST_POLICY (0x368)
|
||||
#define CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER (0x36C)
|
||||
#define CLK_RST_CONTROLLER_CCLKLP_BURST_POLICY (0x370)
|
||||
#define CLK_RST_CONTROLLER_SUPER_CCLKLP_DIVIDER (0x374)
|
||||
#define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2 (0x388)
|
||||
#define CLK_RST_CONTROLLER_SPARE_REG0 (0x55C)
|
||||
#define CLK_RST_CONTROLLER_PLLC4_BASE (0x5A4)
|
||||
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA (0x0F8)
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB (0x0FC)
|
||||
@@ -74,6 +84,10 @@ DEFINE_CLK_RST_REG(CPU_SOFTRST_CTRL2_CAR2PMC_CPU_ACK_WIDTH, 0, 12);
|
||||
|
||||
DEFINE_CLK_RST_REG_TWO_BIT_ENUM(SPARE_REG0_CLK_M_DIVISOR, 2, CLK_M_DIVISOR1, CLK_M_DIVISOR2, CLK_M_DIVISOR3, CLK_M_DIVISOR4);
|
||||
|
||||
DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_IDDQ, 18, OFF, ON);
|
||||
DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_LOCK, 27, NOT_LOCK, LOCK_FEQ_AND_PHASE);
|
||||
DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_ENABLE, 30, DISABLE, ENABLE);
|
||||
|
||||
/* RST_DEVICES */
|
||||
#define CLK_RST_CONTROLLER_RST_DEVICES_L (0x004)
|
||||
#define CLK_RST_CONTROLLER_RST_DEVICES_H (0x008)
|
||||
@@ -93,15 +107,24 @@ DEFINE_CLK_RST_REG_TWO_BIT_ENUM(SPARE_REG0_CLK_M_DIVISOR, 2, CLK_M_DIVISOR1, CLK
|
||||
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_W (0x364)
|
||||
|
||||
/* CLK_SOURCE */
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 (0x124)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 (0x128)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT (0x3B4)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3E8)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF (0x62C)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC (0x630)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 (0x124)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 (0x128)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 (0x138)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 (0x150)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 (0x154)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 (0x164)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 (0x1BC)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE (0x1D4)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT (0x3B4)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3E8)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP (0x620)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF (0x62C)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC (0x630)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL (0x66C)
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM (0x694)
|
||||
|
||||
/* RST_DEV_*_SET */
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_L_SET (0x300)
|
||||
@@ -163,6 +186,19 @@ DEFINE_CLK_RST_REG(CLK_SOURCE_I2C1_I2C1_CLK_DIVISOR, 0, 8);
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_I2C5_I2C5_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||
DEFINE_CLK_RST_REG(CLK_SOURCE_I2C5_I2C5_CLK_DIVISOR, 0, 8);
|
||||
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_SDMMC1_SDMMC1_CLK_SRC, 29, PLLP_OUT0, PLLA_OUT, PLLC_OUT0, PLLC4_OUT2, PLLM_OUT0, PLLE_OUT0, CLK_M, PLLC4_OUT0);
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_SDMMC2_SDMMC2_CLK_SRC, 29, PLLP_OUT0, PLLC4_OUT2_LJ, PLLC4_OUT0_LJ, PLLC4_OUT2, PLLC4_OUT1, PLLC4_OUT1_LJ, CLK_M, PLLC4_OUT0);
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_SDMMC4_SDMMC4_CLK_SRC, 29, PLLP_OUT0, PLLC4_OUT2_LJ, PLLC4_OUT0_LJ, PLLC4_OUT2, PLLC4_OUT1, PLLC4_OUT1_LJ, CLK_M, PLLC4_OUT0);
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_SDMMC3_SDMMC3_CLK_SRC, 29, PLLP_OUT0, PLLA_OUT, PLLC_OUT0, PLLC4_OUT2, PLLC4_OUT1, PLLE_OUT0, CLK_M, PLLC4_OUT0);
|
||||
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_SDMMCX_SDMMCX_CLK_SRC, 29, PLLP_OUT0, _RSVD1_, _RSVD2_, PLLC4_OUT2, _RSVD4_, _RSVD5_, CLK_M, PLLC4_OUT0);
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_SDMMC24_SDMMC24_CLK_SRC, 29, PLLP_OUT0, PLLC4_OUT2_LJ, PLLC4_OUT0_LJ, PLLC4_OUT2, PLLC4_OUT1, PLLC4_OUT1_LJ, CLK_M, PLLC4_OUT0);
|
||||
|
||||
DEFINE_CLK_RST_REG(CLK_SOURCE_SDMMC1_SDMMC1_CLK_DIVISOR, 0, 8);
|
||||
DEFINE_CLK_RST_REG(CLK_SOURCE_SDMMC2_SDMMC2_CLK_DIVISOR, 0, 8);
|
||||
DEFINE_CLK_RST_REG(CLK_SOURCE_SDMMC4_SDMMC4_CLK_DIVISOR, 0, 8);
|
||||
DEFINE_CLK_RST_REG(CLK_SOURCE_SDMMC3_SDMMC3_CLK_DIVISOR, 0, 8);
|
||||
|
||||
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);
|
||||
@@ -178,6 +214,9 @@ DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_DVFS_REF_DVFS_REF_CLK_SRC, 29, PLLP
|
||||
DEFINE_CLK_RST_REG(CLK_SOURCE_DVFS_SOC_DVFS_SOC_DIVISOR, 0, 8);
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_DVFS_SOC_DVFS_SOC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||
|
||||
DEFINE_CLK_RST_REG(CLK_SOURCE_LEGACY_TM_CLK_DIVISOR, 0, 8);
|
||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_LEGACY_TM_CLK_SRC, 29, PLLP_OUT3, PLLC_OUT0, PLLC2_OUT0, CLK_M, PLLP_OUT0, PLLC4_OUT0, PLLC4_OUT1, PLLC4_OUT2);
|
||||
|
||||
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_L_SET_SET_COP_RST, 1, DISABLE, ENABLE);
|
||||
|
||||
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_L_CLR_CLR_COP_RST, 1, DISABLE, ENABLE);
|
||||
@@ -198,6 +237,9 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA
|
||||
HANDLER(L, RTC, 0, 4) \
|
||||
HANDLER(L, TMR, 0, 5) \
|
||||
HANDLER(L, GPIO, 0, 8) \
|
||||
HANDLER(L, SDMMC2, 0, 9) \
|
||||
HANDLER(L, SDMMC1, 0, 14) \
|
||||
HANDLER(L, SDMMC4, 0, 15) \
|
||||
HANDLER(L, USBD, 0, 22) \
|
||||
HANDLER(L, CACHE2, 0, 31) \
|
||||
HANDLER(H, MEM, 1, 0) \
|
||||
@@ -209,6 +251,7 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA
|
||||
HANDLER(H, I2C5, 1, 15) \
|
||||
HANDLER(H, EMC, 1, 25) \
|
||||
HANDLER(H, USB2, 1, 26) \
|
||||
HANDLER(U, SDMMC3, 2, 5) \
|
||||
HANDLER(U, CSITE, 2, 9) \
|
||||
HANDLER(U, IRAMA, 2, 20) \
|
||||
HANDLER(U, IRAMB, 2, 21) \
|
||||
@@ -238,6 +281,7 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA
|
||||
HANDLER(X, GPU, 5, 24) \
|
||||
HANDLER(X, DBGAPB, 5, 25) \
|
||||
HANDLER(X, PLLG_REF, 5, 29) \
|
||||
HANDLER(Y, LEGACY_TM, 6, 1) \
|
||||
HANDLER(Y, MC_CCPA, 6, 8) \
|
||||
HANDLER(Y, MC_CDPA, 6, 9) \
|
||||
HANDLER(Y, PLLP_OUT_CPU, 6, 31)
|
||||
@@ -14,7 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/literals.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/results.hpp>
|
||||
#include <vapours/reg.hpp>
|
||||
|
||||
#define EMC_ADDRESS(x) (0x7001B000 + x)
|
||||
#define EMC0_ADDRESS(x) (0x7001E000 + x)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user