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)"
|
||||
@$$(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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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"
|
||||
#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<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) {
|
||||
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<int>::max());
|
||||
AMS_ABORT_UNLESS(src_size <= std::numeric_limits<int>::max());
|
||||
@ -48,17 +46,7 @@ namespace ams::util {
|
||||
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. */
|
||||
AMS_ABORT_UNLESS(dst_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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
|
||||
@ -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<s32>::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<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. */
|
||||
R_SUCCEED_IF(!is_compressed);
|
||||
|
||||
auto compressed_data_buf = reinterpret_cast<const void *>(load_address);
|
||||
|
||||
if (is_zstd) {
|
||||
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);
|
||||
R_UNLESS(decompressed, ldr::ResultInvalidNso());
|
||||
if (is_zbic) {
|
||||
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_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with zbic!\n");
|
||||
} else {
|
||||
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();
|
||||
@ -675,12 +679,12 @@ namespace ams::ldr {
|
||||
crypto::GenerateSha256(hash, sizeof(hash),
|
||||
reinterpret_cast<void *>(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<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++) {
|
||||
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;
|
||||
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));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user