mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2026-06-25 05:05:52 +00:00
Merge pull request #2817 from alula/fix-zbic-games
Fix zbic games + misc changes
This commit is contained in:
commit
10722de8b9
4
Makefile
4
Makefile
@ -13,6 +13,10 @@ $(strip $1):
|
|||||||
@echo "Building $(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)
|
@$$(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):
|
clean-$(strip $1):
|
||||||
@echo "Cleaning $(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)
|
@$$(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)
|
||||||
|
|||||||
@ -54,7 +54,7 @@ dist: dist-no-debug
|
|||||||
cp $(CURRENT_DIRECTORY)/troposphere/daybreak/daybreak.elf $(DIST_DIR)/daybreak.elf
|
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/haze/haze.elf $(DIST_DIR)/haze.elf
|
||||||
cp $(CURRENT_DIRECTORY)/troposphere/reboot_to_payload/reboot_to_payload.elf $(DIST_DIR)/reboot_to_payload.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)
|
rm -rf $(DIST_DIR)
|
||||||
|
|
||||||
dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||||
|
|||||||
@ -21,11 +21,13 @@ namespace ams::util {
|
|||||||
|
|
||||||
/* Compression utilities. */
|
/* Compression utilities. */
|
||||||
int CompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size);
|
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. */
|
/* Decompression utilities. */
|
||||||
int DecompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size);
|
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);
|
size_t DecompressZbic(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);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -104,25 +104,25 @@ namespace ams::pinmux::driver::board::nintendo::nx {
|
|||||||
#if defined(AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART)
|
#if defined(AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART)
|
||||||
UpdateSinglePinmuxPad({
|
UpdateSinglePinmuxPad({
|
||||||
.index = PinmuxPadIndex_Uart2Tx,
|
.index = PinmuxPadIndex_Uart2Tx,
|
||||||
.option = 0, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output */
|
.option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output,
|
||||||
.option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
|
.option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
|
||||||
});
|
});
|
||||||
UpdateSinglePinmuxPad({
|
UpdateSinglePinmuxPad({
|
||||||
.index = PinmuxPadIndex_Uart2Cts,
|
.index = PinmuxPadIndex_Uart2Cts,
|
||||||
.option = 0x20, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input */
|
.option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input,
|
||||||
.option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
|
.option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
#if defined(AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART)
|
#if defined(AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART)
|
||||||
UpdateSinglePinmuxPad({
|
UpdateSinglePinmuxPad({
|
||||||
.index = PinmuxPadIndex_Uart3Tx,
|
.index = PinmuxPadIndex_Uart3Tx,
|
||||||
.option = 0, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output */
|
.option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output,
|
||||||
.option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
|
.option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
|
||||||
});
|
});
|
||||||
UpdateSinglePinmuxPad({
|
UpdateSinglePinmuxPad({
|
||||||
.index = PinmuxPadIndex_Uart3Cts,
|
.index = PinmuxPadIndex_Uart3Cts,
|
||||||
.option = 0x20, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input */
|
.option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input,
|
||||||
.option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */
|
.option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir,
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,170 +24,6 @@ namespace ams::pinmux::driver::board::nintendo::nx {
|
|||||||
|
|
||||||
uintptr_t g_apb_misc_virtual_address = dd::QueryIoMapping(0x70000000, 0x4000);
|
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 {
|
struct PinmuxPadCharacter {
|
||||||
u32 reg_offset;
|
u32 reg_offset;
|
||||||
u32 reg_mask;
|
u32 reg_mask;
|
||||||
|
|||||||
@ -30,6 +30,170 @@ namespace ams::pinmux::driver::board::nintendo::nx {
|
|||||||
u32 option_mask;
|
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 InitializePlatformPads();
|
||||||
|
|
||||||
void UpdateSinglePinmuxPad(const PinmuxPadConfig &config);
|
void UpdateSinglePinmuxPad(const PinmuxPadConfig &config);
|
||||||
|
|||||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#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<int>::max());
|
||||||
|
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
||||||
|
|
||||||
|
/* This is just a thin wrapper around LZ4. */
|
||||||
|
return LZ4_compress_default(reinterpret_cast<const char *>(src), reinterpret_cast<char *>(dst), static_cast<int>(src_size), static_cast<int>(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<int>::max());
|
||||||
|
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
||||||
|
|
||||||
|
/* This is just a thin wrapper around LZ4. */
|
||||||
|
return LZ4_decompress_safe(reinterpret_cast<const char *>(src), reinterpret_cast<char *>(dst), static_cast<int>(src_size), static_cast<int>(dst_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -17,21 +17,19 @@
|
|||||||
#include "lz4.h"
|
#include "lz4.h"
|
||||||
#define ZSTD_STATIC_LINKING_ONLY
|
#define ZSTD_STATIC_LINKING_ONLY
|
||||||
#define ZSTD_ZBIC_SUPPORT 1
|
#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.h"
|
||||||
|
#include "zstd.inc"
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
namespace ams::util {
|
namespace ams::util {
|
||||||
|
static_assert(sizeof(ZSTD_DCtx) <= ZstdDctxWorkspaceSize);
|
||||||
|
|
||||||
/* Compression utilities. */
|
size_t CompressZbic(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||||
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<int>::max());
|
|
||||||
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
|
||||||
|
|
||||||
/* This is just a thin wrapper around LZ4. */
|
|
||||||
return LZ4_compress_default(reinterpret_cast<const char *>(src), reinterpret_cast<char *>(dst), static_cast<int>(src_size), static_cast<int>(dst_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CompressZstd(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
|
||||||
/* Basic size checks. */
|
/* Basic size checks. */
|
||||||
AMS_ABORT_UNLESS(dst_size <= std::numeric_limits<int>::max());
|
AMS_ABORT_UNLESS(dst_size <= std::numeric_limits<int>::max());
|
||||||
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
||||||
@ -47,18 +45,8 @@ namespace ams::util {
|
|||||||
/* This is just a wrapper around Zstd. */
|
/* This is just a wrapper around Zstd. */
|
||||||
return ZSTD_compress(dst, dst_size, src, src_size, compressionLevel);
|
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<int>::max());
|
|
||||||
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
|
||||||
|
|
||||||
/* This is just a thin wrapper around LZ4. */
|
|
||||||
return LZ4_decompress_safe(reinterpret_cast<const char *>(src), reinterpret_cast<char *>(dst), static_cast<int>(src_size), static_cast<int>(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. */
|
/* Basic size checks. */
|
||||||
AMS_ABORT_UNLESS(dst_size <= std::numeric_limits<int>::max());
|
AMS_ABORT_UNLESS(dst_size <= std::numeric_limits<int>::max());
|
||||||
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
||||||
@ -72,10 +60,12 @@ namespace ams::util {
|
|||||||
return ZSTD_decompress(dst, dst_size, src, src_size);
|
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. */
|
/* Check decompression margin. */
|
||||||
auto margin = ZSTD_decompressionMargin(src, src_size);
|
auto margin = ZSTD_decompressionMargin(src, src_size);
|
||||||
if (ZSTD_isError(margin)) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,17 +76,20 @@ namespace ams::util {
|
|||||||
|
|
||||||
/* Make sure we fit in the destination buffer. */
|
/* Make sure we fit in the destination buffer. */
|
||||||
if (margin + expected_dec_size > dst_size) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a runtime assert in Loader code. We replicate it here. */
|
/* This is a runtime assert in Loader code. Note that Nintendo does == comparison here. */
|
||||||
AMS_ABORT_UNLESS(ZSTD_estimateDCtxSize() == workspace_size);
|
AMS_ABORT_UNLESS(ZSTD_estimateDCtxSize() <= workspace_size);
|
||||||
|
|
||||||
/* Decompress using a static decompression context. */
|
/* Decompress using a static decompression context. */
|
||||||
auto dctx = ZSTD_initStaticDCtx(workspace, workspace_size);
|
auto dctx = ZSTD_initStaticDCtx(workspace, workspace_size);
|
||||||
size_t dec_size = ZSTD_decompressDCtx(dctx, dst, dst_size, src, src_size);
|
size_t dec_size = ZSTD_decompressDCtx(dctx, dst, dst_size, src, src_size);
|
||||||
|
|
||||||
if (ZSTD_isError(dec_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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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.
|
/// Evaluates a boolean expression, and succeeds if that expression is true.
|
||||||
#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess())
|
#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess())
|
||||||
|
|
||||||
|
|||||||
@ -121,8 +121,7 @@ namespace ams::ldr {
|
|||||||
NsoHeader g_nso_headers[Nso_Count];
|
NsoHeader g_nso_headers[Nso_Count];
|
||||||
|
|
||||||
/* Global Zstd decompression context. */
|
/* Global Zstd decompression context. */
|
||||||
constexpr size_t ZstdDctxWorkspaceSize = 0x176E8;
|
alignas(8) u8 g_zstd_dctx_workspace[util::ZstdDctxWorkspaceSize];
|
||||||
alignas(8) u8 g_zstd_dctx_workspace[ZstdDctxWorkspaceSize];
|
|
||||||
|
|
||||||
Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) {
|
Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) {
|
||||||
/* No version verification is done before 8.1.0. */
|
/* No version verification is done before 8.1.0. */
|
||||||
@ -220,7 +219,7 @@ namespace ams::ldr {
|
|||||||
/* Read NSO header. */
|
/* Read NSO header. */
|
||||||
size_t read_size;
|
size_t read_size;
|
||||||
R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, g_nso_headers + ctx.nso_count, sizeof(NsoHeader)));
|
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. */
|
/* Note nso is present. */
|
||||||
switch (i) {
|
switch (i) {
|
||||||
@ -259,7 +258,7 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
Result CheckAutoLoad(const AutoLoadModuleContext &ctx, u32 acid_flags) {
|
Result CheckAutoLoad(const AutoLoadModuleContext &ctx, u32 acid_flags) {
|
||||||
/* We must always have a main. */
|
/* 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. */
|
/* Validate flags and extents for all present NSOs. */
|
||||||
for (int i = 0; i < ctx.nso_count; ++i) {
|
for (int i = 0; i < ctx.nso_count; ++i) {
|
||||||
@ -267,11 +266,11 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
/* All NSOs must not be --X. */
|
/* All NSOs must not be --X. */
|
||||||
/* This is "probably" not checked on Ounce? */
|
/* 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. */
|
/* 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) {
|
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. */
|
/* NSOs must have page-aligned segments. */
|
||||||
@ -294,13 +293,13 @@ namespace ams::ldr {
|
|||||||
const bool has_browser_dll = (acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) != 0;
|
const bool has_browser_dll = (acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) != 0;
|
||||||
if (ctx.ali.has_rtld || ctx.ali.has_sdk) {
|
if (ctx.ali.has_rtld || ctx.ali.has_sdk) {
|
||||||
/* If we have sdk we must have rtld. */
|
/* 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. */
|
/* 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 {
|
} else {
|
||||||
/* We must not have both subsdk and browser dll. */
|
/* 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();
|
R_SUCCEED();
|
||||||
@ -385,6 +384,8 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
/* If the signature check fails, we need to check if this is allowable. */
|
/* If the signature check fails, we need to check if this is allowable. */
|
||||||
if (!is_signature_valid) {
|
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. */
|
/* 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(IsDevelopmentForAcidProductionCheck(), ldr::ResultInvalidNcaSignature());
|
||||||
R_UNLESS(!code_verification_data.has_data, ldr::ResultInvalidNcaSignature());
|
R_UNLESS(!code_verification_data.has_data, ldr::ResultInvalidNcaSignature());
|
||||||
@ -635,10 +636,13 @@ namespace ams::ldr {
|
|||||||
R_SUCCEED();
|
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. */
|
/* Select read size based on compression. */
|
||||||
size_t file_size = is_compressed ? compressed_size : segment_size;
|
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. */
|
/* Validate size. */
|
||||||
R_UNLESS(file_size <= segment_size, ldr::ResultInvalidNso());
|
R_UNLESS(file_size <= segment_size, ldr::ResultInvalidNso());
|
||||||
R_UNLESS(file_size <= std::numeric_limits<s32>::max(), ldr::ResultInvalidNso());
|
R_UNLESS(file_size <= std::numeric_limits<s32>::max(), ldr::ResultInvalidNso());
|
||||||
@ -648,19 +652,19 @@ namespace ams::ldr {
|
|||||||
uintptr_t load_address = is_compressed ? map_end - compressed_size : map_base;
|
uintptr_t load_address = is_compressed ? map_end - compressed_size : map_base;
|
||||||
size_t read_size;
|
size_t read_size;
|
||||||
R_TRY(fs::ReadFile(std::addressof(read_size), file, file_offset, reinterpret_cast<void *>(load_address), file_size));
|
R_TRY(fs::ReadFile(std::addressof(read_size), file, file_offset, reinterpret_cast<void *>(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. */
|
/* Uncompress if necessary. */
|
||||||
R_SUCCEED_IF(!is_compressed);
|
R_SUCCEED_IF(!is_compressed);
|
||||||
|
|
||||||
auto compressed_data_buf = reinterpret_cast<const void *>(load_address);
|
auto compressed_data_buf = reinterpret_cast<const void *>(load_address);
|
||||||
|
|
||||||
if (is_zstd) {
|
if (is_zbic) {
|
||||||
bool decompressed = util::DecompressZstdForLoader(reinterpret_cast<void *>(g_zstd_dctx_workspace), ZstdDctxWorkspaceSize, reinterpret_cast<void *>(map_base), static_cast<size_t>(map_end - map_base), segment_size, compressed_data_buf, file_size);
|
bool decompressed = util::DecompressZbicForLoader(reinterpret_cast<void *>(g_zstd_dctx_workspace), sizeof(g_zstd_dctx_workspace), reinterpret_cast<void *>(map_base), static_cast<size_t>(map_end - map_base), segment_size, compressed_data_buf, file_size);
|
||||||
R_UNLESS(decompressed, ldr::ResultInvalidNso());
|
R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with zbic!\n");
|
||||||
} else {
|
} else {
|
||||||
bool decompressed = (util::DecompressLZ4(reinterpret_cast<void *>(map_base), segment_size, compressed_data_buf, file_size) == static_cast<int>(segment_size));
|
bool decompressed = (util::DecompressLZ4(reinterpret_cast<void *>(map_base), segment_size, compressed_data_buf, file_size) == static_cast<int>(segment_size));
|
||||||
R_UNLESS(decompressed, ldr::ResultInvalidNso());
|
R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with lz4!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -675,12 +679,12 @@ namespace ams::ldr {
|
|||||||
crypto::GenerateSha256(hash, sizeof(hash),
|
crypto::GenerateSha256(hash, sizeof(hash),
|
||||||
reinterpret_cast<void *>(map_address + nso_header->segments[segment].dst_offset),
|
reinterpret_cast<void *>(map_address + nso_header->segments[segment].dst_offset),
|
||||||
nso_header->segments[segment].size);
|
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();
|
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) {
|
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. */
|
/* Map and read data from file. */
|
||||||
{
|
{
|
||||||
@ -694,11 +698,11 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
/* Load NSO segments. */
|
/* Load NSO segments. */
|
||||||
R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Text].file_offset, nso_header->text_compressed_size, nso_header->text_size,
|
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,
|
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,
|
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. */
|
/* Clear unused space to zero. */
|
||||||
const size_t text_end = static_cast<size_t>(nso_header->text_dst_offset) + static_cast<size_t>(nso_header->text_size);
|
const size_t text_end = static_cast<size_t>(nso_header->text_dst_offset) + static_cast<size_t>(nso_header->text_size);
|
||||||
@ -744,14 +748,15 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
for (int i = 0; i < ctx.nso_count; i++) {
|
for (int i = 0; i < ctx.nso_count; i++) {
|
||||||
const NsoIndex nso_idx = static_cast<NsoIndex>(ctx.ali.nso_indices[i]);
|
const NsoIndex nso_idx = static_cast<NsoIndex>(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;
|
fs::FileHandle file;
|
||||||
R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(nso_idx), fs::OpenMode_Read));
|
R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(nso_idx), fs::OpenMode_Read));
|
||||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
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,
|
R_TRY(LoadAutoLoadModule(process_info->process_handle, file, ctx.headers + i,
|
||||||
process_info->nso_address[i], process_info->nso_size[i], map_size));
|
process_info->nso_address[i], process_info->nso_size[i], map_size));
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user