diff --git a/Makefile b/Makefile
index d85056f77..26bc306a7 100644
--- a/Makefile
+++ b/Makefile
@@ -13,6 +13,10 @@ $(strip $1):
@echo "Building $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/atmosphere.mk ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
+dist-no-debug-$(strip $1):
+ @echo "Building $(strip $1)"
+ @$$(MAKE) -f $(CURRENT_DIRECTORY)/atmosphere.mk dist-no-debug ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
+
clean-$(strip $1):
@echo "Cleaning $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/atmosphere.mk clean ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
diff --git a/atmosphere.mk b/atmosphere.mk
index 7d80c94be..691597a3e 100644
--- a/atmosphere.mk
+++ b/atmosphere.mk
@@ -54,7 +54,7 @@ dist: dist-no-debug
cp $(CURRENT_DIRECTORY)/troposphere/daybreak/daybreak.elf $(DIST_DIR)/daybreak.elf
cp $(CURRENT_DIRECTORY)/troposphere/haze/haze.elf $(DIST_DIR)/haze.elf
cp $(CURRENT_DIRECTORY)/troposphere/reboot_to_payload/reboot_to_payload.elf $(DIST_DIR)/reboot_to_payload.elf
- cd $(DIST_DIR); zip -r ../atmosphere-$(ATMOSPHERE_VERSION)-debug.zip ./*; cd ../;
+ cd $(DIST_DIR); zip -1 -r ../atmosphere-$(ATMOSPHERE_VERSION)-debug.zip ./*; cd ../;
rm -rf $(DIST_DIR)
dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
diff --git a/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp b/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp
index a9f03641b..b22f3441e 100644
--- a/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp
+++ b/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp
@@ -21,11 +21,13 @@ namespace ams::util {
/* Compression utilities. */
int CompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size);
- size_t CompressZstd(void *dst, size_t dst_size, const void *src, size_t src_size);
+ size_t CompressZbic(void *dst, size_t dst_size, const void *src, size_t src_size);
+
+ constexpr size_t ZstdDctxWorkspaceSize = 0x176E8;
/* Decompression utilities. */
int DecompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size);
- size_t DecompressZstd(void *dst, size_t dst_size, const void *src, size_t src_size);
- bool DecompressZstdForLoader(void* workspace, size_t workspace_size, void *dst, size_t dst_size, size_t expected_dec_size, const void *src, size_t src_size);
+ size_t DecompressZbic(void *dst, size_t dst_size, const void *src, size_t src_size);
+ bool DecompressZbicForLoader(void* workspace, size_t workspace_size, void *dst, size_t dst_size, size_t expected_dec_size, const void *src, size_t src_size);
}
\ No newline at end of file
diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp
index 827a02c1c..e687f9bbc 100644
--- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp
+++ b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp
@@ -104,25 +104,25 @@ namespace ams::pinmux::driver::board::nintendo::nx {
#if defined(AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART)
UpdateSinglePinmuxPad({
.index = PinmuxPadIndex_Uart2Tx,
- .option = 0, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output */
- .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
+ .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output,
+ .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
});
UpdateSinglePinmuxPad({
.index = PinmuxPadIndex_Uart2Cts,
- .option = 0x20, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input */
- .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
+ .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input,
+ .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
});
#endif
#if defined(AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART)
UpdateSinglePinmuxPad({
.index = PinmuxPadIndex_Uart3Tx,
- .option = 0, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output */
- .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
+ .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output,
+ .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
});
UpdateSinglePinmuxPad({
.index = PinmuxPadIndex_Uart3Cts,
- .option = 0x20, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input */
- .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
+ .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input,
+ .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
});
#endif
}
diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.cpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.cpp
index c7c9de2c2..081b7aba7 100644
--- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.cpp
+++ b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.cpp
@@ -24,170 +24,6 @@ namespace ams::pinmux::driver::board::nintendo::nx {
uintptr_t g_apb_misc_virtual_address = dd::QueryIoMapping(0x70000000, 0x4000);
- enum PinmuxPadMask : u32 {
- PinmuxPadMask_Pm = 0x3,
- PinmuxPadMask_Pupd = 0xC,
- PinmuxPadMask_Tristate = 0x10,
- PinmuxPadMask_Park = 0x20,
- PinmuxPadMask_EInput = 0x40,
- PinmuxPadMask_Lock = 0x80,
- PinmuxPadMask_ELpdr = 0x100,
- PinmuxPadMask_EHsm = 0x200,
- PinmuxPadMask_EIoHv = 0x400,
- PinmuxPadMask_EOd = 0x800,
- PinmuxPadMask_ESchmt = 0x1000,
- PinmuxPadMask_DrvType = 0x6000,
- PinmuxPadMask_Preemp = 0x8000,
- PinmuxPadMask_IoReset = 0x10000,
- };
-
- enum PinmuxPadBitOffset : u32 {
- PinmuxPadBitOffset_Pm = 0x0,
- PinmuxPadBitOffset_Pupd = 0x2,
- PinmuxPadBitOffset_Tristate = 0x4,
- PinmuxPadBitOffset_Park = 0x5,
- PinmuxPadBitOffset_EInput = 0x6,
- PinmuxPadBitOffset_Lock = 0x7,
- PinmuxPadBitOffset_ELpdr = 0x8,
- PinmuxPadBitOffset_EHsm = 0x9,
- PinmuxPadBitOffset_EIoHv = 0xA,
- PinmuxPadBitOffset_EOd = 0xB,
- PinmuxPadBitOffset_ESchmt = 0xC,
- PinmuxPadBitOffset_DrvType = 0xD,
- PinmuxPadBitOffset_Preemp = 0xF,
- PinmuxPadBitOffset_IoReset = 0x10,
- };
-
- enum PinmuxOptBitMask : u32 {
- PinmuxOptBitMask_Pm = 0x7,
- PinmuxOptBitMask_Pupd = 0x18,
- PinmuxOptBitMask_Dir = 0x60,
- PinmuxOptBitMask_Lock = 0x80,
- PinmuxOptBitMask_IoReset = 0x100,
- PinmuxOptBitMask_IoHv = 0x200,
- PinmuxOptBitMask_Park = 0x400,
- PinmuxOptBitMask_Lpdr = 0x800,
- PinmuxOptBitMask_Hsm = 0x1000,
- PinmuxOptBitMask_Schmt = 0x2000,
- PinmuxOptBitMask_DrvType = 0xC000,
- PinmuxOptBitMask_Preemp = 0x10000,
- };
-
- enum PinmuxOptBitOffset {
- PinmuxOptBitOffset_Pm = 0x0,
- PinmuxOptBitOffset_Pupd = 0x3,
- PinmuxOptBitOffset_Dir = 0x5,
- PinmuxOptBitOffset_Lock = 0x7,
- PinmuxOptBitOffset_IoReset = 0x8,
- PinmuxOptBitOffset_IoHv = 0x9,
- PinmuxOptBitOffset_Park = 0xA,
- PinmuxOptBitOffset_Lpdr = 0xB,
- PinmuxOptBitOffset_Hsm = 0xC,
- PinmuxOptBitOffset_Schmt = 0xD,
- PinmuxOptBitOffset_DrvType = 0xE,
- PinmuxOptBitOffset_Preemp = 0x10,
- };
-
- enum PinmuxDrivePadMask : u32{
- PinmuxDrivePadMask_DrvDn = 0x0001F000,
- PinmuxDrivePadMask_DrvUp = 0x01F00000,
- PinmuxDrivePadMask_CzDrvDn = 0x0007F000,
- PinmuxDrivePadMask_CzDrvUp = 0x07F00000,
- PinmuxDrivePadMask_SlwR = 0x30000000,
- PinmuxDrivePadMask_SlwF = 0xC0000000,
- };
-
- enum PinmuxDrivePadBitOffset : u32 {
- PinmuxDrivePadBitOffset_DrvDn = 12,
- PinmuxDrivePadBitOffset_DrvUp = 20,
- PinmuxDrivePadBitOffset_CzDrvDn = 12,
- PinmuxDrivePadBitOffset_CzDrvUp = 20,
- PinmuxDrivePadBitOffset_SlwR = 28,
- PinmuxDrivePadBitOffset_SlwF = 30,
- };
-
- enum PinmuxDriveOptBitMask : u32 {
- PinmuxDriveOptBitMask_DrvDn = 0x0001F000,
- PinmuxDriveOptBitMask_DrvUp = 0x01F00000,
- PinmuxDriveOptBitMask_CzDrvDn = 0x0007F000,
- PinmuxDriveOptBitMask_CzDrvUp = 0x07F00000,
- PinmuxDriveOptBitMask_SlwR = 0x30000000,
- PinmuxDriveOptBitMask_SlwF = 0xC0000000,
- };
-
- enum PinmuxDriveOptBitOffset : u32 {
- PinmuxDriveOptBitOffset_DrvDn = 12,
- PinmuxDriveOptBitOffset_DrvUp = 20,
- PinmuxDriveOptBitOffset_CzDrvDn = 12,
- PinmuxDriveOptBitOffset_CzDrvUp = 20,
- PinmuxDriveOptBitOffset_SlwR = 28,
- PinmuxDriveOptBitOffset_SlwF = 30,
- };
-
- enum PinmuxOpt : u32 {
- /* Pm */
- PinmuxOpt_Gpio = 0x4,
- PinmuxOpt_Unused = 0x5,
-
- /* Pupd */
- PinmuxOpt_NoPupd = 0x0,
- PinmuxOpt_PullDown = 0x8,
- PinmuxOpt_PullUp = 0x10,
-
- /* Dir */
- PinmuxOpt_Output = 0x0,
- PinmuxOpt_Input = 0x20,
- PinmuxOpt_Bidirection = 0x40,
- PinmuxOpt_OpenDrain = 0x60,
-
- /* Lock */
- PinmuxOpt_Unlock = 0x0,
- PinmuxOpt_Lock = 0x80,
-
- /* IoReset */
- PinmuxOpt_DisableIoReset = 0x0,
- PinmuxOpt_EnableIoReset = 0x100,
-
- /* IoHv */
- PinmuxOpt_NormalVoltage = 0x0,
- PinmuxOpt_HighVoltage = 0x200,
-
- /* Park */
- PinmuxOpt_ResetOnLowPower = 0x0,
- PinmuxOpt_ParkOnLowPower = 0x400,
-
- /* Lpdr */
- PinmuxOpt_DisableBaseDriver = 0x0,
- PinmuxOpt_EnableBaseDriver = 0x800,
-
- /* Hsm */
- PinmuxOpt_DisableHighSpeedMode = 0x0,
- PinmuxOpt_EnableHighSpeedMode = 0x1000,
-
- /* Schmt */
- PinmuxOpt_CmosMode = 0x0,
- PinmuxOpt_SchmittTrigger = 0x2000,
-
- /* DrvType */
- PinmuxOpt_DrvType1X = 0x0,
- PinmuxOpt_DrvType2X = 0x4000,
- PinmuxOpt_DrvType3X = 0x8000,
- PinmuxOpt_DrvType4X = 0xC000,
-
- /* Preemp */
- PinmuxOpt_DisablePreemp = 0x0,
- PinmuxOpt_EnablePreemp = 0x10000,
- };
-
- enum PinmuxPadPm : u32 {
- PinmuxPadPm_Default = 0xFFFFFFFF,
- PinmuxPadPm_Pm0 = 0x0,
- PinmuxPadPm_Pm1 = 0x1,
- PinmuxPadPm_Pm2 = 0x2,
- PinmuxPadPm_Pm3 = 0x3,
- PinmuxPadPm_Safe = 0x4,
- };
-
struct PinmuxPadCharacter {
u32 reg_offset;
u32 reg_mask;
diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.hpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.hpp
index 6ec386b70..5e1087d13 100644
--- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.hpp
+++ b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_platform_pads.hpp
@@ -30,6 +30,170 @@ namespace ams::pinmux::driver::board::nintendo::nx {
u32 option_mask;
};
+ enum PinmuxPadMask : u32 {
+ PinmuxPadMask_Pm = 0x3,
+ PinmuxPadMask_Pupd = 0xC,
+ PinmuxPadMask_Tristate = 0x10,
+ PinmuxPadMask_Park = 0x20,
+ PinmuxPadMask_EInput = 0x40,
+ PinmuxPadMask_Lock = 0x80,
+ PinmuxPadMask_ELpdr = 0x100,
+ PinmuxPadMask_EHsm = 0x200,
+ PinmuxPadMask_EIoHv = 0x400,
+ PinmuxPadMask_EOd = 0x800,
+ PinmuxPadMask_ESchmt = 0x1000,
+ PinmuxPadMask_DrvType = 0x6000,
+ PinmuxPadMask_Preemp = 0x8000,
+ PinmuxPadMask_IoReset = 0x10000,
+ };
+
+ enum PinmuxPadBitOffset : u32 {
+ PinmuxPadBitOffset_Pm = 0x0,
+ PinmuxPadBitOffset_Pupd = 0x2,
+ PinmuxPadBitOffset_Tristate = 0x4,
+ PinmuxPadBitOffset_Park = 0x5,
+ PinmuxPadBitOffset_EInput = 0x6,
+ PinmuxPadBitOffset_Lock = 0x7,
+ PinmuxPadBitOffset_ELpdr = 0x8,
+ PinmuxPadBitOffset_EHsm = 0x9,
+ PinmuxPadBitOffset_EIoHv = 0xA,
+ PinmuxPadBitOffset_EOd = 0xB,
+ PinmuxPadBitOffset_ESchmt = 0xC,
+ PinmuxPadBitOffset_DrvType = 0xD,
+ PinmuxPadBitOffset_Preemp = 0xF,
+ PinmuxPadBitOffset_IoReset = 0x10,
+ };
+
+ enum PinmuxOptBitMask : u32 {
+ PinmuxOptBitMask_Pm = 0x7,
+ PinmuxOptBitMask_Pupd = 0x18,
+ PinmuxOptBitMask_Dir = 0x60,
+ PinmuxOptBitMask_Lock = 0x80,
+ PinmuxOptBitMask_IoReset = 0x100,
+ PinmuxOptBitMask_IoHv = 0x200,
+ PinmuxOptBitMask_Park = 0x400,
+ PinmuxOptBitMask_Lpdr = 0x800,
+ PinmuxOptBitMask_Hsm = 0x1000,
+ PinmuxOptBitMask_Schmt = 0x2000,
+ PinmuxOptBitMask_DrvType = 0xC000,
+ PinmuxOptBitMask_Preemp = 0x10000,
+ };
+
+ enum PinmuxOptBitOffset {
+ PinmuxOptBitOffset_Pm = 0x0,
+ PinmuxOptBitOffset_Pupd = 0x3,
+ PinmuxOptBitOffset_Dir = 0x5,
+ PinmuxOptBitOffset_Lock = 0x7,
+ PinmuxOptBitOffset_IoReset = 0x8,
+ PinmuxOptBitOffset_IoHv = 0x9,
+ PinmuxOptBitOffset_Park = 0xA,
+ PinmuxOptBitOffset_Lpdr = 0xB,
+ PinmuxOptBitOffset_Hsm = 0xC,
+ PinmuxOptBitOffset_Schmt = 0xD,
+ PinmuxOptBitOffset_DrvType = 0xE,
+ PinmuxOptBitOffset_Preemp = 0x10,
+ };
+
+ enum PinmuxDrivePadMask : u32 {
+ PinmuxDrivePadMask_DrvDn = 0x0001F000,
+ PinmuxDrivePadMask_DrvUp = 0x01F00000,
+ PinmuxDrivePadMask_CzDrvDn = 0x0007F000,
+ PinmuxDrivePadMask_CzDrvUp = 0x07F00000,
+ PinmuxDrivePadMask_SlwR = 0x30000000,
+ PinmuxDrivePadMask_SlwF = 0xC0000000,
+ };
+
+ enum PinmuxDrivePadBitOffset : u32 {
+ PinmuxDrivePadBitOffset_DrvDn = 12,
+ PinmuxDrivePadBitOffset_DrvUp = 20,
+ PinmuxDrivePadBitOffset_CzDrvDn = 12,
+ PinmuxDrivePadBitOffset_CzDrvUp = 20,
+ PinmuxDrivePadBitOffset_SlwR = 28,
+ PinmuxDrivePadBitOffset_SlwF = 30,
+ };
+
+ enum PinmuxDriveOptBitMask : u32 {
+ PinmuxDriveOptBitMask_DrvDn = 0x0001F000,
+ PinmuxDriveOptBitMask_DrvUp = 0x01F00000,
+ PinmuxDriveOptBitMask_CzDrvDn = 0x0007F000,
+ PinmuxDriveOptBitMask_CzDrvUp = 0x07F00000,
+ PinmuxDriveOptBitMask_SlwR = 0x30000000,
+ PinmuxDriveOptBitMask_SlwF = 0xC0000000,
+ };
+
+ enum PinmuxDriveOptBitOffset : u32 {
+ PinmuxDriveOptBitOffset_DrvDn = 12,
+ PinmuxDriveOptBitOffset_DrvUp = 20,
+ PinmuxDriveOptBitOffset_CzDrvDn = 12,
+ PinmuxDriveOptBitOffset_CzDrvUp = 20,
+ PinmuxDriveOptBitOffset_SlwR = 28,
+ PinmuxDriveOptBitOffset_SlwF = 30,
+ };
+
+ enum PinmuxOpt : u32 {
+ /* Pm */
+ PinmuxOpt_Gpio = 0x4,
+ PinmuxOpt_Unused = 0x5,
+
+ /* Pupd */
+ PinmuxOpt_NoPupd = 0x0,
+ PinmuxOpt_PullDown = 0x8,
+ PinmuxOpt_PullUp = 0x10,
+
+ /* Dir */
+ PinmuxOpt_Output = 0x0,
+ PinmuxOpt_Input = 0x20,
+ PinmuxOpt_Bidirection = 0x40,
+ PinmuxOpt_OpenDrain = 0x60,
+
+ /* Lock */
+ PinmuxOpt_Unlock = 0x0,
+ PinmuxOpt_Lock = 0x80,
+
+ /* IoReset */
+ PinmuxOpt_DisableIoReset = 0x0,
+ PinmuxOpt_EnableIoReset = 0x100,
+
+ /* IoHv */
+ PinmuxOpt_NormalVoltage = 0x0,
+ PinmuxOpt_HighVoltage = 0x200,
+
+ /* Park */
+ PinmuxOpt_ResetOnLowPower = 0x0,
+ PinmuxOpt_ParkOnLowPower = 0x400,
+
+ /* Lpdr */
+ PinmuxOpt_DisableBaseDriver = 0x0,
+ PinmuxOpt_EnableBaseDriver = 0x800,
+
+ /* Hsm */
+ PinmuxOpt_DisableHighSpeedMode = 0x0,
+ PinmuxOpt_EnableHighSpeedMode = 0x1000,
+
+ /* Schmt */
+ PinmuxOpt_CmosMode = 0x0,
+ PinmuxOpt_SchmittTrigger = 0x2000,
+
+ /* DrvType */
+ PinmuxOpt_DrvType1X = 0x0,
+ PinmuxOpt_DrvType2X = 0x4000,
+ PinmuxOpt_DrvType3X = 0x8000,
+ PinmuxOpt_DrvType4X = 0xC000,
+
+ /* Preemp */
+ PinmuxOpt_DisablePreemp = 0x0,
+ PinmuxOpt_EnablePreemp = 0x10000,
+ };
+
+ enum PinmuxPadPm : u32 {
+ PinmuxPadPm_Default = 0xFFFFFFFF,
+ PinmuxPadPm_Pm0 = 0x0,
+ PinmuxPadPm_Pm1 = 0x1,
+ PinmuxPadPm_Pm2 = 0x2,
+ PinmuxPadPm_Pm3 = 0x3,
+ PinmuxPadPm_Safe = 0x4,
+ };
+
void InitializePlatformPads();
void UpdateSinglePinmuxPad(const PinmuxPadConfig &config);
diff --git a/libraries/libstratosphere/source/util/util_compression_lz4.cpp b/libraries/libstratosphere/source/util/util_compression_lz4.cpp
new file mode 100644
index 000000000..2f5704f47
--- /dev/null
+++ b/libraries/libstratosphere/source/util/util_compression_lz4.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include "lz4.h"
+
+namespace ams::util {
+
+ /* Compression utilities. */
+ int CompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size) {
+ /* Size checks. */
+ AMS_ABORT_UNLESS(dst_size <= std::numeric_limits::max());
+ AMS_ABORT_UNLESS(src_size <= std::numeric_limits::max());
+
+ /* This is just a thin wrapper around LZ4. */
+ return LZ4_compress_default(reinterpret_cast(src), reinterpret_cast(dst), static_cast(src_size), static_cast(dst_size));
+ }
+
+ /* Decompression utilities. */
+ int DecompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size) {
+ /* Size checks. */
+ AMS_ABORT_UNLESS(dst_size <= std::numeric_limits::max());
+ AMS_ABORT_UNLESS(src_size <= std::numeric_limits::max());
+
+ /* This is just a thin wrapper around LZ4. */
+ return LZ4_decompress_safe(reinterpret_cast(src), reinterpret_cast(dst), static_cast(src_size), static_cast(dst_size));
+ }
+
+}
\ No newline at end of file
diff --git a/libraries/libstratosphere/source/util/util_compression.cpp b/libraries/libstratosphere/source/util/util_compression_zbic.cpp
similarity index 68%
rename from libraries/libstratosphere/source/util/util_compression.cpp
rename to libraries/libstratosphere/source/util/util_compression_zbic.cpp
index f17021024..69743bf2d 100644
--- a/libraries/libstratosphere/source/util/util_compression.cpp
+++ b/libraries/libstratosphere/source/util/util_compression_zbic.cpp
@@ -17,21 +17,19 @@
#include "lz4.h"
#define ZSTD_STATIC_LINKING_ONLY
#define ZSTD_ZBIC_SUPPORT 1
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#define ZSTDLIB_VISIBLE static
+#define ZSTDLIB_HIDDEN static
#include "zstd.h"
+#include "zstd.inc"
+#pragma GCC diagnostic pop
namespace ams::util {
+ static_assert(sizeof(ZSTD_DCtx) <= ZstdDctxWorkspaceSize);
- /* Compression utilities. */
- int CompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size) {
- /* Size checks. */
- AMS_ABORT_UNLESS(dst_size <= std::numeric_limits::max());
- AMS_ABORT_UNLESS(src_size <= std::numeric_limits::max());
-
- /* This is just a thin wrapper around LZ4. */
- return LZ4_compress_default(reinterpret_cast(src), reinterpret_cast(dst), static_cast(src_size), static_cast(dst_size));
- }
-
- size_t CompressZstd(void *dst, size_t dst_size, const void *src, size_t src_size) {
+ size_t CompressZbic(void *dst, size_t dst_size, const void *src, size_t src_size) {
/* Basic size checks. */
AMS_ABORT_UNLESS(dst_size <= std::numeric_limits::max());
AMS_ABORT_UNLESS(src_size <= std::numeric_limits::max());
@@ -47,18 +45,8 @@ namespace ams::util {
/* This is just a wrapper around Zstd. */
return ZSTD_compress(dst, dst_size, src, src_size, compressionLevel);
}
-
- /* Decompression utilities. */
- int DecompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size) {
- /* Size checks. */
- AMS_ABORT_UNLESS(dst_size <= std::numeric_limits::max());
- AMS_ABORT_UNLESS(src_size <= std::numeric_limits::max());
-
- /* This is just a thin wrapper around LZ4. */
- return LZ4_decompress_safe(reinterpret_cast(src), reinterpret_cast(dst), static_cast(src_size), static_cast(dst_size));
- }
- size_t DecompressZstd(void *dst, size_t dst_size, const void *src, size_t src_size) {
+ size_t DecompressZbic(void *dst, size_t dst_size, const void *src, size_t src_size) {
/* Basic size checks. */
AMS_ABORT_UNLESS(dst_size <= std::numeric_limits::max());
AMS_ABORT_UNLESS(src_size <= std::numeric_limits::max());
@@ -72,10 +60,12 @@ namespace ams::util {
return ZSTD_decompress(dst, dst_size, src, src_size);
}
- bool DecompressZstdForLoader(void* workspace, size_t workspace_size, void *dst, size_t dst_size, size_t expected_dec_size, const void *src, size_t src_size) {
+ bool DecompressZbicForLoader(void* workspace, size_t workspace_size, void *dst, size_t dst_size, size_t expected_dec_size, const void *src, size_t src_size) {
/* Check decompression margin. */
auto margin = ZSTD_decompressionMargin(src, src_size);
if (ZSTD_isError(margin)) {
+ auto ec = ZSTD_getErrorCode(margin);
+ AMS_LOG("[ldr] can't determine decompression margin: %u (%s)\n", ec, ZSTD_getErrorString(ec));
return false;
}
@@ -86,17 +76,20 @@ namespace ams::util {
/* Make sure we fit in the destination buffer. */
if (margin + expected_dec_size > dst_size) {
+ AMS_LOG("[ldr] not enough space for decompression %lu + %lu > %lu\n", margin, expected_dec_size, dst_size);
return false;
}
- /* This is a runtime assert in Loader code. We replicate it here. */
- AMS_ABORT_UNLESS(ZSTD_estimateDCtxSize() == workspace_size);
+ /* This is a runtime assert in Loader code. Note that Nintendo does == comparison here. */
+ AMS_ABORT_UNLESS(ZSTD_estimateDCtxSize() <= workspace_size);
/* Decompress using a static decompression context. */
auto dctx = ZSTD_initStaticDCtx(workspace, workspace_size);
size_t dec_size = ZSTD_decompressDCtx(dctx, dst, dst_size, src, src_size);
if (ZSTD_isError(dec_size)) {
+ auto ec = ZSTD_getErrorCode(dec_size);
+ AMS_LOG("[ldr] decompression failed: %u (%s)\n", ec, ZSTD_getErrorString(ec));
return false;
}
diff --git a/libraries/libstratosphere/source/util/zstd.c b/libraries/libstratosphere/source/util/zstd.inc
similarity index 100%
rename from libraries/libstratosphere/source/util/zstd.c
rename to libraries/libstratosphere/source/util/zstd.inc
diff --git a/libraries/libvapours/include/vapours/results/results_common.hpp b/libraries/libvapours/include/vapours/results/results_common.hpp
index a9a72505b..a013d7c9d 100644
--- a/libraries/libvapours/include/vapours/results/results_common.hpp
+++ b/libraries/libvapours/include/vapours/results/results_common.hpp
@@ -494,6 +494,14 @@ namespace ams::result::impl {
} \
}
+#define R_UNLESS_LOG(expr, res, ...) \
+ { \
+ if (!(expr)) { \
+ AMS_LOG(__VA_ARGS__); \
+ R_THROW(res); \
+ } \
+ }
+
/// Evaluates a boolean expression, and succeeds if that expression is true.
#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess())
diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp
index 276484824..f4dc57862 100644
--- a/stratosphere/loader/source/ldr_process_creation.cpp
+++ b/stratosphere/loader/source/ldr_process_creation.cpp
@@ -121,8 +121,7 @@ namespace ams::ldr {
NsoHeader g_nso_headers[Nso_Count];
/* Global Zstd decompression context. */
- constexpr size_t ZstdDctxWorkspaceSize = 0x176E8;
- alignas(8) u8 g_zstd_dctx_workspace[ZstdDctxWorkspaceSize];
+ alignas(8) u8 g_zstd_dctx_workspace[util::ZstdDctxWorkspaceSize];
Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) {
/* No version verification is done before 8.1.0. */
@@ -220,7 +219,7 @@ namespace ams::ldr {
/* Read NSO header. */
size_t read_size;
R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, g_nso_headers + ctx.nso_count, sizeof(NsoHeader)));
- R_UNLESS(read_size == sizeof(NsoHeader), ldr::ResultInvalidNso());
+ R_UNLESS_LOG(read_size == sizeof(NsoHeader), ldr::ResultInvalidNso(), "[ldr] NSO header truncated!\n");
/* Note nso is present. */
switch (i) {
@@ -259,7 +258,7 @@ namespace ams::ldr {
Result CheckAutoLoad(const AutoLoadModuleContext &ctx, u32 acid_flags) {
/* We must always have a main. */
- R_UNLESS(ctx.ali.has_main, ldr::ResultInvalidNso());
+ R_UNLESS_LOG(ctx.ali.has_main, ldr::ResultInvalidNso(), "[ldr] Missing main!\n");
/* Validate flags and extents for all present NSOs. */
for (int i = 0; i < ctx.nso_count; ++i) {
@@ -267,11 +266,11 @@ namespace ams::ldr {
/* All NSOs must not be --X. */
/* This is "probably" not checked on Ounce? */
- R_UNLESS((hdr.flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso());
+ R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] --x not allowed!\n", i);
/* Zstd compression only allowed on main, and only when both rtld+sdk are present. */
if (i != ctx.main_nso_idx || ctx.rtld_idx < 0 || ctx.sdk_nso_idx < 0) {
- R_UNLESS((hdr.flags & NsoHeader::Flag_UseZbicCompression) == 0, ldr::ResultInvalidNso());
+ R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_UseZbicCompression) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] zbic not allowed!\n", i);
}
/* NSOs must have page-aligned segments. */
@@ -294,13 +293,13 @@ namespace ams::ldr {
const bool has_browser_dll = (acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) != 0;
if (ctx.ali.has_rtld || ctx.ali.has_sdk) {
/* If we have sdk we must have rtld. */
- R_UNLESS(ctx.ali.has_rtld, ldr::ResultInvalidNso());
+ R_UNLESS_LOG(ctx.ali.has_rtld, ldr::ResultInvalidNso(), "[ldr] Missing rtld!\n");
/* If we have rtld, we must not have browser core dll. */
- R_UNLESS(!has_browser_dll, ldr::ResultInvalidNso());
+ R_UNLESS_LOG(!has_browser_dll, ldr::ResultInvalidNso(), "[ldr] BrowserCoreDll must not be present!\n");
} else {
/* We must not have both subsdk and browser dll. */
- R_UNLESS(!(ctx.ali.has_subsdk && has_browser_dll), ldr::ResultInvalidNso());
+ R_UNLESS_LOG(!(ctx.ali.has_subsdk && has_browser_dll), ldr::ResultInvalidNso(), "[ldr] Can't have both subsdk and BrowserCoreDll!\n");
}
R_SUCCEED();
@@ -385,6 +384,8 @@ namespace ams::ldr {
/* If the signature check fails, we need to check if this is allowable. */
if (!is_signature_valid) {
+ AMS_LOG("[ldr] invalid signature!\n");
+
/* We have to enforce signature checks on prod and when we have a signature to check on dev. */
R_UNLESS(IsDevelopmentForAcidProductionCheck(), ldr::ResultInvalidNcaSignature());
R_UNLESS(!code_verification_data.has_data, ldr::ResultInvalidNcaSignature());
@@ -635,10 +636,13 @@ namespace ams::ldr {
R_SUCCEED();
}
- Result LoadAutoLoadModuleSegment(fs::FileHandle file, size_t file_offset, size_t compressed_size, size_t segment_size, bool is_compressed, bool is_zstd, uintptr_t map_base, uintptr_t map_end) {
+ Result LoadAutoLoadModuleSegment(fs::FileHandle file, size_t file_offset, size_t compressed_size, size_t segment_size, bool is_compressed, bool is_zbic, uintptr_t map_base, uintptr_t map_end) {
/* Select read size based on compression. */
size_t file_size = is_compressed ? compressed_size : segment_size;
+ AMS_LOG("[ldr] Loading segment @ 0x%016lx: compressed=%d, file_size=0x%08lx, compressed_size=0x%08lx, segment_size=0x%08lx\n",
+ map_base, is_compressed, file_size, compressed_size, segment_size);
+
/* Validate size. */
R_UNLESS(file_size <= segment_size, ldr::ResultInvalidNso());
R_UNLESS(file_size <= std::numeric_limits::max(), ldr::ResultInvalidNso());
@@ -648,19 +652,19 @@ namespace ams::ldr {
uintptr_t load_address = is_compressed ? map_end - compressed_size : map_base;
size_t read_size;
R_TRY(fs::ReadFile(std::addressof(read_size), file, file_offset, reinterpret_cast(load_address), file_size));
- R_UNLESS(read_size == file_size, ldr::ResultInvalidNso());
+ R_UNLESS_LOG(read_size == file_size, ldr::ResultInvalidNso(), "[ldr] Couldn't read segment from file!\n");
/* Uncompress if necessary. */
R_SUCCEED_IF(!is_compressed);
auto compressed_data_buf = reinterpret_cast(load_address);
- if (is_zstd) {
- bool decompressed = util::DecompressZstdForLoader(reinterpret_cast(g_zstd_dctx_workspace), ZstdDctxWorkspaceSize, reinterpret_cast(map_base), static_cast(map_end - map_base), segment_size, compressed_data_buf, file_size);
- R_UNLESS(decompressed, ldr::ResultInvalidNso());
+ if (is_zbic) {
+ bool decompressed = util::DecompressZbicForLoader(reinterpret_cast(g_zstd_dctx_workspace), sizeof(g_zstd_dctx_workspace), reinterpret_cast(map_base), static_cast(map_end - map_base), segment_size, compressed_data_buf, file_size);
+ R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with zbic!\n");
} else {
bool decompressed = (util::DecompressLZ4(reinterpret_cast(map_base), segment_size, compressed_data_buf, file_size) == static_cast(segment_size));
- R_UNLESS(decompressed, ldr::ResultInvalidNso());
+ R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with lz4!\n");
}
R_SUCCEED();
@@ -675,12 +679,12 @@ namespace ams::ldr {
crypto::GenerateSha256(hash, sizeof(hash),
reinterpret_cast(map_address + nso_header->segments[segment].dst_offset),
nso_header->segments[segment].size);
- R_UNLESS(std::memcmp(hash, nso_header->segment_hashes[segment], sizeof(hash)) == 0, ldr::ResultInvalidNso());
+ R_UNLESS_LOG(std::memcmp(hash, nso_header->segment_hashes[segment], sizeof(hash)) == 0, ldr::ResultInvalidNso(), "[ldr] Invalid segment hash!\n");
R_SUCCEED();
}
Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size, size_t map_size) {
- const bool is_zstd = (nso_header->flags & NsoHeader::Flag_UseZbicCompression) != 0;
+ const bool is_zbic = (nso_header->flags & NsoHeader::Flag_UseZbicCompression) != 0;
/* Map and read data from file. */
{
@@ -694,11 +698,11 @@ namespace ams::ldr {
/* Load NSO segments. */
R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Text].file_offset, nso_header->text_compressed_size, nso_header->text_size,
- (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, is_zstd, map_address + nso_header->text_dst_offset, map_end));
+ (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, is_zbic, map_address + nso_header->text_dst_offset, map_end));
R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Ro].file_offset, nso_header->ro_compressed_size, nso_header->ro_size,
- (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, is_zstd, map_address + nso_header->ro_dst_offset, map_end));
+ (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, is_zbic, map_address + nso_header->ro_dst_offset, map_end));
R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Rw].file_offset, nso_header->rw_compressed_size, nso_header->rw_size,
- (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, is_zstd, map_address + nso_header->rw_dst_offset, map_end));
+ (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, is_zbic, map_address + nso_header->rw_dst_offset, map_end));
/* Clear unused space to zero. */
const size_t text_end = static_cast(nso_header->text_dst_offset) + static_cast(nso_header->text_size);
@@ -744,14 +748,15 @@ namespace ams::ldr {
for (int i = 0; i < ctx.nso_count; i++) {
const NsoIndex nso_idx = static_cast(ctx.ali.nso_indices[i]);
+ const bool is_zbic = (ctx.headers[i].flags & NsoHeader::Flag_UseZbicCompression) != 0;
+ const size_t map_size = is_zbic ? (total_end - process_info->nso_address[i]) : process_info->nso_size[i];
+
+ AMS_LOG("[ldr] module[%d]: idx=%d, path='%s', zbic=%d\n", i, (int)nso_idx, GetNsoPath(nso_idx), is_zbic);
fs::FileHandle file;
R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(nso_idx), fs::OpenMode_Read));
ON_SCOPE_EXIT { fs::CloseFile(file); };
- const bool is_zstd = (ctx.headers[i].flags & NsoHeader::Flag_UseZbicCompression) != 0;
- const size_t map_size = is_zstd ? (total_end - process_info->nso_address[i]) : process_info->nso_size[i];
-
R_TRY(LoadAutoLoadModule(process_info->process_handle, file, ctx.headers + i,
process_info->nso_address[i], process_info->nso_size[i], map_size));
}