Compare commits

...

56 Commits

Author SHA1 Message Date
hexkyz
3ace80cc7b loader/util: support regular zstd alongside zbic 2026-06-24 22:08:13 +01:00
hexkyz
10722de8b9 Merge pull request #2817 from alula/fix-zbic-games
Fix zbic games + misc changes
2026-06-24 20:32:18 +01:00
Alula
59846adcb7 ams: fix a copy paste mistake in makefile 2026-06-24 21:01:43 +02:00
Alula
94e62a7b1b loader: add non-release build debug logging 2026-06-24 20:54:42 +02:00
Alula
fbeea26919 ams: add R_UNLESS_LOG() 2026-06-24 20:51:39 +02:00
Alula
38251801df loader/strat: fix/refactor zstd-zbic integration 2026-06-24 20:50:41 +02:00
Alula
7b6ee4916e pinmux: use the actual option definitions instead of magic numbers 2026-06-24 20:46:23 +02:00
Alula
556e628478 ams: add dist-no-debug targets to main makefile 2026-06-23 16:10:39 +02:00
hexkyz
5388824be1 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "d3083af18"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "d3083af18"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 22:11:17 +01:00
hexkyz
974a1025b8 erpt: add new ID for 22.5.0 2026-06-16 22:10:07 +01:00
hexkyz
9d21cfca4c git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "f6b3a28ec"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "f6b3a28ec"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:21:53 +01:00
hexkyz
1478f3443e emummc: update readme for 22.5.0 2026-06-16 21:21:24 +01:00
hexkyz
f527e7fc48 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "24946ac76"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "24946ac76"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:17:37 +01:00
hexkyz
7dccf3bffa git subrepo pull (merge) emummc
subrepo:
  subdir:   "emummc"
  merged:   "6cecd09b2"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "bde9957f1"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:17:11 +01:00
hexkyz
4ea042510b git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "e4100b5f5"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "e4100b5f5"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:15:53 +01:00
hexkyz
d97f520058 docs: add gcc16 to changelog 2026-06-16 21:12:42 +01:00
hexkyz
3a3a2ca99b ams: basic support for compiling with gcc 16 2026-06-16 21:10:23 +01:00
hexkyz
fcd46b4419 docs: add changelog for 1.11.2 2026-06-16 19:32:59 +01:00
hexkyz
c046eeacdd meso: fix longstanding bad asm copy-paste 2026-06-16 19:22:54 +01:00
hexkyz
4181169f80 emummc: update for 22.5.0 2026-06-16 19:18:26 +01:00
hexkyz
47cfe05bb0 loader: update USB 3.0 patches for 22.5.0 2026-06-16 18:51:10 +01:00
hexkyz
c497ffda75 ams: add enum recognition for 22.5.0 2026-06-16 18:41:32 +01:00
hexkyz
15c434f185 Merge pull request #2811 from ZachyCatGames/patch-1
pgl: GetHostContentMetaInfo returns a ncm::ContentMetaType
2026-05-30 00:32:39 +01:00
Zachary Kirtz
7d38bf16cd pgl: GetHostContentMetaInfo returns a ncm::ContentMetaType 2026-05-29 01:16:11 -05:00
hexkyz
2c7e2bfaae Merge pull request #2800 from masagrator/patch-1
fs.mitm: Add "Until Then" as another game which needs stolen heap for layeredfs
2026-04-25 19:55:43 +01:00
MasaGratoR
e655fd4b01 fs.mitm: Add "Until Then" as another game which needs stolen heap for layeredfs 2026-04-24 22:30:25 +02:00
hexkyz
022000f668 docs: add changelog for 1.11.1
this was missing from the usual enum recognition changes
synchronization will happen at a future release instead
2026-04-07 22:53:21 +01:00
hexkyz
d04c20a049 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "82f1553c4"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "82f1553c4"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-04-07 17:24:31 +01:00
hexkyz
252f8685b4 Merge pull request #2786 from alula/alula
ams: add enum recognition for 22.1.0
2026-04-07 17:22:46 +01:00
Alula
020ed307b1 ams: add enum recognition for 22.1.0 2026-04-07 03:22:37 +02:00
hexkyz
d9e1d799ab git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "3726bfd65"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "3726bfd65"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-04-05 20:34:44 +01:00
ndeadly
80bd459516 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "8e9c9ab16"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "8e9c9ab16"
git-subrepo:
  version:  "0.4.9"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "5e0f401"
2026-04-04 16:44:08 +02:00
hexkyz
931e3c37fd docs: add changelog for 1.11.0 2026-04-03 23:34:13 +01:00
hexkyz
4b4db91341 pgl: no need to initialize lr services when already using our own 2026-04-03 23:32:15 +01:00
hexkyz
e3fc339fe5 Merge pull request #2766 from alula/erpt-crash-fix
erpt: Fix rare aborts caused by ResultInvalidPowerState
2026-04-03 23:09:55 +01:00
Alula
a051c3c723 erpt: document unknown 0x20000 flag 2026-04-04 00:06:49 +02:00
Alula
9a1ea02c8c erpt: Add some missed 20.0.0+ FsInfo changes 2026-04-04 00:06:49 +02:00
hexkyz
bae1ad22ec Merge pull request #2768 from masagrator/patch-1
Update services in PGL to match 21.0.0
2026-04-03 22:33:28 +01:00
hexkyz
cd1503a9ca emummc: fix offsets
22.0.0 now boots under emummc
2026-04-03 22:31:19 +01:00
Alula
72e3b0dd34 erpt: Fix rare aborts caused by ResultInvalidPowerState 2026-04-03 22:55:09 +02:00
MasaGratoR
ac120cf84b Match 21.0.0 FW 2026-04-03 22:23:08 +02:00
MasaGratoR
97ffad2ab6 Update service access to match 21.0.0 2026-04-03 22:22:15 +02:00
hexkyz
c8d68a3a8a Merge pull request #2763 from masagrator/patch-1
Fix off by 1 bug + allocation error + missing initialize in PGL
2026-04-03 19:27:56 +01:00
hexkyz
8987d642d1 Merge pull request #2748 from CTCaer/auto_dram_cfg
[Feature] Auto dram cfg & Auto memory mode
2026-04-03 19:27:38 +01:00
hexkyz
7ffb1da2ac Merge pull request #2734 from ndeadly/r_discard
libvapours: add R_DISCARD macro
2026-04-03 19:27:19 +01:00
hexkyz
5c426bf90d loader: remove unused file 2026-04-03 19:09:28 +01:00
MasaGratoR
31ca20f3b7 Add missing libstratosphere lr::Initialize() 2026-04-02 21:09:15 +02:00
MasaGratoR
174da786e4 Override new and delete operators 2026-04-02 20:45:30 +02:00
MasaGratoR
4a8f7628c2 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:44:08 +02:00
MasaGratoR
9d16ee6a74 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:41:25 +02:00
MasaGratoR
3b9ee08c69 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:33:27 +02:00
MasaGratoR
2694f31eb3 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:31:47 +02:00
MasaGratoR
f3f1fa46ed Fix off by 1 bug 2026-04-01 20:17:52 +02:00
CTCaer
5dd9816e3c exosphere: allow memory mode to be used on retail 2026-03-19 16:35:36 +02:00
CTCaer
5a5d9b206b exosphere: automatically adjust dram id if needed
Checks if programmed memory size matches the one from fused dram id.
If not, adjust it properly so PCV can do proper training and not crash.
2026-03-19 16:32:12 +02:00
ndeadly
f8a5a6c015 libvapours: add R_DISCARD macro 2026-02-23 01:09:11 +01:00
51 changed files with 749 additions and 304 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -15,6 +15,13 @@
# Desc: Controls whether userland has access to the PMU registers. # Desc: Controls whether userland has access to the PMU registers.
# NOTE: It is unknown what effects this has on official code. # NOTE: It is unknown what effects this has on official code.
# Key: enable_mem_mode, default: 0.
# Desc: Controls whether boot config memory mode is taken into account
# for retail units. This does not affect development units.
# NOTE: On retail units max ram size is capped to 4GB.
# Enabling this will use the boot config memory mode parameter,
# which by default is auto and size gets set based on physical size.
# Key: blank_prodinfo_sysmmc, default: 0. # Key: blank_prodinfo_sysmmc, default: 0.
# Desc: Controls whether PRODINFO should be blanked in sysmmc. # Desc: Controls whether PRODINFO should be blanked in sysmmc.
# This will cause the system to see dummied out keys and # This will cause the system to see dummied out keys and
@@ -51,6 +58,7 @@ debugmode=1
debugmode_user=0 debugmode_user=0
disable_user_exception_handlers=0 disable_user_exception_handlers=0
enable_user_pmu_access=0 enable_user_pmu_access=0
enable_mem_mode=0
blank_prodinfo_sysmmc=0 blank_prodinfo_sysmmc=0
blank_prodinfo_emummc=0 blank_prodinfo_emummc=0
allow_writing_to_cal_sysmmc=0 allow_writing_to_cal_sysmmc=0

View File

@@ -1,4 +1,29 @@
# Changelog # Changelog
## 1.11.2
+ Basic support was added for 22.5.0.
+ Atmosphère was updated to use GCC 16/newlib (latest devkitA64/devkitARM releases).
+ General system stability improvements to enhance the user's experience.
## 1.11.1
+ Basic support was added for 22.1.0.
+ General system stability improvements to enhance the user's experience.
## 1.11.0
+ Support was added for 22.0.0.
+ Special thanks to @alula for handling a large chunk of the necessary kernel, loader and erpt changes.
+ The console should boot and atmosphère should be fully functional.
+ **Please note**: A change in how applications/applets' lifespan is managed broke the homebrew ecosystem.
+ All applications and applets are expected to perform a clean exit by calling the relevant IPC commands.
+ Homebrew compiled with libnx and hbmenu itself explicitly avoid exiting so it can keep using the same process.
+ Properly fixing this would require a re-design of how homebrew is launched and terminated.
+ As a temporary solution, patches to the `am` sysmodule are now included which allow restoring the previous behavior and regain homebrew compatibility without any further changes.
+ Nonetheless, please report any issues you may face when testing homebrew to ensure no edge cases have been missed.
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `loader` was updated to reflect the latest official behavior.
+ `erpt` was updated to reflect the latest official behavior.
+ `pgl` was updated to fix a few issues.
+ Support was added for memory modes above 4GB (thanks @CTCaer).
+ A build time option to configure Joy-Con rails as UART for debugging was added (thanks @alula).
+ General system stability improvements to enhance the user's experience.
## 1.10.2 ## 1.10.2
+ Basic support was added for 21.2.0. + Basic support was added for 21.2.0.
+ General system stability improvements to enhance the user's experience. + General system stability improvements to enhance the user's experience.

6
emummc/.gitrepo vendored
View File

@@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/m4xw/emummc remote = https://github.com/m4xw/emummc
branch = develop branch = develop
commit = 8ab963b0b1c24b68de8e0c98c62c7822a9765bf3 commit = f6b3a28ecea9834f96151a526de66abd11033b70
parent = 1e88f37892555da4c38ca6c95f43c56cc6bb87e6 parent = 1478f3443e8f04534edac8c15bf2d504663d0384
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.9

2
emummc/README.md vendored
View File

@@ -2,7 +2,7 @@
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw*** *A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
### Supported Horizon Versions ### Supported Horizon Versions
**1.0.0 - 21.2.0** **1.0.0 - 22.5.0**
## Features ## Features
* Arbitrary SDMMC backend selection * Arbitrary SDMMC backend selection

View File

@@ -85,6 +85,8 @@
#include "offsets/2120_exfat.h" #include "offsets/2120_exfat.h"
#include "offsets/2200.h" #include "offsets/2200.h"
#include "offsets/2200_exfat.h" #include "offsets/2200_exfat.h"
#include "offsets/2250.h"
#include "offsets/2250_exfat.h"
#include "../utils/fatal.h" #include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers #define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -181,6 +183,8 @@ DEFINE_OFFSET_STRUCT(_2120);
DEFINE_OFFSET_STRUCT(_2120_EXFAT); DEFINE_OFFSET_STRUCT(_2120_EXFAT);
DEFINE_OFFSET_STRUCT(_2200); DEFINE_OFFSET_STRUCT(_2200);
DEFINE_OFFSET_STRUCT(_2200_EXFAT); DEFINE_OFFSET_STRUCT(_2200_EXFAT);
DEFINE_OFFSET_STRUCT(_2250);
DEFINE_OFFSET_STRUCT(_2250_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) { const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) { switch (version) {
@@ -322,6 +326,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_2200)); return &(GET_OFFSET_STRUCT_NAME(_2200));
case FS_VER_22_0_0_EXFAT: case FS_VER_22_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_2200_EXFAT)); return &(GET_OFFSET_STRUCT_NAME(_2200_EXFAT));
case FS_VER_22_5_0:
return &(GET_OFFSET_STRUCT_NAME(_2250));
case FS_VER_22_5_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_2250_EXFAT));
default: default:
fatal_abort(Fatal_UnknownVersion); fatal_abort(Fatal_UnknownVersion);
} }

View File

@@ -125,6 +125,9 @@ enum FS_VER
FS_VER_22_0_0, FS_VER_22_0_0,
FS_VER_22_0_0_EXFAT, FS_VER_22_0_0_EXFAT,
FS_VER_22_5_0,
FS_VER_22_5_0_EXFAT,
FS_VER_MAX, FS_VER_MAX,
}; };

View File

@@ -31,7 +31,7 @@
#define FS_OFFSET_2200_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260 #define FS_OFFSET_2200_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260
// Misc funcs // Misc funcs
#define FS_OFFSET_2200_LOCK_MUTEX 0x1CF260 #define FS_OFFSET_2200_LOCK_MUTEX 0x1A4EF0
#define FS_OFFSET_2200_UNLOCK_MUTEX 0x1A4F40 #define FS_OFFSET_2200_UNLOCK_MUTEX 0x1A4F40
#define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0 #define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0

View File

@@ -31,7 +31,7 @@
#define FS_OFFSET_2200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450 #define FS_OFFSET_2200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450
// Misc funcs // Misc funcs
#define FS_OFFSET_2200_EXFAT_LOCK_MUTEX 0x1DA450 #define FS_OFFSET_2200_EXFAT_LOCK_MUTEX 0x1B00E0
#define FS_OFFSET_2200_EXFAT_UNLOCK_MUTEX 0x1B0130 #define FS_OFFSET_2200_EXFAT_UNLOCK_MUTEX 0x1B0130
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B72A0 #define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B72A0

59
emummc/source/FS/offsets/2250.h vendored Normal file
View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-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/>.
*/
#ifndef __FS_2250_H__
#define __FS_2250_H__
// Accessor vtable getters
#define FS_OFFSET_2250_SDMMC_ACCESSOR_GC 0x1B01C0
#define FS_OFFSET_2250_SDMMC_ACCESSOR_SD 0x1B21C0
#define FS_OFFSET_2250_SDMMC_ACCESSOR_NAND 0x1B07F0
// Hooks
#define FS_OFFSET_2250_SDMMC_WRAPPER_READ 0x1AC0F0
#define FS_OFFSET_2250_SDMMC_WRAPPER_WRITE 0x1AC150
#define FS_OFFSET_2250_RTLD 0x2DED0
#define FS_OFFSET_2250_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2250_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260
// Misc funcs
#define FS_OFFSET_2250_LOCK_MUTEX 0x1A4EF0
#define FS_OFFSET_2250_UNLOCK_MUTEX 0x1A4F40
#define FS_OFFSET_2250_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0
#define FS_OFFSET_2250_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1AC0D0
// Misc Data
#define FS_OFFSET_2250_SD_MUTEX 0xFF1408
#define FS_OFFSET_2250_NAND_MUTEX 0xFECD00
#define FS_OFFSET_2250_ACTIVE_PARTITION 0xFECD40
#define FS_OFFSET_2250_SDMMC_DAS_HANDLE 0xFCEB98
// NOPs
#define FS_OFFSET_2250_SD_DAS_INIT 0x2B438
// Nintendo Paths
#define FS_OFFSET_2250_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x000715EC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00082E64, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008B888, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000A1B1C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2250_H__

59
emummc/source/FS/offsets/2250_exfat.h vendored Normal file
View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-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/>.
*/
#ifndef __FS_2250_EXFAT_H__
#define __FS_2250_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_2250_EXFAT_SDMMC_ACCESSOR_GC 0x1BB3B0
#define FS_OFFSET_2250_EXFAT_SDMMC_ACCESSOR_SD 0x1BD3B0
#define FS_OFFSET_2250_EXFAT_SDMMC_ACCESSOR_NAND 0x1BB9E0
// Hooks
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_READ 0x1B72E0
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_WRITE 0x1B7340
#define FS_OFFSET_2250_EXFAT_RTLD 0x2DED0
#define FS_OFFSET_2250_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2250_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450
// Misc funcs
#define FS_OFFSET_2250_EXFAT_LOCK_MUTEX 0x1B00E0
#define FS_OFFSET_2250_EXFAT_UNLOCK_MUTEX 0x1B0130
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B72A0
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B72C0
// Misc Data
#define FS_OFFSET_2250_EXFAT_SD_MUTEX 0x1002408
#define FS_OFFSET_2250_EXFAT_NAND_MUTEX 0xFFDD00
#define FS_OFFSET_2250_EXFAT_ACTIVE_PARTITION 0xFFDD40
#define FS_OFFSET_2250_EXFAT_SDMMC_DAS_HANDLE 0xFDBB98
// NOPs
#define FS_OFFSET_2250_EXFAT_SD_DAS_INIT 0x2B438
// Nintendo Paths
#define FS_OFFSET_2250_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x000715EC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00082E64, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008B888, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000A1B1C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2250_EXFAT_H__

View File

@@ -132,10 +132,13 @@ namespace ams::secmon::smc {
} }
u32 GetMemoryMode() { u32 GetMemoryMode() {
/* Unless development function is enabled, we're 4 GB. */ /* Unless development function or forced boot config memory size is enabled, we're 4 GB. */
u32 memory_mode = pkg1::MemoryMode_4GB; u32 memory_mode = pkg1::MemoryMode_4GB;
if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) { const auto &bcd = GetBootConfig().data;
const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */
if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) {
memory_mode = GetMemoryMode(bcd.GetMemoryMode()); memory_mode = GetMemoryMode(bcd.GetMemoryMode());
} }
@@ -146,17 +149,19 @@ namespace ams::secmon::smc {
pkg1::MemorySize memory_size = pkg1::MemorySize_4GB; pkg1::MemorySize memory_size = pkg1::MemorySize_4GB;
util::BitPack32 value = {}; util::BitPack32 value = {};
if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) { const auto &bcd = GetBootConfig().data;
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode())); const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */
if (bcd.IsDevelopmentFunctionEnabled()) {
value.Set<KernelConfiguration::Flags1>(bcd.GetKernelFlags1()); value.Set<KernelConfiguration::Flags1>(bcd.GetKernelFlags1());
value.Set<KernelConfiguration::Flags0>(bcd.GetKernelFlags0()); value.Set<KernelConfiguration::Flags0>(bcd.GetKernelFlags0());
} }
value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size); if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) {
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode()));
}
/* Exosphere extensions. */ value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size);
const auto &sc = GetSecmonConfiguration();
if (!sc.DisableUserModeExceptionHandlers()) { if (!sc.DisableUserModeExceptionHandlers()) {
value.Set<KernelConfiguration::EnableUserExceptionHandlers>(true); value.Set<KernelConfiguration::EnableUserExceptionHandlers>(true);
@@ -169,6 +174,27 @@ namespace ams::secmon::smc {
return value.value; return value.value;
} }
fuse::DramId GetDramIdAdjusted() {
const auto dram_id = fuse::GetDramId();
AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count);
const auto fuse_mem_size = DramIdToMemorySize[dram_id];
const auto phys_mem_size = GetPhysicalMemorySize();
AMS_ABORT_UNLESS(fuse_mem_size <= phys_mem_size);
if (fuse_mem_size == phys_mem_size) {
return dram_id;
}
/* Adjust Dram ID to match density/ranks. */
if (GetSocType() == fuse::SocType_Erista) {
return fuse::DramId_IcosaSamsung6GB;
} else { /* fuse::SocType_Mariko */
return fuse::DramId_IowaSamsung1y8GBX;
}
}
constinit u64 g_payload_address = 0; constinit u64 g_payload_address = 0;
constinit bool g_set_true_target_firmware = false; constinit bool g_set_true_target_firmware = false;
@@ -178,7 +204,7 @@ namespace ams::secmon::smc {
args.r[1] = GetBootConfig().signed_data.IsProgramVerificationDisabled(); args.r[1] = GetBootConfig().signed_data.IsProgramVerificationDisabled();
break; break;
case ConfigItem::DramId: case ConfigItem::DramId:
args.r[1] = fuse::GetDramId(); args.r[1] = GetDramIdAdjusted(); /* Nintendo: fuse::GetDramId() */
break; break;
case ConfigItem::SecurityEngineInterruptNumber: case ConfigItem::SecurityEngineInterruptNumber:
args.r[1] = SecurityEngineUserInterruptId; args.r[1] = SecurityEngineUserInterruptId;
@@ -471,9 +497,18 @@ namespace ams::secmon::smc {
/* For exosphere's usage. */ /* For exosphere's usage. */
pkg1::MemorySize GetPhysicalMemorySize() { pkg1::MemorySize GetPhysicalMemorySize() {
const auto dram_id = fuse::GetDramId(); const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count); const u32 mem_size = reg::Read(MC + MC_EMEM_CFG) & 0x3FFF;
return DramIdToMemorySize[dram_id];
switch (mem_size >> 10) {
case 4:
default:
return pkg1::MemorySize_4GB;
case 6:
return pkg1::MemorySize_6GB;
case 8:
return pkg1::MemorySize_8GB;
}
} }
} }

View File

@@ -545,6 +545,12 @@ namespace ams::nxboot {
} else { } else {
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess; storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess;
} }
} else if (std::strcmp(entry.key, "enable_mem_mode") == 0) {
if (entry.value[0] == '1') {
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled;
} else {
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled;
}
} else if (std::strcmp(entry.key, "blank_prodinfo_sysmmc") == 0) { } else if (std::strcmp(entry.key, "blank_prodinfo_sysmmc") == 0) {
if (!emummc_enabled) { if (!emummc_enabled) {
if (entry.value[0] == '1') { if (entry.value[0] == '1') {

View File

@@ -195,6 +195,9 @@ namespace ams::nxboot {
FsVersion_22_0_0, FsVersion_22_0_0,
FsVersion_22_0_0_Exfat, FsVersion_22_0_0_Exfat,
FsVersion_22_5_0,
FsVersion_22_5_0_Exfat,
FsVersion_Count, FsVersion_Count,
}; };
@@ -302,6 +305,9 @@ namespace ams::nxboot {
{ 0xB7, 0xA2, 0x97, 0x39, 0xB7, 0xED, 0xDE, 0xFC }, /* FsVersion_22_0_0 */ { 0xB7, 0xA2, 0x97, 0x39, 0xB7, 0xED, 0xDE, 0xFC }, /* FsVersion_22_0_0 */
{ 0xFB, 0x0B, 0x68, 0xDB, 0x24, 0x03, 0xD1, 0x19 }, /* FsVersion_22_0_0_Exfat */ { 0xFB, 0x0B, 0x68, 0xDB, 0x24, 0x03, 0xD1, 0x19 }, /* FsVersion_22_0_0_Exfat */
{ 0x53, 0x6D, 0x93, 0x84, 0x69, 0xFE, 0x73, 0xBE }, /* FsVersion_22_5_0 */
{ 0xD4, 0x45, 0x28, 0x29, 0x5B, 0x41, 0x92, 0xBA }, /* FsVersion_22_5_0_Exfat */
}; };
const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) { const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) {
@@ -716,11 +722,13 @@ namespace ams::nxboot {
AddPatch(fs_meta, 0x18AD40, NogcPatch1, sizeof(NogcPatch1)); AddPatch(fs_meta, 0x18AD40, NogcPatch1, sizeof(NogcPatch1));
break; break;
case FsVersion_22_0_0: case FsVersion_22_0_0:
case FsVersion_22_5_0:
AddPatch(fs_meta, 0x1B023D, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x1B023D, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1B0255, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x1B0255, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x183060, NogcPatch1, sizeof(NogcPatch1)); AddPatch(fs_meta, 0x183060, NogcPatch1, sizeof(NogcPatch1));
break; break;
case FsVersion_22_0_0_Exfat: case FsVersion_22_0_0_Exfat:
case FsVersion_22_5_0_Exfat:
AddPatch(fs_meta, 0x1BB42D, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x1BB42D, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1BB445, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x1BB445, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x18E250, NogcPatch1, sizeof(NogcPatch1)); AddPatch(fs_meta, 0x18E250, NogcPatch1, sizeof(NogcPatch1));

View File

@@ -1356,6 +1356,9 @@ namespace ams::nxboot {
emc_zcal_wait_cnt_old &= ~0x7ff; emc_zcal_wait_cnt_old &= ~0x7ff;
emc_zcal_wait_cnt_new &= ~0x7ff; emc_zcal_wait_cnt_new &= ~0x7ff;
/* TODO: Unused variable. */
AMS_UNUSED(emc_zcal_wait_cnt_old);
if (dram_type == DRAM_TYPE_LPDDR4) { if (dram_type == DRAM_TYPE_LPDDR4) {
zq_wait_long = std::max<u32>(1, util::DivideUp(1000000, destination_clock_period)); zq_wait_long = std::max<u32>(1, util::DivideUp(1000000, destination_clock_period));
} else if (dram_type == DRAM_TYPE_LPDDR2 || is_lpddr3) { } else if (dram_type == DRAM_TYPE_LPDDR2 || is_lpddr3) {

View File

@@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master branch = master
commit = 9a8703e710760be8c88147d15414a1c581711625 commit = d3083af1827cd6ca2a96feb9316eb85cd01bae1f
parent = eb34f9789c62745d87f37e76761b14d946bac300 parent = 974a1025b834136134e8133d8db23f69cb5ae0be
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.9

View File

@@ -30,6 +30,7 @@ namespace ams::secmon {
SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5), SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5),
SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6), SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6),
SecureMonitorConfigurationFlag_ForceEnableUsb30 = (1u << 7), SecureMonitorConfigurationFlag_ForceEnableUsb30 = (1u << 7),
SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled = (1u << 8),
SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel, SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel,
}; };
@@ -103,6 +104,7 @@ namespace ams::secmon {
constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; } constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; }
constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags[0] & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; } constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags[0] & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; }
constexpr bool IsUsb30ForceEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ForceEnableUsb30) != 0; } constexpr bool IsUsb30ForceEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ForceEnableUsb30) != 0; }
constexpr bool IsBootConfigMemoryModeEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled) != 0; }
constexpr bool IsDevelopmentFunctionEnabled(bool for_kern) const { return for_kern ? this->IsDevelopmentFunctionEnabledForKernel() : this->IsDevelopmentFunctionEnabledForUser(); } constexpr bool IsDevelopmentFunctionEnabled(bool for_kern) const { return for_kern ? this->IsDevelopmentFunctionEnabledForKernel() : this->IsDevelopmentFunctionEnabledForUser(); }
}; };

View File

@@ -105,6 +105,9 @@ namespace ams::se {
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 1) : 0; value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 1) : 0;
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 2) : 0; value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 2) : 0;
/* TODO: Unused variable. */
AMS_UNUSED(value);
reg::Write(SE->SE_RSA_KEYTABLE_ACCESS[slot], SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYREAD, (flags & KeySlotLockFlags_KeyRead) != 0, DISABLE, ENABLE), reg::Write(SE->SE_RSA_KEYTABLE_ACCESS[slot], SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYREAD, (flags & KeySlotLockFlags_KeyRead) != 0, DISABLE, ENABLE),
SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUPDATE, (flags & KeySlotLockFlags_KeyWrite) != 0, DISABLE, ENABLE), SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUPDATE, (flags & KeySlotLockFlags_KeyWrite) != 0, DISABLE, ENABLE),
SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUSE, (flags & KeySlotLockFlags_KeyUse) != 0, DISABLE, ENABLE)); SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUSE, (flags & KeySlotLockFlags_KeyUse) != 0, DISABLE, ENABLE));

View File

@@ -730,6 +730,9 @@ namespace ams::kern::arch::arm64 {
} }
MESOSPHERE_ASSERT(mapped_pages == num_pages); MESOSPHERE_ASSERT(mapped_pages == num_pages);
/* TODO: Unused variable. */
AMS_UNUSED(mapped_pages);
/* Perform what coalescing we can. */ /* Perform what coalescing we can. */
this->MergePages(orig_virt_addr, num_pages, page_list); this->MergePages(orig_virt_addr, num_pages, page_list);

View File

@@ -682,7 +682,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl18WriteIoMemory32BitEPvPKvm:
mov x30, x10 mov x30, x10
/* Write the word to io. */ /* Write the word to io. */
sttr w9, [x5] sttr w9, [x4]
dsb sy dsb sy
2: /* Continue. */ 2: /* Continue. */
@@ -727,7 +727,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl18WriteIoMemory16BitEPvPKvm:
mov x30, x10 mov x30, x10
/* Write the word to io. */ /* Write the word to io. */
sttrh w9, [x5] sttrh w9, [x4]
dsb sy dsb sy
2: /* Continue. */ 2: /* Continue. */
@@ -772,7 +772,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl17WriteIoMemory8BitEPvPKvm:
mov x30, x10 mov x30, x10
/* Write the word to io. */ /* Write the word to io. */
sttrb w9, [x5] sttrb w9, [x4]
dsb sy dsb sy
2: /* Continue. */ 2: /* Continue. */

View File

@@ -757,11 +757,13 @@ namespace ams::kern {
{ {
MESOSPHERE_ASSERT(num_params >= 3); MESOSPHERE_ASSERT(num_params >= 3);
/* Keep the compiler happy, even though the assert has us covered. */
if (num_params >= 3) {
info->info.exception.exception_address = params[1]; info->info.exception.exception_address = params[1];
info->info.exception.exception_data_count = 1; info->info.exception.exception_data_count = 1;
info->info.exception.exception_data[0] = params[2]; info->info.exception.exception_data[0] = params[2];
} }
}
break; break;
case ams::svc::DebugException_DebuggerAttached: case ams::svc::DebugException_DebuggerAttached:
{ {
@@ -774,7 +776,10 @@ namespace ams::kern {
{ {
MESOSPHERE_ASSERT(num_params >= 2); MESOSPHERE_ASSERT(num_params >= 2);
/* Keep the compiler happy, even though the assert has us covered. */
if (num_params >= 2) {
info->info.exception.exception_address = params[1]; info->info.exception.exception_address = params[1];
}
info->info.exception.exception_data_count = 0; info->info.exception.exception_data_count = 0;
for (size_t i = 2; i < num_params; ++i) { for (size_t i = 2; i < num_params; ++i) {
@@ -806,8 +811,11 @@ namespace ams::kern {
{ {
MESOSPHERE_ASSERT(num_params >= 2); MESOSPHERE_ASSERT(num_params >= 2);
/* Keep the compiler happy, even though the assert has us covered. */
if (num_params >= 2) {
info->info.exception.exception_address = params[1]; info->info.exception.exception_address = params[1];
} }
}
break; break;
} }
} }

View File

@@ -979,6 +979,7 @@
HANDLER(FsSaveDataFileSystemPeakMountCount, 777, FsProxyErrorInfo3, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(FsSaveDataFileSystemPeakMountCount, 777, FsProxyErrorInfo3, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(TestBool, 778, Test, FieldType_Bool, FieldFlag_None ) \ HANDLER(TestBool, 778, Test, FieldType_Bool, FieldFlag_None ) \
HANDLER(TestI8Array, 779, Test, FieldType_I8Array, FieldFlag_None ) \ HANDLER(TestI8Array, 779, Test, FieldType_I8Array, FieldFlag_None ) \
HANDLER(SslProcessHeapAllocatable, 781, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(TestStringNx, 1000, TestNx, FieldType_String, FieldFlag_None ) \ HANDLER(TestStringNx, 1000, TestNx, FieldType_String, FieldFlag_None ) \
HANDLER(BoostModeCurrentLimit, 1001, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(BoostModeCurrentLimit, 1001, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(ChargeConfiguration, 1002, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(ChargeConfiguration, 1002, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \

View File

@@ -111,6 +111,7 @@ namespace ams::erpt {
struct CreateReportOptionFlag { struct CreateReportOptionFlag {
using SubmitFsInfo = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>::Flag<0>; using SubmitFsInfo = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>::Flag<0>;
using Unknown0x20000 = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>::Flag<17>; /* TODO: What is this, it's checked in Reporter::CreateReport or below */
}; };
using CreateReportOptionFlagSet = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>; using CreateReportOptionFlagSet = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>;

View File

@@ -52,7 +52,8 @@ namespace ams::fs {
struct GameCardErrorReportInfo { struct GameCardErrorReportInfo {
u16 game_card_crc_error_num; u16 game_card_crc_error_num;
u16 reserved1; u8 last_deactivate_reason;
u8 reserved1;
u16 asic_crc_error_num; u16 asic_crc_error_num;
u16 reserved2; u16 reserved2;
u16 refresh_num; u16 refresh_num;
@@ -73,7 +74,8 @@ namespace ams::fs {
u32 awaken_count; u32 awaken_count;
u32 read_count_from_insert; u32 read_count_from_insert;
u32 read_count_from_awaken; u32 read_count_from_awaken;
u8 reserved5[8]; u32 last_deactivate_reason_result;
u32 reserved5;
}; };
static_assert(util::is_pod<GameCardErrorReportInfo>::value); static_assert(util::is_pod<GameCardErrorReportInfo>::value);
static_assert(sizeof(GameCardErrorReportInfo) == 0x40); static_assert(sizeof(GameCardErrorReportInfo) == 0x40);

View File

@@ -101,6 +101,8 @@ namespace ams::hos {
Version_21_1_0 = ::ams::TargetFirmware_21_1_0, Version_21_1_0 = ::ams::TargetFirmware_21_1_0,
Version_21_2_0 = ::ams::TargetFirmware_21_2_0, Version_21_2_0 = ::ams::TargetFirmware_21_2_0,
Version_22_0_0 = ::ams::TargetFirmware_22_0_0, Version_22_0_0 = ::ams::TargetFirmware_22_0_0,
Version_22_1_0 = ::ams::TargetFirmware_22_1_0,
Version_22_5_0 = ::ams::TargetFirmware_22_5_0,
Version_Current = ::ams::TargetFirmware_Current, Version_Current = ::ams::TargetFirmware_Current,

View File

@@ -41,7 +41,8 @@ namespace ams::pgl {
u32 version; u32 version;
ncm::ContentType content_type; ncm::ContentType content_type;
u8 id_offset; u8 id_offset;
u8 reserved_0E[2]; ncm::ContentMetaType content_meta_type;
u8 reserved_0F;
static constexpr ContentMetaInfo Make(u64 id, u32 version, ncm::ContentType content_type, u8 id_offset) { static constexpr ContentMetaInfo Make(u64 id, u32 version, ncm::ContentType content_type, u8 id_offset) {
return { return {

View File

@@ -19,13 +19,17 @@
namespace ams::util { namespace ams::util {
constexpr size_t DecompressZstdWithBicWorkBufferSizeDefault = 0x176E8;
/* 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 CompressZstd(void *dst, size_t dst_size, const void *src, size_t src_size);
size_t CompressZstdWithBic(void *dst, size_t dst_size, const void *src, size_t src_size);
/* 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 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 DecompressZstdWithBic(void *dst, size_t dst_size, const void *src, size_t src_size);
bool DecompressZstdWithBic(void* workspace, size_t workspace_size, void *dst, size_t dst_size, size_t expected_dec_size, const void *src, size_t src_size);
} }

View File

@@ -19,5 +19,6 @@
namespace ams::erpt::srv { namespace ams::erpt::srv {
Result SubmitFsInfo(); Result SubmitFsInfo();
void ClearFsInfo();
} }

View File

@@ -363,6 +363,8 @@ namespace ams::erpt::srv {
R_ABORT_UNLESS(record->Add(FieldId_GameCardReadCountFromAwaken, ei.read_count_from_awaken)); R_ABORT_UNLESS(record->Add(FieldId_GameCardReadCountFromAwaken, ei.read_count_from_awaken));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageAddress, ei.last_read_error_page_address)); R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageAddress, ei.last_read_error_page_address));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageCount, ei.last_read_error_page_count)); R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageCount, ei.last_read_error_page_count));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastDeactivateReasonResult, ei.last_deactivate_reason_result));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastDeactivateReason, ei.last_deactivate_reason));
/* Submit the record. */ /* Submit the record. */
R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record))); R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record)));
@@ -496,4 +498,27 @@ namespace ams::erpt::srv {
R_SUCCEED(); R_SUCCEED();
} }
void ClearFsInfo() {
Context::ClearContext(CategoryId_NANDTypeInfo);
Context::ClearContext(CategoryId_NANDSpeedModeInfo);
Context::ClearContext(CategoryId_NANDExtendedCsd);
Context::ClearContext(CategoryId_NANDPatrolInfo);
Context::ClearContext(CategoryId_NANDErrorInfo);
Context::ClearContext(CategoryId_NANDDriverLog);
Context::ClearContext(CategoryId_MicroSDTypeInfo);
Context::ClearContext(CategoryId_MicroSDSpeedModeInfo);
Context::ClearContext(CategoryId_SdCardSizeSpec);
Context::ClearContext(CategoryId_SdCardActivationInfo);
Context::ClearContext(CategoryId_SdCardErrorInfo);
Context::ClearContext(CategoryId_SdCardDriverLog);
Context::ClearContext(CategoryId_GameCardCIDInfo);
Context::ClearContext(CategoryId_GameCardErrorInfo);
Context::ClearContext(CategoryId_GameCardDetailedErrorInfo);
Context::ClearContext(CategoryId_GameCardLogInfo);
Context::ClearContext(CategoryId_FsProxyErrorInfo);
Context::ClearContext(CategoryId_FsProxyErrorInfo2);
Context::ClearContext(CategoryId_FsProxyErrorInfo3);
Context::ClearContext(CategoryId_FsMemoryInfo);
}
} }

View File

@@ -423,7 +423,11 @@ namespace ams::erpt::srv {
auto report = std::make_unique<Report>(record.get(), redirect_new_reports); auto report = std::make_unique<Report>(record.get(), redirect_new_reports);
R_UNLESS(report != nullptr, erpt::ResultOutOfMemory()); R_UNLESS(report != nullptr, erpt::ResultOutOfMemory());
auto report_guard = SCOPE_GUARD { const auto delete_res = report->Delete(); R_ASSERT(delete_res); AMS_UNUSED(delete_res); }; auto report_guard = SCOPE_GUARD {
const auto delete_res = report->Delete();
R_ASSERT(delete_res);
AMS_UNUSED(delete_res);
};
R_TRY(Context::WriteContextsToReport(report.get())); R_TRY(Context::WriteContextsToReport(report.get()));
R_TRY(report->GetSize(std::addressof(record->m_info.report_size))); R_TRY(report->GetSize(std::addressof(record->m_info.report_size)));
@@ -434,7 +438,7 @@ namespace ams::erpt::srv {
} else { } else {
/* If we are redirecting new reports, we don't want to store the report in the journal. */ /* If we are redirecting new reports, we don't want to store the report in the journal. */
/* We should take this opportunity to delete any attachments associated with the report. */ /* We should take this opportunity to delete any attachments associated with the report. */
R_ABORT_UNLESS(JournalForAttachments::DeleteAttachments(report_id)); R_TRY(JournalForAttachments::DeleteAttachments(report_id));
} }
R_TRY(Journal::Commit()); R_TRY(Journal::Commit());
@@ -489,6 +493,20 @@ namespace ams::erpt::srv {
static_cast<void>(Context::ClearContext(CategoryId_ErrorInfo)); static_cast<void>(Context::ClearContext(CategoryId_ErrorInfo));
static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoAuto)); static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoAuto));
static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoDefaults)); static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoDefaults));
#if defined(ATMOSPHERE_OS_HORIZON)
/* TODO: What else is missing? */
if (hos::GetVersion() >= hos::Version_17_0_0 && flags.Test<CreateReportOptionFlag::SubmitFsInfo>()) {
ClearFsInfo();
}
/* if (erpt::ResultInvalidPowerState::Includes(...)) {
* Nintendo ignores this and sends "power_state_violation" play report if this error happens.
* } else {
* Nintendo sends "write_failure" play report if any other error happens.
* }
*/
#endif
}; };
/* Get the context entry pointer. */ /* Get the context entry pointer. */

View File

@@ -47,7 +47,7 @@ namespace ams::hos {
#endif #endif
exosphere::ApiInfo GetExosphereApiInfo(bool allow_approximate) { exosphere::ApiInfo GetExosphereApiInfo(bool allow_approximate) {
exosphere::ApiInfo info; exosphere::ApiInfo info = exosphere::ApiInfo{ util::BitPack64{0} };
#if defined(ATMOSPHERE_OS_HORIZON) #if defined(ATMOSPHERE_OS_HORIZON)
while (true) { while (true) {
if (R_SUCCEEDED(GetExosphereApiInfo(std::addressof(info)))) { if (R_SUCCEEDED(GetExosphereApiInfo(std::addressof(info)))) {

View File

@@ -221,6 +221,9 @@ namespace ams::ncm {
/* Assert that we copied the right number of infos. */ /* Assert that we copied the right number of infos. */
AMS_ASSERT(count == fragment_count); AMS_ASSERT(count == fragment_count);
/* TODO: Unused variable. */
AMS_UNUSED(count);
R_SUCCEED(); R_SUCCEED();
} }
@@ -433,6 +436,9 @@ namespace ams::ncm {
/* Assert that we copied the right number of infos. */ /* Assert that we copied the right number of infos. */
AMS_ASSERT(count == fragment_count); AMS_ASSERT(count == fragment_count);
/* TODO: Unused variable. */
AMS_UNUSED(count);
R_SUCCEED(); R_SUCCEED();
} }

View File

@@ -77,7 +77,7 @@ namespace ams::pgl::srv {
private: private:
char m_content_path[fs::EntryNameLengthMax] = {}; char m_content_path[fs::EntryNameLengthMax] = {};
ExtensionType m_extension_type = ExtensionType::None; ExtensionType m_extension_type = ExtensionType::None;
char m_mount_name[fs::MountNameLengthMax] = {}; char m_mount_name[fs::MountNameLengthMax + 1] = {};
bool m_is_mounted = false; bool m_is_mounted = false;
ncm::AutoBuffer m_content_meta_buffer; ncm::AutoBuffer m_content_meta_buffer;
ncm::ProgramId m_program_id = ncm::InvalidProgramId; ncm::ProgramId m_program_id = ncm::InvalidProgramId;
@@ -349,6 +349,7 @@ namespace ams::pgl::srv {
.version = reader.GetProgramVersion(), .version = reader.GetProgramVersion(),
.content_type = ncm::ContentType::Program, .content_type = ncm::ContentType::Program,
.id_offset = reader.GetProgramIndex(), .id_offset = reader.GetProgramIndex(),
.content_meta_type = reader.GetContentMetaType(),
}; };
R_SUCCEED(); R_SUCCEED();

View File

@@ -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
} }

View File

@@ -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;

View File

@@ -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);

View File

@@ -0,0 +1,39 @@
/*
* 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 {
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));
}
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));
}
}

View File

@@ -0,0 +1,60 @@
/*
* 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>
#define ZSTD_STATIC_LINKING_ONLY
#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 {
size_t CompressZstd(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());
/* Additionally, we must check the compression boundary. */
auto bound = ZSTD_compressBound(src_size);
AMS_ABORT_UNLESS(!ZSTD_isError(bound));
AMS_ABORT_UNLESS(dst_size >= bound);
/* Use Zstd default level. */
int compressionLevel = 3;
/* This is just a wrapper around Zstd. */
return ZSTD_compress(dst, dst_size, src, src_size, compressionLevel);
}
size_t DecompressZstd(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());
/* Additionally, we must check the decompression boundary. */
auto bound = ZSTD_decompressBound(src, src_size);
AMS_ABORT_UNLESS(!ZSTD_isError(bound));
AMS_ABORT_UNLESS(dst_size >= bound);
/* This is just a wrapper around Zstd. */
return ZSTD_decompress(dst, dst_size, src, src_size);
}
}

View File

@@ -14,24 +14,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#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) <= DecompressZstdWithBicWorkBufferSizeDefault);
/* Compression utilities. */ size_t CompressZstdWithBic(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());
@@ -44,21 +41,11 @@ namespace ams::util {
/* Use Zstd default level. */ /* Use Zstd default level. */
int compressionLevel = 3; int compressionLevel = 3;
/* This is just a wrapper around Zstd. */ /* This is just a wrapper around Zstd with BIC support enabled. */
return ZSTD_compress(dst, dst_size, src, src_size, compressionLevel); return ZSTD_compress(dst, dst_size, src, src_size, compressionLevel);
} }
/* Decompression utilities. */ size_t DecompressZstdWithBic(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 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) {
/* 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());
@@ -68,14 +55,22 @@ namespace ams::util {
AMS_ABORT_UNLESS(!ZSTD_isError(bound)); AMS_ABORT_UNLESS(!ZSTD_isError(bound));
AMS_ABORT_UNLESS(dst_size >= bound); AMS_ABORT_UNLESS(dst_size >= bound);
/* This is just a wrapper around Zstd. */ /* This is just a wrapper around Zstd with BIC support enabled. */
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 DecompressZstdWithBic(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 error_code = ZSTD_getErrorCode(margin);
auto error_string = ZSTD_getErrorString(error_code);
AMS_LOG("[util] Can't determine decompression margin: %u (%s)\n", error_code, error_string);
/* TODO: Unused variables in non-debug build. */
AMS_UNUSED(error_code, error_string);
return false; return false;
} }
@@ -86,20 +81,30 @@ 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("[util] 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 error_code = ZSTD_getErrorCode(margin);
auto error_string = ZSTD_getErrorString(error_code);
AMS_LOG("[util] Decompression failed: %u (%s)\n", error_code, error_string);
/* TODO: Unused variables in non-debug build. */
AMS_UNUSED(error_code, error_string);
return false; return false;
} }
/* Make sure we match the expected size. */
if (dec_size != expected_dec_size) { if (dec_size != expected_dec_size) {
return false; return false;
} }

View File

@@ -17,10 +17,10 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 11 #define ATMOSPHERE_RELEASE_VERSION_MINOR 11
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #define ATMOSPHERE_RELEASE_VERSION_MICRO 2
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 22 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 22
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 5
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0

View File

@@ -99,8 +99,10 @@
#define ATMOSPHERE_TARGET_FIRMWARE_21_1_0 ATMOSPHERE_TARGET_FIRMWARE(21, 1, 0) #define ATMOSPHERE_TARGET_FIRMWARE_21_1_0 ATMOSPHERE_TARGET_FIRMWARE(21, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_21_2_0 ATMOSPHERE_TARGET_FIRMWARE(21, 2, 0) #define ATMOSPHERE_TARGET_FIRMWARE_21_2_0 ATMOSPHERE_TARGET_FIRMWARE(21, 2, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_22_0_0 ATMOSPHERE_TARGET_FIRMWARE(22, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_22_0_0 ATMOSPHERE_TARGET_FIRMWARE(22, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_22_1_0 ATMOSPHERE_TARGET_FIRMWARE(22, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_22_5_0 ATMOSPHERE_TARGET_FIRMWARE(22, 5, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_22_0_0 #define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_22_5_0
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
@@ -192,6 +194,8 @@ namespace ams {
TargetFirmware_21_1_0 = ATMOSPHERE_TARGET_FIRMWARE_21_1_0, TargetFirmware_21_1_0 = ATMOSPHERE_TARGET_FIRMWARE_21_1_0,
TargetFirmware_21_2_0 = ATMOSPHERE_TARGET_FIRMWARE_21_2_0, TargetFirmware_21_2_0 = ATMOSPHERE_TARGET_FIRMWARE_21_2_0,
TargetFirmware_22_0_0 = ATMOSPHERE_TARGET_FIRMWARE_22_0_0, TargetFirmware_22_0_0 = ATMOSPHERE_TARGET_FIRMWARE_22_0_0,
TargetFirmware_22_1_0 = ATMOSPHERE_TARGET_FIRMWARE_22_1_0,
TargetFirmware_22_5_0 = ATMOSPHERE_TARGET_FIRMWARE_22_5_0,
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,

View File

@@ -452,6 +452,9 @@ namespace ams::result::impl {
} \ } \
} }
/// Explicitly discards the result returned by an expression.
#define R_DISCARD(res_expr) (static_cast<void>(res_expr))
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX) && defined(ATMOSPHERE_IS_STRATOSPHERE) && !defined(AMS_ENABLE_DETAILED_ASSERTIONS) && !defined(AMS_BUILD_FOR_DEBUGGING) && !defined(AMS_BUILD_FOR_AUDITING) #if defined(ATMOSPHERE_BOARD_NINTENDO_NX) && defined(ATMOSPHERE_IS_STRATOSPHERE) && !defined(AMS_ENABLE_DETAILED_ASSERTIONS) && !defined(AMS_BUILD_FOR_DEBUGGING) && !defined(AMS_BUILD_FOR_AUDITING)
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false) #define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false) #define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)
@@ -491,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())

View File

@@ -186,6 +186,9 @@ namespace ams::svc::codegen::impl {
size_t i = 0; size_t i = 0;
(layout.ProcessArgument<AbiType, ArgumentTypes>(i++, NGRN, NSAA), ...); (layout.ProcessArgument<AbiType, ArgumentTypes>(i++, NGRN, NSAA), ...);
/* TODO: Unused variable. */
AMS_UNUSED(i);
return layout; return layout;
} }

View File

@@ -36,6 +36,11 @@ namespace ams::mitm::fs {
}; };
constexpr const ApplicationWithDynamicHeapInfo ApplicationsWithDynamicHeap[] = { constexpr const ApplicationWithDynamicHeapInfo ApplicationsWithDynamicHeap[] = {
/* Until Then. */
/* Requirement ~34 MB. */
/* No particular heap sensitivity. */
{ 0x010019C023004000, 16_MB, 0_MB },
/* Trails in the Sky 1st Chapter. */ /* Trails in the Sky 1st Chapter. */
/* Requirement ? MB. 16 MB stolen heap fixes a crash, though. */ /* Requirement ? MB. 16 MB stolen heap fixes a crash, though. */
/* Unknown heap sensitivity. */ /* Unknown heap sensitivity. */

View File

@@ -100,5 +100,6 @@ constexpr inline const EmbeddedPatch Usb30ForceEnablePatches[] = {
{ ParseModuleId("40E80E7442C0DFC985315E6F9E8C77229818AC0F"), util::size(Usb30ForceEnablePatches_20_0_0), Usb30ForceEnablePatches_20_0_0 }, /* 20.0.0 */ { ParseModuleId("40E80E7442C0DFC985315E6F9E8C77229818AC0F"), util::size(Usb30ForceEnablePatches_20_0_0), Usb30ForceEnablePatches_20_0_0 }, /* 20.0.0 */
{ ParseModuleId("A5EF8D22EDF8A384E4135270ED596C1D2D524159"), util::size(Usb30ForceEnablePatches_20_0_0), Usb30ForceEnablePatches_20_0_0 }, /* 20.1.0 - 20.5.0 */ { ParseModuleId("A5EF8D22EDF8A384E4135270ED596C1D2D524159"), util::size(Usb30ForceEnablePatches_20_0_0), Usb30ForceEnablePatches_20_0_0 }, /* 20.1.0 - 20.5.0 */
{ ParseModuleId("766D0C2277207B40AD9B8DE309396D50CCE94885"), util::size(Usb30ForceEnablePatches_21_0_0), Usb30ForceEnablePatches_21_0_0 }, /* 21.0.0 */ { ParseModuleId("766D0C2277207B40AD9B8DE309396D50CCE94885"), util::size(Usb30ForceEnablePatches_21_0_0), Usb30ForceEnablePatches_21_0_0 }, /* 21.0.0 */
{ ParseModuleId("B734339F2280170AF0200573F9B943242CEF8C15"), util::size(Usb30ForceEnablePatches_22_0_0), Usb30ForceEnablePatches_22_0_0 }, /* 22.0.0 */ { ParseModuleId("B734339F2280170AF0200573F9B943242CEF8C15"), util::size(Usb30ForceEnablePatches_22_0_0), Usb30ForceEnablePatches_22_0_0 }, /* 22.0.0 - 22.1.0 */
{ ParseModuleId("AD8D36F2029822A4C498F055ADBDAA789EB913C6"), util::size(Usb30ForceEnablePatches_22_0_0), Usb30ForceEnablePatches_22_0_0 }, /* 22.5.0 */
}; };

View File

@@ -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::DecompressZstdWithBicWorkBufferSizeDefault];
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::DecompressZstdWithBic(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));
} }

View File

@@ -1,18 +0,0 @@
/*
* 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/>.
*/
#define AMS_ZSTD_IMPLEMENTATION
#include <stratosphere/util/util_zbic_for_loader.hpp>

View File

@@ -15,7 +15,7 @@
"filesystem_access": { "filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF" "permissions": "0xFFFFFFFFFFFFFFFF"
}, },
"service_access": ["erpt:c", "fatal:u", "fsp-srv", "ldr:shel", "lm", "lr", "pm:shell", "set", "set:sys"], "service_access": ["fatal:u", "fsp-srv", "ldr:shel", "lr", "pm:shell", "set:sys"],
"service_host": ["pgl"], "service_host": ["pgl"],
"kernel_capabilities": [{ "kernel_capabilities": [{
"type": "kernel_flags", "type": "kernel_flags",

View File

@@ -31,12 +31,13 @@ namespace ams {
fs::SetAllocator(pgl::srv::Allocate, pgl::srv::Deallocate); fs::SetAllocator(pgl::srv::Allocate, pgl::srv::Deallocate);
fs::SetEnabledAutoAbort(false); fs::SetEnabledAutoAbort(false);
/* Initialize lr. */
lr::Initialize();
/* Initialize other services we need. */ /* Initialize other services we need. */
R_ABORT_UNLESS(setInitialize());
R_ABORT_UNLESS(setsysInitialize()); R_ABORT_UNLESS(setsysInitialize());
R_ABORT_UNLESS(pmshellInitialize()); R_ABORT_UNLESS(pmshellInitialize());
R_ABORT_UNLESS(ldrShellInitialize()); R_ABORT_UNLESS(ldrShellInitialize());
R_ABORT_UNLESS(lrInitialize());
/* Verify that we can sanely execute. */ /* Verify that we can sanely execute. */
ams::CheckApiVersion(); ams::CheckApiVersion();
@@ -58,3 +59,36 @@ namespace ams {
} }
} }
/* Override operator new. */
void *operator new(size_t size) {
return ams::pgl::srv::Allocate(size);
}
void *operator new(size_t size, const std::nothrow_t &) {
return ams::pgl::srv::Allocate(size);
}
void operator delete(void *p) {
return ams::pgl::srv::Deallocate(p, 0);
}
void operator delete(void *p, size_t size) {
return ams::pgl::srv::Deallocate(p, size);
}
void *operator new[](size_t size) {
return ams::pgl::srv::Allocate(size);
}
void *operator new[](size_t size, const std::nothrow_t &) {
return ams::pgl::srv::Allocate(size);
}
void operator delete[](void *p) {
return ams::pgl::srv::Deallocate(p, 0);
}
void operator delete[](void *p, size_t size) {
return ams::pgl::srv::Deallocate(p, size);
}