Compare commits

...

122 Commits

Author SHA1 Message Date
Niklas080208
ec9b500c67 daybreak: Add a setting to bypass the firmware version check
Let users turn off the Exosphere compatibility gate from the main menu when installing firmware newer than this Atmosphere build supports.
2026-10-02 17:20:07 +02:00
Niklas080208
31d5beb756 Merge upstream Atmosphere-NX/Atmosphere master 2026-09-29 21:44:46 +02:00
Niklas080208
efc4e5e87b Changed 1st stage boot logo to NiklasCFW 2026-09-29 21:43:56 +02:00
hexkyz
28d6a2e11f git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "aae2da015"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "aae2da015"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-09-27 23:13:40 +01:00
hexkyz
c68e08a101 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "5b966b6f3"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "5b966b6f3"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-09-27 23:12:36 +01:00
hexkyz
7442487ace docs: add changelog for 1.12.0 2026-09-27 23:10:27 +01:00
hexkyz
a1a9886290 ro/util: last round of fixes, now fully matches official behavior 2026-09-27 22:09:31 +01:00
hexkyz
afb0cda7f3 Merge pull request #2860 from borntohonk/web
ncm: add OpenWeb and SystemWeb applet ids
2026-09-27 18:56:57 +01:00
borntohonk
7dd6771584 ncm: add OpenWeb and SystemWeb applet ids 2026-09-27 11:30:35 +02:00
hexkyz
59e7786a45 web: introduce browser memory patching
With 23.0.0 we have even less memory available which is causing the browser (openWeb) and eshop (systemWeb) applets to crash immediately.
While the amount of memory required by the browser applets didn't change this time, just implementing 23.0.0 changes was enough to push it over the limit.
Instead of reducing the memory available to us even further, this convoluted set of patches attempts to reclaim around 9 MB of unused browser memory.
2026-09-27 01:35:29 +01:00
hexkyz
2ae182bd5d ro: add missing fixes 2026-09-25 01:33:40 +01:00
hexkyz
788546f476 Merge pull request #2852 from Lazy-Coder-03/htcfs_rename_fix
htcfs: fix swapped path lengths in RenameFile/RenameDirectory
2026-09-24 01:31:13 +01:00
hexkyz
e872f5b566 Merge pull request #2854 from Ludwigmk/master
fs.mitm: add danganronpa v3 to games needing stolen heap for layeredfs
2026-09-24 01:30:57 +01:00
hexkyz
56cb82aa44 Merge pull request #2855 from Lazy-Coder-03/kern_continue_debug_event_fix
kern: only check thread ids pointer when count is nonzero
2026-09-24 01:22:03 +01:00
hexkyz
58f2b963d5 ro: implement NRO decompression and fix bugs 2026-09-24 01:18:59 +01:00
hexkyz
44d9649c6d ams: use R_DISCARD everywhere 2026-09-23 20:42:15 +01:00
hexkyz
2d0fc65fd8 kern: implement and comment missing 23.0.0 changes 2026-09-23 00:02:33 +01:00
hexkyz
21f16ff938 boot: add missing 18.0.0 change and new 23.0.0 change 2026-09-21 23:10:09 +01:00
hexkyz
82f15b6e5d pm: NotifyBootFinished no longer changes program verification 2026-09-21 21:33:12 +01:00
hexkyz
1de771e264 os: ShadowStack is a forbidden region 2026-09-21 21:20:13 +01:00
Lazy-Coder-03
02ce3bc385 kern: only check thread ids pointer when count is nonzero 2026-09-21 13:04:46 +05:30
hexkyz
0411dbfdda ro: start implementing 23.0.0 changes 2026-09-20 23:23:56 +01:00
Ludwig
56d301ef5c fs.mitm: add danganronpa v3 to games needing stolen heap for layeredfs 2026-09-20 22:17:14 +02:00
Lazy-Coder-03
1748644f81 htcfs: fix swapped path lengths in RenameFile/RenameDirectory 2026-09-20 21:38:31 +05:30
hexkyz
f62bc71ea4 Merge pull request #2847 from alula/23_support
23.0.0 remaining kernel / loader changes
2026-09-18 21:18:12 +01:00
Alula
518e494744 ams: fix libnx build in dockerfile 2026-09-18 08:35:14 +02:00
Alula
1d6e593aba kern: use CTR_DRBG from vapours 2026-09-18 07:25:48 +02:00
Alula
866c831f7a spl/vapours: move CTR_DRBG to vapours 2026-09-18 07:22:42 +02:00
Alula
85f119a5c4 kern/loader: fix git rebase errors 2026-09-18 07:21:22 +02:00
Alula
3cfac4c2d8 kern: switch RNG to CTR-DBRG 2026-09-18 04:02:58 +02:00
Alula
4e917d700f kern: allocate the shadow stack 2026-09-18 04:02:54 +02:00
Alula
f40b85cd5d loader: pass enable shadow stack flag 2026-09-18 03:38:33 +02:00
Alula
af14725916 kern: handle SVE exceptions 2026-09-18 03:38:32 +02:00
Alula
1d308207f7 pinmux: configure logport via exosphere 2026-09-18 03:38:32 +02:00
hexkyz
8ad3efdd79 loader: add missing EnableShadowStack to process flags 2026-09-17 21:44:25 +01:00
hexkyz
ab1e8a3e32 kern/loader/svc: adopt updated names 2026-09-17 21:42:22 +01:00
hexkyz
9b4e4a2190 gpio: update for 23.0.0 2026-09-17 19:40:17 +01:00
hexkyz
ff09b598d5 i2c: deprecate SetRetryPolicy as of 23.0.0 2026-09-17 17:11:51 +01:00
hexkyz
6acbabeb72 Merge pull request #2844 from alula/23_support
23.0.0: kernel changes
2026-09-17 00:36:07 +01:00
hexkyz
98d64c28d8 sprofile: clean up and update for 23.0.0 2026-09-17 00:34:00 +01:00
hexkyz
7cc625946e pgl: add missing changes and fix bugs 2026-09-17 00:30:00 +01:00
hexkyz
afff8cbf16 erpt: use the AMS_UNUSED macro 2026-09-17 00:28:26 +01:00
Alula
b7048ec595 kern: fix kthread constinit 2026-09-16 05:30:17 +02:00
hexkyz
092f451c33 pgl: fix bad copy paste 2026-09-15 22:26:03 +01:00
hexkyz
49b12237e8 pgl: clean up and add new 23.0.0 command 2026-09-15 22:16:29 +01:00
Alula
dbfe192b2f kern: reject shadow stack accesses in syscalls 2026-09-15 17:04:50 +02:00
Alula
7e58f5fbae kern: finish shadow stack region, 64k page process segregation implementation, fix some long-standing issues 2026-09-15 17:04:50 +02:00
Alula
289ba7104e kern: add new unknown DebugThreadParam 2026-09-15 17:04:50 +02:00
Alula
0f15010ba5 kern/loader: make aware of new address space and shadow stack region 2026-09-15 17:04:50 +02:00
hexkyz
e6a3d71692 exo/spl: new ConfigItem in 23.0.0 is wild 2026-09-14 23:04:57 +01:00
hexkyz
819da013ed erpt: implement new command changes for 23.0.0 2026-09-12 21:23:53 +01:00
hexkyz
3d8caba822 erpt: update categories for 23.0.0 2026-09-12 18:33:22 +01:00
hexkyz
aad15daad6 Merge pull request #2840 from alula/23_support
23.0.0 pt 1
2026-09-11 18:58:42 +01:00
Alula
22bbe413c6 fusee: fix missing FS enum 2026-09-11 02:14:16 +02:00
hexkyz
85aea12e53 erpt: add new IDs and category changes for 23.0.0 2026-09-10 16:57:39 +01:00
hexkyz
8ec1288bd6 loader: update USB 3.0 patches for 23.0.0 2026-09-10 16:31:52 +01:00
hexkyz
bce987792d emummc: update for 23.0.0 2026-09-10 16:23:01 +01:00
hexkyz
3d3f0c2daf fusee/exo/ams: update with new keydata/version enums 2026-09-10 15:31:12 +01:00
hexkyz
6e6af69424 Merge pull request #2838 from alula/alula/dockerfile
ams: add Dockerfile with build environment
2026-09-10 13:50:10 +01:00
Alula
332926fc17 ams: add Dockerfile with build environment 2026-09-10 12:09:16 +02:00
hexkyz
cb4b882e3b git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "edb2cca26"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "edb2cca26"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-08-21 23:15:32 +01:00
hexkyz
f7d46d38fa meso: only increment send/recv/exch on success 2026-08-21 23:13:40 +01:00
hexkyz
e468f59c9d Merge pull request #2821 from dogty/master
sf: close request copy handles in mitm ForwardRequest
2026-07-17 18:36:33 +01:00
26b1ec7ca8 Merge upstream Atmosphere-NX/Atmosphere master 2026-07-17 12:07:12 +02:00
dogty
b05166d502 sf: close request copy handles in mitm ForwardRequest
ForwardRequest closes copy handles from the forward response but never from the request. Any mitm'd command that carries a client copy handle therefore leaks that handle in the mitm process for its lifetime. A leaked transfer memory pins the client process object after it dies, its application memory reservation never releases, and the next application launch blocks forever freezing the console.

Close the request's copy handles after the forward send, parsed from the saved message.
2026-07-17 08:40:28 +02:00
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
5cb085b00c daybreak: Add firmware compatibility gate and German UI
Block unsupported firmware updates via a dedicated dialog using
Exosphere's maximum supported HOS version, and translate the Daybreak
interface to German.
2026-05-17 12:59:14 +02: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
254 changed files with 3892 additions and 1746 deletions

80
Dockerfile Normal file
View File

@@ -0,0 +1,80 @@
FROM devkitpro/devkita64:20260219
ARG PYTHON_VERSION=2.7.18
ARG PYTHON_SHA256=da3080e3b488f648a3d7a4560ddee895284c3380b11d6de75edb986526b9a814
ARG PYTHON_LZ4_VERSION=2.2.1
ARG PYTHON_LZ4_SHA256=9f529a443f9eb1b49d040f0791bb3934c64b9a927609a30319c3b82f93d9525a
RUN apt update && \
apt install automake build-essential ca-certificates wget libbz2-dev libffi-dev libgdbm-dev liblz4-dev libncurses5-dev libreadline-dev libsqlite3-dev libssl-dev liblzma-dev sudo tk-dev uuid-dev zlib1g-dev python3-lz4 python3-pip -y && \
cd /tmp && \
wget -q https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz && \
echo "${PYTHON_SHA256} Python-${PYTHON_VERSION}.tgz" | sha256sum --check && \
tar -xzf Python-${PYTHON_VERSION}.tgz && \
cd /tmp/Python-${PYTHON_VERSION} && \
./configure --prefix=/usr/local --with-ensurepip=install && \
make -j"$(nproc)" altinstall && \
cd /tmp && \
wget -q https://files.pythonhosted.org/packages/86/4f/028a9ff9cfc73f317c22dc3b8f29a7c5c94098d4da590405e6b78af00e57/lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl && \
echo "${PYTHON_LZ4_SHA256} lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl" | sha256sum --check && \
/usr/local/bin/python2.7 -m pip install --no-deps --no-index lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl && \
ln -fs /usr/local/bin/python2.7 /usr/local/bin/python2 && \
ln -fs /usr/local/bin/python2.7 /usr/local/bin/python && \
rm -rf /tmp/Python-${PYTHON_VERSION} /tmp/Python-${PYTHON_VERSION}.tgz /tmp/lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/* /usr/share/doc /usr/share/man
# Install latest hactool & switch-tools from dkp pacman & update everything
RUN dkp-pacman -S switch-tools hactool --noconfirm && dkp-pacman -Syu --noconfirm
# # Install hactool from Git (optional)
# ENV HACTOOL_REV=1d64a83450e025622f3468c28fc4164dad2c5ef6
# RUN cd /tmp && \
# mkdir -p /tmp/hactool && \
# cd /tmp/hactool && \
# git init && \
# git remote add origin https://github.com/SciresM/hactool.git && \
# git fetch --depth 1 origin $HACTOOL_REV && \
# git reset --hard FETCH_HEAD && \
# cp config.mk.template config.mk && \
# make -j$(nproc) && \
# cp hactool /opt/devkitpro/tools/bin/hactool && \
# cd /tmp && \
# rm -rf /tmp/hactool
# # Install switch-tools from Git (optional)
# ENV SWITCH_TOOLS_REV=22756068dd0ed6ff9734c59cb4f99ebd3f62555b
# RUN cd /tmp && \
# mkdir -p /tmp/switch-tools && \
# cd /tmp/switch-tools && \
# git init && \
# git remote add origin https://github.com/switchbrew/switch-tools.git && \
# git fetch --depth 1 origin $SWITCH_TOOLS_REV && \
# git reset --hard FETCH_HEAD && \
# ./autogen.sh && ./configure && make -j$(nproc) && \
# make install prefix=/opt/devkitpro/tools && \
# cd /tmp && \
# rm -rf /tmp/switch-tools
# Install libnx from Git (optional)
# ENV LIBNX_REV=146c3d1446d35546943c7b6cfcd479bc1f5e9b67
# RUN cd /tmp && \
# mkdir -p /tmp/libnx && \
# cd /tmp/libnx && \
# git init && \
# git remote add origin https://github.com/switchbrew/libnx.git && \
# git fetch --depth 1 origin $LIBNX_REV && \
# git reset --hard FETCH_HEAD && \
# make -j$(nproc) && \
# cd nx && \
# make install && \
# cd /tmp && \
# rm -rf /tmp/libnx
RUN useradd -m atmosphere && \
echo "atmosphere ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/atmosphere && \
chmod 0440 /etc/sudoers.d/atmosphere && \
echo "atmosphere:atmosphere" | chpasswd && \
usermod -aG sudo atmosphere
USER atmosphere
CMD ["/bin/bash"]

View File

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

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

View File

@@ -15,6 +15,13 @@
# Desc: Controls whether userland has access to the PMU registers.
# 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.
# Desc: Controls whether PRODINFO should be blanked in sysmmc.
# This will cause the system to see dummied out keys and
@@ -51,6 +58,7 @@ debugmode=1
debugmode_user=0
disable_user_exception_handlers=0
enable_user_pmu_access=0
enable_mem_mode=0
blank_prodinfo_sysmmc=0
blank_prodinfo_emummc=0
allow_writing_to_cal_sysmmc=0

View File

@@ -1,4 +1,61 @@
# Changelog
## 1.12.0
+ Support was added for 23.0.0.
+ Special thanks to @alula for handling the implementation of several kernel changes.
+ The console should boot and atmosphère should be fully functional.
+ **Please note**: As a result of changes made to nintendo's software in 23.0.0, there is even less memory available for custom system modules.
+ The amount of memory we can steal from the applet pool has been reduced beyond 7MB and we can no longer launch browser applets (e.g.: eshop) without crashing.
+ To compensate for this, a set of patches for the browser applets has been introduced.
+ Thanks to the redesign of the browser applets in 22.0.0 there are only 3 applets we need to worry about: systemWeb, openWeb and LibAppletOff.
+ With the added burden of maintaining patches for these applets, we can reclaim around 9MB of reserved memory by patching out their allocations.
+ This memory is provably unused and stealing it should not affect the browser applets in any way as the applets themselves tag it as reserved and never access it.
+ As a result, the memory available for custom system modules has been experimentally increased to 16MB.
+ Preliminary testing has seemingly shown no downsides to the overall functioning of the OS and the browser applets in particular.
+ Nonetheless, please report any issues you may face to ensure no edge cases have been missed and to determine if the memory amount needs to be adjusted.
+ These patches may be deprecated at any point in the future if a better solution is devised.
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
+ A new ConfigItem was added to the secure monitor for the first time since firmware 5.0.0.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ The kernel now supports a 42bit wide address space.
+ A new memory region dubbed ShadowStack has been introduced.
+ Kernel RNG was changed to CTR-DRBG.
+ `boot` was updated to reflect the latest official behavior and to implement a previously missing change.
+ The way battery i2c shutdown was being enabled changed in firmware 18.0.0 and we missed it.
+ It is possible this might have been related to a known battery draining issue reported to have started around firmware 18.0.0. Further testing will be needed to confirm.
+ `loader` was updated to reflect the latest official behavior.
+ `erpt` was updated to reflect the latest official behavior.
+ `pgl` was updated to reflect the latest official behavior.
+ `ro` was updated to reflect the latest official behavior.
+ NROs can now be lz4 frame compressed.
+ ZBIC compresison/decompression has been properly implemented. Applications using it should now launch and work properly.
+ A dockerfile has been added to atmosphère (thanks @alula).
+ R_DISCARD macro has been adopted across the entire codebase where applicable. This finishes the work started in version 1.10.0 and eliminates the nodiscard warnings during compilation.
+ General system stability improvements to enhance the user's experience.
## 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
+ Basic support was added for 21.2.0.
+ General system stability improvements to enhance the user's experience.

6
emummc/.gitrepo vendored
View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/m4xw/emummc
branch = develop
commit = 8ab963b0b1c24b68de8e0c98c62c7822a9765bf3
parent = 1e88f37892555da4c38ca6c95f43c56cc6bb87e6
commit = 5b966b6f3f83349ec65066a1877f7f948b48d08c
parent = 7442487ace6b79ddddf2cd0007b8dade8150bf5c
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***
### Supported Horizon Versions
**1.0.0 - 21.2.0**
**1.0.0 - 23.0.0**
## Features
* Arbitrary SDMMC backend selection

View File

@@ -85,6 +85,10 @@
#include "offsets/2120_exfat.h"
#include "offsets/2200.h"
#include "offsets/2200_exfat.h"
#include "offsets/2250.h"
#include "offsets/2250_exfat.h"
#include "offsets/2300.h"
#include "offsets/2300_exfat.h"
#include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -181,6 +185,10 @@ DEFINE_OFFSET_STRUCT(_2120);
DEFINE_OFFSET_STRUCT(_2120_EXFAT);
DEFINE_OFFSET_STRUCT(_2200);
DEFINE_OFFSET_STRUCT(_2200_EXFAT);
DEFINE_OFFSET_STRUCT(_2250);
DEFINE_OFFSET_STRUCT(_2250_EXFAT);
DEFINE_OFFSET_STRUCT(_2300);
DEFINE_OFFSET_STRUCT(_2300_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) {
@@ -322,6 +330,14 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_2200));
case FS_VER_22_0_0_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));
case FS_VER_23_0_0:
return &(GET_OFFSET_STRUCT_NAME(_2300));
case FS_VER_23_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_2300_EXFAT));
default:
fatal_abort(Fatal_UnknownVersion);
}

View File

@@ -124,6 +124,12 @@ enum FS_VER
FS_VER_22_0_0,
FS_VER_22_0_0_EXFAT,
FS_VER_22_5_0,
FS_VER_22_5_0_EXFAT,
FS_VER_23_0_0,
FS_VER_23_0_0_EXFAT,
FS_VER_MAX,
};

View File

@@ -31,7 +31,7 @@
#define FS_OFFSET_2200_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260
// 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_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0

View File

@@ -31,7 +31,7 @@
#define FS_OFFSET_2200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450
// 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_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__

59
emummc/source/FS/offsets/2300.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_2300_H__
#define __FS_2300_H__
// Accessor vtable getters
#define FS_OFFSET_2300_SDMMC_ACCESSOR_GC 0x1B3640
#define FS_OFFSET_2300_SDMMC_ACCESSOR_SD 0x1B5640
#define FS_OFFSET_2300_SDMMC_ACCESSOR_NAND 0x1B3C70
// Hooks
#define FS_OFFSET_2300_SDMMC_WRAPPER_READ 0x1AF570
#define FS_OFFSET_2300_SDMMC_WRAPPER_WRITE 0x1AF5D0
#define FS_OFFSET_2300_RTLD 0x2F520
#define FS_OFFSET_2300_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2300_CLKRST_SET_MIN_V_CLK_RATE 0x1D27E0
// Misc funcs
#define FS_OFFSET_2300_LOCK_MUTEX 0x1A8090
#define FS_OFFSET_2300_UNLOCK_MUTEX 0x1A80E0
#define FS_OFFSET_2300_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AF530
#define FS_OFFSET_2300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1AF550
// Misc Data
#define FS_OFFSET_2300_SD_MUTEX 0xFF5408
#define FS_OFFSET_2300_NAND_MUTEX 0xFF0D70
#define FS_OFFSET_2300_ACTIVE_PARTITION 0xFF0DB0
#define FS_OFFSET_2300_SDMMC_DAS_HANDLE 0xFD2BE8
// NOPs
#define FS_OFFSET_2300_SD_DAS_INIT 0x2CA98
// Nintendo Paths
#define FS_OFFSET_2300_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00072D7C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00081BA4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A668, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0009F97C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2300_H__

59
emummc/source/FS/offsets/2300_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_2300_EXFAT_H__
#define __FS_2300_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_2300_EXFAT_SDMMC_ACCESSOR_GC 0x1BE840
#define FS_OFFSET_2300_EXFAT_SDMMC_ACCESSOR_SD 0x1C0840
#define FS_OFFSET_2300_EXFAT_SDMMC_ACCESSOR_NAND 0x1BEE70
// Hooks
#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_READ 0x1BA770
#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_WRITE 0x1BA7D0
#define FS_OFFSET_2300_EXFAT_RTLD 0x2F530
#define FS_OFFSET_2300_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2300_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DD9E0
// Misc funcs
#define FS_OFFSET_2300_EXFAT_LOCK_MUTEX 0x1B3290
#define FS_OFFSET_2300_EXFAT_UNLOCK_MUTEX 0x1B32E0
#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1BA730
#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1BA750
// Misc Data
#define FS_OFFSET_2300_EXFAT_SD_MUTEX 0x1006408
#define FS_OFFSET_2300_EXFAT_NAND_MUTEX 0x1001D70
#define FS_OFFSET_2300_EXFAT_ACTIVE_PARTITION 0x1001DB0
#define FS_OFFSET_2300_EXFAT_SDMMC_DAS_HANDLE 0xFDFBE8
// NOPs
#define FS_OFFSET_2300_EXFAT_SD_DAS_INIT 0x2CAA8
// Nintendo Paths
#define FS_OFFSET_2300_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00072D8C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00081BB4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A678, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0009F98C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2300_EXFAT_H__

View File

@@ -85,10 +85,10 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
/* We can get away with only including latest because exosphere supports newer-than-expected master key in engine. */
/* TODO: Update on next change of keys. */
/* Mariko Development Master Kek Source. */
.byte 0x2E, 0x27, 0x44, 0xEA, 0x32, 0xF8, 0x2C, 0xF0, 0x6F, 0xCA, 0xCD, 0x77, 0xAE, 0xAE, 0x1A, 0x1B
.byte 0x2B, 0xCD, 0xE7, 0xA4, 0x93, 0x12, 0x0A, 0x72, 0x64, 0x2B, 0x9E, 0xA4, 0xC2, 0x9F, 0xED, 0x13
/* Mariko Production Master Kek Source. */
.byte 0x82, 0xE2, 0x0A, 0x59, 0x67, 0xDF, 0xBF, 0x51, 0x47, 0x62, 0x11, 0xF2, 0x41, 0xD3, 0xEE, 0x13
.byte 0x08, 0x11, 0xF7, 0xE8, 0x76, 0x9E, 0xA3, 0xD5, 0x3A, 0x3D, 0x7A, 0x68, 0x1A, 0x24, 0x2A, 0x99
/* Development Master Key Vectors. */
.byte 0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE /* Zeroes encrypted with Master Key 00. */
@@ -113,6 +113,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x94, 0x46, 0x3B, 0xFA, 0x7D, 0xB9, 0xE2, 0x94, 0xC2, 0x9D, 0xB9, 0xA4, 0xB2, 0x56, 0xCA, 0xFE /* Master key 12 encrypted with Master key 13. */
.byte 0x74, 0xB2, 0x5F, 0xA0, 0x4B, 0x74, 0x6D, 0x47, 0x5B, 0xA9, 0xF5, 0x26, 0x46, 0xD7, 0x4B, 0x6E /* Master key 13 encrypted with Master key 14. */
.byte 0x97, 0xB3, 0x61, 0x88, 0x5C, 0x0D, 0xA1, 0x38, 0x73, 0xA4, 0x2F, 0x1A, 0x46, 0xA1, 0x09, 0xBF /* Master key 14 encrypted with Master key 15. */
.byte 0xA6, 0x25, 0x12, 0x6D, 0xA1, 0x12, 0x1F, 0x15, 0x08, 0x2F, 0x30, 0x5F, 0xCB, 0x7D, 0x32, 0x82 /* Master key 15 encrypted with Master key 16. */
/* Production Master Key Vectors. */
.byte 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D /* Zeroes encrypted with Master Key 00. */
@@ -137,6 +138,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 /* Master key 12 encrypted with Master key 13. */
.byte 0xF7, 0x92, 0xC0, 0xEC, 0xF3, 0xA4, 0x8C, 0xB7, 0x0D, 0xB3, 0xF3, 0xAB, 0x10, 0x9B, 0x18, 0xBA /* Master key 13 encrypted with Master key 14. */
.byte 0x14, 0xCB, 0x60, 0x29, 0x3D, 0xE0, 0xFB, 0xF2, 0x5B, 0x60, 0xB6, 0xC5, 0x2E, 0x77, 0x8F, 0x98 /* Master key 14 encrypted with Master key 15. */
.byte 0x26, 0x87, 0xDF, 0x21, 0x44, 0xD4, 0x5F, 0x4E, 0x61, 0x03, 0x9E, 0xF3, 0x40, 0x04, 0xC3, 0x87 /* Master Key 15 encrypted with Master Key 16. */
/* Device Master Key Source Sources. */
.byte 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D /* 4.0.0 Device Master Key Source Source. */
@@ -158,6 +160,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xA3, 0x6B, 0x0A, 0xB5, 0x6F, 0x57, 0x4C, 0x5E, 0x00, 0xFD, 0x56, 0x21, 0xF5, 0x06, 0x6B, 0xD1 /* 20.0.0 Device Master Key Source Source. */
.byte 0xF9, 0x62, 0x05, 0x99, 0xE0, 0xB9, 0xA6, 0x9B, 0x9D, 0xAA, 0xB4, 0x12, 0x0B, 0x0F, 0xF5, 0x8F /* 21.0.0 Device Master Key Source Source. */
.byte 0xF8, 0xF4, 0x22, 0xA4, 0x34, 0xAE, 0x0E, 0x0C, 0x4D, 0x5C, 0x5B, 0xA1, 0x1B, 0x46, 0x1C, 0x78 /* 22.0.0 Device Master Key Source Source. */
.byte 0x95, 0xC1, 0xAC, 0xB7, 0xB2, 0xCA, 0x9B, 0x8C, 0xD5, 0xEA, 0x40, 0xD9, 0x9C, 0xD2, 0x7C, 0x47 /* 23.0.0 Device Master Key Source Source. */
/* Development Device Master Kek Sources. */
.byte 0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34 /* 4.0.0 Device Master Kek Source. */
@@ -179,6 +182,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x09, 0x12, 0x4F, 0x26, 0x90, 0xB9, 0xA6, 0xF5, 0xA5, 0x18, 0x74, 0xB6, 0x8D, 0x80, 0x59, 0x3D /* 20.0.0 Device Master Kek Source. */
.byte 0x7A, 0x4C, 0x38, 0xB7, 0x03, 0x6B, 0x1E, 0x81, 0x20, 0x53, 0x14, 0x99, 0xA4, 0x21, 0x92, 0x9F /* 21.0.0 Device Master Kek Source. */
.byte 0xF3, 0xBC, 0xB5, 0xB5, 0x5F, 0x01, 0x50, 0x2B, 0x69, 0x69, 0x3A, 0x6B, 0xF9, 0x2C, 0x11, 0x9F /* 22.0.0 Device Master Kek Source. */
.byte 0x54, 0xAD, 0x79, 0x15, 0x11, 0x7C, 0x1E, 0x52, 0xBF, 0x2E, 0x40, 0xBB, 0x8B, 0x11, 0x54, 0x38 /* 23.0.0 Device Master Kek Source. */
/* Production Device Master Kek Sources. */
.byte 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D /* 4.0.0 Device Master Kek Source. */
@@ -199,4 +203,5 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F /* 19.0.0 Device Master Kek Source. */
.byte 0xDA, 0xFB, 0x61, 0x39, 0x48, 0x2D, 0xC2, 0x7E, 0x0D, 0x8E, 0x8F, 0x98, 0x57, 0x20, 0xB8, 0x15 /* 20.0.0 Device Master Kek Source. */
.byte 0x92, 0xBF, 0x37, 0x80, 0x0E, 0x79, 0x56, 0x8C, 0x57, 0x75, 0x72, 0x0A, 0x48, 0xD8, 0x15, 0x39 /* 21.0.0 Device Master Kek Source. */
.byte 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 /* 22.0.0 Device Master Kek Source. */
.byte 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 /* 22.0.0 Device Master Kek Source. */
.byte 0xA0, 0xC8, 0x44, 0x39, 0x8A, 0x1F, 0xD8, 0x6A, 0x3D, 0x0A, 0x23, 0xFF, 0x43, 0xA6, 0x95, 0x80 /* 23.0.0 Device Master Kek Source. */

View File

@@ -94,7 +94,7 @@ namespace ams::secmon::boot {
}
/* Check that the key generation is one that we can use. */
static_assert(pkg1::KeyGeneration_Count == 22);
static_assert(pkg1::KeyGeneration_Count == 23);
if (key_generation >= pkg1::KeyGeneration_Count) {
return false;
}

View File

@@ -132,10 +132,13 @@ namespace ams::secmon::smc {
}
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;
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());
}
@@ -146,17 +149,19 @@ namespace ams::secmon::smc {
pkg1::MemorySize memory_size = pkg1::MemorySize_4GB;
util::BitPack32 value = {};
if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) {
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode()));
const auto &bcd = GetBootConfig().data;
const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */
if (bcd.IsDevelopmentFunctionEnabled()) {
value.Set<KernelConfiguration::Flags1>(bcd.GetKernelFlags1());
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. */
const auto &sc = GetSecmonConfiguration();
value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size);
if (!sc.DisableUserModeExceptionHandlers()) {
value.Set<KernelConfiguration::EnableUserExceptionHandlers>(true);
@@ -169,6 +174,27 @@ namespace ams::secmon::smc {
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 bool g_set_true_target_firmware = false;
@@ -178,7 +204,7 @@ namespace ams::secmon::smc {
args.r[1] = GetBootConfig().signed_data.IsProgramVerificationDisabled();
break;
case ConfigItem::DramId:
args.r[1] = fuse::GetDramId();
args.r[1] = GetDramIdAdjusted(); /* Nintendo: fuse::GetDramId() */
break;
case ConfigItem::SecurityEngineInterruptNumber:
args.r[1] = SecurityEngineUserInterruptId;
@@ -245,6 +271,9 @@ namespace ams::secmon::smc {
std::memcpy(std::addressof(args.r[1]), std::addressof(tmp_hash), sizeof(tmp_hash));
}
break;
case ConfigItem::Unknown18:
args.r[1] = GetBootConfig().data.GetUnknown70();
break;
case ConfigItem::ExosphereApiVersion:
/* Get information about the current exosphere version. */
if (kern || g_set_true_target_firmware) {
@@ -471,9 +500,18 @@ namespace ams::secmon::smc {
/* For exosphere's usage. */
pkg1::MemorySize GetPhysicalMemorySize() {
const auto dram_id = fuse::GetDramId();
AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count);
return DramIdToMemorySize[dram_id];
const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
const u32 mem_size = reg::Read(MC + MC_EMEM_CFG) & 0x3FFF;
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

@@ -38,6 +38,7 @@ namespace ams::secmon::smc {
RegulatorType = 15,
DeviceUniqueKeyGeneration = 16,
Package2Hash = 17,
Unknown18 = 18,
/* Extension config items for exosphere. */
ExosphereApiVersion = 65000,

View File

@@ -23,17 +23,17 @@ namespace ams::nxboot {
alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSource[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */
0x82, 0xE2, 0x0A, 0x59, 0x67, 0xDF, 0xBF, 0x51, 0x47, 0x62, 0x11, 0xF2, 0x41, 0xD3, 0xEE, 0x13
0x08, 0x11, 0xF7, 0xE8, 0x76, 0x9E, 0xA3, 0xD5, 0x3A, 0x3D, 0x7A, 0x68, 0x1A, 0x24, 0x2A, 0x99
};
alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSourceDev[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */
0x2E, 0x27, 0x44, 0xEA, 0x32, 0xF8, 0x2C, 0xF0, 0x6F, 0xCA, 0xCD, 0x77, 0xAE, 0xAE, 0x1A, 0x1B
0x2B, 0xCD, 0xE7, 0xA4, 0x93, 0x12, 0x0A, 0x72, 0x64, 0x2B, 0x9E, 0xA4, 0xC2, 0x9F, 0xED, 0x13
};
alignas(se::AesBlockSize) constexpr inline const u8 EristaMasterKekSource[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */
0x15, 0xAC, 0x96, 0x34, 0xF5, 0x32, 0x56, 0x68, 0xFE, 0x5B, 0x9D, 0xD7, 0xED, 0x19, 0xB7, 0x8E
0x92, 0xC8, 0x9C, 0x8A, 0x58, 0xE6, 0xE7, 0xB6, 0xE4, 0x27, 0xE2, 0x31, 0xEF, 0x4B, 0xD8, 0x82
};
alignas(se::AesBlockSize) constexpr inline const u8 KeyblobKeySource[se::AesBlockSize] = {
@@ -76,6 +76,7 @@ namespace ams::nxboot {
{ 0xA3, 0x6B, 0x0A, 0xB5, 0x6F, 0x57, 0x4C, 0x5E, 0x00, 0xFD, 0x56, 0x21, 0xF5, 0x06, 0x6B, 0xD1 }, /* 20.0.0 Device Master Key Source Source. */
{ 0xF9, 0x62, 0x05, 0x99, 0xE0, 0xB9, 0xA6, 0x9B, 0x9D, 0xAA, 0xB4, 0x12, 0x0B, 0x0F, 0xF5, 0x8F }, /* 21.0.0 Device Master Key Source Source. */
{ 0xF8, 0xF4, 0x22, 0xA4, 0x34, 0xAE, 0x0E, 0x0C, 0x4D, 0x5C, 0x5B, 0xA1, 0x1B, 0x46, 0x1C, 0x78 }, /* 22.0.0 Device Master Key Source Source. */
{ 0x95, 0xC1, 0xAC, 0xB7, 0xB2, 0xCA, 0x9B, 0x8C, 0xD5, 0xEA, 0x40, 0xD9, 0x9C, 0xD2, 0x7C, 0x47 }, /* 23.0.0 Device Master Key Source Source. */
};
alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSources[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = {
@@ -98,6 +99,7 @@ namespace ams::nxboot {
{ 0xDA, 0xFB, 0x61, 0x39, 0x48, 0x2D, 0xC2, 0x7E, 0x0D, 0x8E, 0x8F, 0x98, 0x57, 0x20, 0xB8, 0x15 }, /* 20.0.0 Device Master Kek Source. */
{ 0x92, 0xBF, 0x37, 0x80, 0x0E, 0x79, 0x56, 0x8C, 0x57, 0x75, 0x72, 0x0A, 0x48, 0xD8, 0x15, 0x39 }, /* 21.0.0 Device Master Kek Source. */
{ 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 }, /* 22.0.0 Device Master Kek Source. */
{ 0xA0, 0xC8, 0x44, 0x39, 0x8A, 0x1F, 0xD8, 0x6A, 0x3D, 0x0A, 0x23, 0xFF, 0x43, 0xA6, 0x95, 0x80 }, /* 23.0.0 Device Master Kek Source. */
};
alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSourcesDev[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = {
@@ -120,6 +122,7 @@ namespace ams::nxboot {
{ 0x09, 0x12, 0x4F, 0x26, 0x90, 0xB9, 0xA6, 0xF5, 0xA5, 0x18, 0x74, 0xB6, 0x8D, 0x80, 0x59, 0x3D }, /* 20.0.0 Device Master Kek Source. */
{ 0x7A, 0x4C, 0x38, 0xB7, 0x03, 0x6B, 0x1E, 0x81, 0x20, 0x53, 0x14, 0x99, 0xA4, 0x21, 0x92, 0x9F }, /* 21.0.0 Device Master Kek Source. */
{ 0xF3, 0xBC, 0xB5, 0xB5, 0x5F, 0x01, 0x50, 0x2B, 0x69, 0x69, 0x3A, 0x6B, 0xF9, 0x2C, 0x11, 0x9F }, /* 22.0.0 Device Master Kek Source. */
{ 0x54, 0xAD, 0x79, 0x15, 0x11, 0x7C, 0x1E, 0x52, 0xBF, 0x2E, 0x40, 0xBB, 0x8B, 0x11, 0x54, 0x38 }, /* 23.0.0 Device Master Kek Source. */
};
alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySources[pkg1::KeyGeneration_Count][se::AesBlockSize] = {
@@ -145,6 +148,7 @@ namespace ams::nxboot {
{ 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 }, /* Master key 12 encrypted with Master key 13. */
{ 0xF7, 0x92, 0xC0, 0xEC, 0xF3, 0xA4, 0x8C, 0xB7, 0x0D, 0xB3, 0xF3, 0xAB, 0x10, 0x9B, 0x18, 0xBA }, /* Master key 13 encrypted with Master key 14. */
{ 0x14, 0xCB, 0x60, 0x29, 0x3D, 0xE0, 0xFB, 0xF2, 0x5B, 0x60, 0xB6, 0xC5, 0x2E, 0x77, 0x8F, 0x98 }, /* Master key 14 encrypted with Master key 15. */
{ 0x26, 0x87, 0xDF, 0x21, 0x44, 0xD4, 0x5F, 0x4E, 0x61, 0x03, 0x9E, 0xF3, 0x40, 0x04, 0xC3, 0x87 }, /* Master key 15 encrypted with Master key 16. */
};
alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySourcesDev[pkg1::KeyGeneration_Count][se::AesBlockSize] = {
@@ -170,6 +174,7 @@ namespace ams::nxboot {
{ 0x94, 0x46, 0x3B, 0xFA, 0x7D, 0xB9, 0xE2, 0x94, 0xC2, 0x9D, 0xB9, 0xA4, 0xB2, 0x56, 0xCA, 0xFE }, /* Master key 12 encrypted with Master key 13. */
{ 0x74, 0xB2, 0x5F, 0xA0, 0x4B, 0x74, 0x6D, 0x47, 0x5B, 0xA9, 0xF5, 0x26, 0x46, 0xD7, 0x4B, 0x6E }, /* Master key 13 encrypted with Master key 14. */
{ 0x97, 0xB3, 0x61, 0x88, 0x5C, 0x0D, 0xA1, 0x38, 0x73, 0xA4, 0x2F, 0x1A, 0x46, 0xA1, 0x09, 0xBF }, /* Master key 14 encrypted with Master key 15. */
{ 0xA6, 0x25, 0x12, 0x6D, 0xA1, 0x12, 0x1F, 0x15, 0x08, 0x2F, 0x30, 0x5F, 0xCB, 0x7D, 0x32, 0x82 }, /* Master key 15 encrypted with Master key 16. */
};
alignas(se::AesBlockSize) constinit u8 MasterKeys[pkg1::OldMasterKeyCount][se::AesBlockSize] = {};

View File

@@ -80,7 +80,7 @@ namespace ams::nxboot {
}
/* Check that the key generation is one that we can use. */
static_assert(pkg1::KeyGeneration_Count == 22);
static_assert(pkg1::KeyGeneration_Count == 23);
if (key_generation >= pkg1::KeyGeneration_Count) {
return false;
}

View File

@@ -269,6 +269,8 @@ namespace ams::nxboot {
return ams::TargetFirmware_21_0_0;
} else if (std::memcmp(package1 + 0x10, "20260123", 8) == 0) {
return ams::TargetFirmware_22_0_0;
} else if (std::memcmp(package1 + 0x10, "20260730", 8) == 0) {
return ams::TargetFirmware_23_0_0;
}
break;
default:
@@ -545,6 +547,12 @@ namespace ams::nxboot {
} else {
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) {
if (!emummc_enabled) {
if (entry.value[0] == '1') {

View File

@@ -194,6 +194,12 @@ namespace ams::nxboot {
FsVersion_22_0_0,
FsVersion_22_0_0_Exfat,
FsVersion_22_5_0,
FsVersion_22_5_0_Exfat,
FsVersion_23_0_0,
FsVersion_23_0_0_Exfat,
FsVersion_Count,
};
@@ -302,6 +308,12 @@ namespace ams::nxboot {
{ 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 */
{ 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 */
{ 0x34, 0x38, 0x3E, 0xE7, 0x99, 0x92, 0x63, 0x40 }, /* FsVersion_23_0_0 */
{ 0xFD, 0xAF, 0x16, 0x32, 0x88, 0xE1, 0x08, 0x05 }, /* FsVersion_23_0_0_Exfat */
};
const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) {
@@ -716,15 +728,27 @@ namespace ams::nxboot {
AddPatch(fs_meta, 0x18AD40, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_22_0_0:
case FsVersion_22_5_0:
AddPatch(fs_meta, 0x1B023D, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1B0255, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x183060, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_22_0_0_Exfat:
case FsVersion_22_5_0_Exfat:
AddPatch(fs_meta, 0x1BB42D, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1BB445, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x18E250, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_23_0_0:
AddPatch(fs_meta, 0x1B36BD, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1B36D5, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x186340, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_23_0_0_Exfat:
AddPatch(fs_meta, 0x1BE8BD, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1BE8D5, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x191540, NogcPatch1, sizeof(NogcPatch1));
break;
default:
break;
}

View File

@@ -1355,6 +1355,9 @@ namespace ams::nxboot {
uint32_t emc_zcal_wait_cnt_new = dst_timing->burst_regs.emc_zcal_wait_cnt;
emc_zcal_wait_cnt_old &= ~0x7ff;
emc_zcal_wait_cnt_new &= ~0x7ff;
/* TODO: Unused variable. */
AMS_UNUSED(emc_zcal_wait_cnt_old);
if (dram_type == DRAM_TYPE_LPDDR4) {
zq_wait_long = std::max<u32>(1, util::DivideUp(1000000, destination_clock_period));

View File

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

View File

@@ -61,14 +61,15 @@ namespace ams::pkg1 {
}
struct BootConfigData {
u32 version;
u32 reserved_04;
u64 version;
u32 reserved_08;
u32 reserved_0C;
u8 flags1[0x10];
u8 flags0[0x10];
u64 initial_tsc_value;
u8 padding_38[0x200 - 0x38];
u8 padding_38[0x38];
u64 unknown_70;
u8 padding_78[0x200 - 0x78];
constexpr bool IsDevelopmentFunctionEnabled() const {
return (this->flags1[0] & (1 << 1)) != 0;
@@ -97,13 +98,16 @@ namespace ams::pkg1 {
constexpr u64 GetInitialTscValue() const {
return this->IsInitialTscValueValid() ? this->initial_tsc_value : 0;
}
constexpr u64 GetUnknown70() const {
return this->unknown_70;
}
};
static_assert(util::is_pod<BootConfigData>::value);
static_assert(sizeof(BootConfigData) == 0x200);
struct BootConfigSignedData {
u32 version;
u32 reserved_04;
u64 version;
u8 flags;
u8 reserved_09[0x10 - 9];
u8 ecid[0x10];

View File

@@ -42,6 +42,7 @@ namespace ams::pkg1 {
KeyGeneration_20_0_0 = 0x13,
KeyGeneration_21_0_0 = 0x14,
KeyGeneration_22_0_0 = 0x15,
KeyGeneration_23_0_0 = 0x16,
KeyGeneration_Count,

View File

@@ -24,7 +24,7 @@ namespace ams::pkg2 {
constexpr inline int PayloadCount = 3;
constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x18 in Nintendo's code. */
constexpr inline int CurrentBootloaderVersion = 0x17;
constexpr inline int CurrentBootloaderVersion = 0x18;
struct Package2Meta {
using Magic = util::FourCC<'P','K','2','1'>;

View File

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

View File

@@ -177,6 +177,7 @@ namespace ams::fuse {
}
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
TargetFirmware_23_0_0,
TargetFirmware_22_0_0,
TargetFirmware_21_0_0,
TargetFirmware_20_0_0,

View File

@@ -104,7 +104,10 @@ namespace ams::se {
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 0) : 0;
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 1) : 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),
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));

View File

@@ -81,6 +81,7 @@ namespace ams::kern::arch::arm64::cpu {
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(SpEl0, sp_el0)
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Dfr0El1, id_aa64dfr0_el1)
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Mmfr0El1, id_aa64mmfr0_el1)
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmcrEl0, pmcr_el0)
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmUserEnrEl0, pmuserenr_el0)

View File

@@ -19,6 +19,7 @@
#include <mesosphere/kern_k_page_table_base.hpp>
#include <mesosphere/kern_k_page_group.hpp>
#include <mesosphere/kern_k_page_table_manager.hpp>
#include <mesosphere/init/kern_init_slab_setup.hpp>
namespace ams::kern::arch::arm64 {
@@ -94,10 +95,10 @@ namespace ams::kern::arch::arm64 {
return KPageTable::GetBlockSize(static_cast<KPageTable::BlockType>(KPageTable::GetBlockType(alignment) + 1));
}
public:
/* TODO: How should this size be determined. Does the KProcess slab count need to go in a header as a define? */
static constexpr size_t NumTtbr0Entries = 81;
static constexpr size_t NumPTEntries = ::ams::kern::init::SlabCountKProcess + 1; /* +1 for kernel. */
private:
static constinit inline const volatile u64 s_ttbr0_entries[NumTtbr0Entries] = {};
static constinit inline const volatile u64 s_ttbr0_entries[NumPTEntries] = {};
static constinit inline const volatile u64 s_tcr_el1_entries[NumPTEntries] = {};
private:
KPageTableManager *m_manager;
u8 m_asid;
@@ -188,6 +189,12 @@ namespace ams::kern::arch::arm64 {
return s_ttbr0_entries[0];
}
static const volatile u64 &GetTcrEL1Entry(size_t index) { return s_tcr_el1_entries[index]; }
static ALWAYS_INLINE u64 GetKernelTcrEL1() {
return s_tcr_el1_entries[0];
}
static ALWAYS_INLINE void ActivateKernel() {
/* Activate, using asid 0 and process id = 0xFFFFFFFF */
cpu::SwitchProcess(GetKernelTtbr0(), 0xFFFFFFFF);
@@ -198,7 +205,7 @@ namespace ams::kern::arch::arm64 {
}
NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index);
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index);
void Finalize();
static void NoteUpdatedCallback(const void *pt) {

View File

@@ -28,10 +28,15 @@ namespace ams::kern::arch::arm64 {
m_page_table.ActivateProcess(process_index, id);
}
Result Initialize(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) {
Result Initialize(ams::svc::CreateProcessParameterFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) {
R_RETURN(m_page_table.InitializeForProcess(flags, from_back, pool, code_address, code_size, system_resource, resource_limit, process_index));
}
static ALWAYS_INLINE u64 GetProcessTcrEl1(size_t process_index) {
/* The kernel's root table is entry zero; processes are indexed from one. */
return KPageTable::GetTcrEL1Entry(process_index + 1);
}
void Finalize() { m_page_table.Finalize(); }
ALWAYS_INLINE KScopedLightLock AcquireDeviceMapLock() {
@@ -302,19 +307,25 @@ namespace ams::kern::arch::arm64 {
bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return m_page_table.CanContain(addr, size, state); }
bool CanContain(KProcessAddress addr, size_t size, ams::svc::MemoryState state) const { return m_page_table.CanContain(addr, size, state); }
KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); }
KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); }
KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); }
KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); }
KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); }
KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); }
bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const { return m_page_table.IsInShadowStackRegion(addr, size); }
bool IsInShadowStackRegion(KProcessAddress addr) const { return m_page_table.IsInShadowStackRegion(addr); }
bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { return m_page_table.IsSafeUserPointer(addr, size); }
size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); }
size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); }
size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); }
size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); }
size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); }
size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); }
KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); }
KProcessAddress GetShadowStackRegionStart() const { return m_page_table.GetShadowStackRegionStart(); }
KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); }
KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); }
KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); }
KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); }
KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); }
size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); }
size_t GetShadowStackRegionSize() const { return m_page_table.GetShadowStackRegionSize(); }
size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); }
size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); }
size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); }
size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); }
size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); }
size_t GetAliasRegionExtraSize() const { return m_page_table.GetAliasRegionExtraSize(); }

View File

@@ -77,7 +77,7 @@ namespace ams::kern::arch::arm64 {
static bool CopyMemoryFromUserSize32BitWithSupervisorAccess(void *dst, const void *src) {
/* Check that the address is within the valid userspace range. */
if (const uintptr_t src_uptr = reinterpret_cast<uintptr_t>(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion39Size) {
if (const uintptr_t src_uptr = reinterpret_cast<uintptr_t>(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion42Size) {
return false;
}

View File

@@ -51,9 +51,7 @@ namespace ams::kern::board::nintendo::nx {
static NOINLINE u32 GetCreateProcessMemoryPool();
/* Randomness. */
static void GenerateRandom(u64 *dst, size_t count);
static u64 GenerateRandomRange(u64 min, u64 max);
static u64 GenerateRandomU64();
static void GenerateRandomBytesForUninitialized(void *dst, size_t size);
/* Privileged Access. */
static void ReadWriteRegisterPrivileged(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);

View File

@@ -18,6 +18,25 @@
#include <mesosphere/kern_k_slab_heap.hpp>
namespace ams::kern::init {
/* Constexpr counts. */
constexpr size_t SlabCountKProcess = 80;
constexpr size_t SlabCountKThread = 800;
constexpr size_t SlabCountKEvent = 900;
constexpr size_t SlabCountKInterruptEvent = 100;
constexpr size_t SlabCountKPort = 384;
constexpr size_t SlabCountKSharedMemory = 80;
constexpr size_t SlabCountKTransferMemory = 200;
constexpr size_t SlabCountKCodeMemory = 10;
constexpr size_t SlabCountKDeviceAddressSpace = 300;
constexpr size_t SlabCountKSession = 1133;
constexpr size_t SlabCountKLightSession = 100;
constexpr size_t SlabCountKObjectName = 7;
constexpr size_t SlabCountKResourceLimit = 5;
constexpr size_t SlabCountKDebug = cpu::NumCores;
constexpr size_t SlabCountKIoPool = 1;
constexpr size_t SlabCountKIoRegion = 6;
constexpr size_t SlabcountKSessionRequestMappings = 40;
struct KSlabResourceCounts {
size_t num_KProcess;

View File

@@ -24,7 +24,7 @@ namespace ams::kern {
enum Type {
Type_MapSmall = 0,
Type_MapLarge = 1,
Type_Map39Bit = 2,
Type_MapHuge = 2,
Type_Heap = 3,
Type_Stack = 4,
Type_Alias = 5,
@@ -37,8 +37,8 @@ namespace ams::kern {
size_t m_size;
Type m_type;
public:
static uintptr_t GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, Type type, size_t code_size);
static size_t GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, Type type);
static uintptr_t GetAddressSpaceStart(ams::svc::CreateProcessParameterFlag flags, Type type, size_t code_size);
static size_t GetAddressSpaceSize(ams::svc::CreateProcessParameterFlag flags, Type type);
static void SetAddressSpaceSize(size_t width, Type type, size_t size);

View File

@@ -119,6 +119,8 @@ namespace ams::kern {
KMemoryState_Insecure = ams::svc::MemoryState_Insecure | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped | KMemoryState_FlagCanChangeAttribute
| KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanQueryPhysical
| KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
KMemoryState_ShadowStack = ams::svc::MemoryState_ShadowStack,
};
#if 1
@@ -147,6 +149,7 @@ namespace ams::kern {
static_assert(KMemoryState_CodeOut == 0x04402015);
static_assert(KMemoryState_Coverage == 0x00002016); /* TODO: Is this correct? */
static_assert(KMemoryState_Insecure == 0x055C3817);
static_assert(KMemoryState_ShadowStack == 0x0000001A);
#endif
enum KMemoryPermission : u8 {
@@ -211,15 +214,15 @@ namespace ams::kern {
uintptr_t m_address;
size_t m_size;
KMemoryState m_state;
u16 m_device_disable_merge_left_count;
u16 m_device_disable_merge_right_count;
u16 m_ipc_lock_count;
u16 m_device_use_count;
u16 m_ipc_disable_merge_count;
KMemoryPermission m_permission;
KMemoryAttribute m_attribute;
KMemoryPermission m_original_permission;
u16 m_ipc_lock_count;
u16 m_device_use_count;
KMemoryBlockDisableMergeAttribute m_disable_merge_attribute;
u16 m_ipc_disable_merge_count;
u16 m_device_disable_merge_left_count;
u16 m_device_disable_merge_right_count;
constexpr ams::svc::MemoryInfo GetSvcMemoryInfo() const {
return {
@@ -365,15 +368,15 @@ namespace ams::kern {
.m_address = GetInteger(this->GetAddress()),
.m_size = this->GetSize(),
.m_state = m_memory_state,
.m_device_disable_merge_left_count = m_device_disable_merge_left_count,
.m_device_disable_merge_right_count = m_device_disable_merge_right_count,
.m_ipc_lock_count = m_ipc_lock_count,
.m_device_use_count = m_device_use_count,
.m_ipc_disable_merge_count = m_ipc_disable_merge_count,
.m_permission = m_permission,
.m_attribute = m_attribute,
.m_original_permission = m_original_permission,
.m_ipc_lock_count = m_ipc_lock_count,
.m_device_use_count = m_device_use_count,
.m_disable_merge_attribute = m_disable_merge_attribute,
.m_ipc_disable_merge_count = m_ipc_disable_merge_count,
.m_device_disable_merge_left_count = m_device_disable_merge_left_count,
.m_device_disable_merge_right_count = m_device_disable_merge_right_count,
};
}
public:

View File

@@ -90,10 +90,11 @@ namespace ams::kern {
};
enum RegionType {
RegionType_KernelMap = 0,
RegionType_Stack = 1,
RegionType_Alias = 2,
RegionType_Heap = 3,
RegionType_KernelMap = 0,
RegionType_Stack = 1,
RegionType_Alias = 2,
RegionType_Heap = 3,
RegionType_ShadowStack = 4,
RegionType_Count,
};
@@ -150,14 +151,14 @@ namespace ams::kern {
static constexpr u32 DefaultMemoryIgnoreAttr = KMemoryAttribute_IpcLocked | KMemoryAttribute_DeviceShared;
static constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag as_type) {
switch (static_cast<ams::svc::CreateProcessFlag>(as_type & ams::svc::CreateProcessFlag_AddressSpaceMask)) {
case ams::svc::CreateProcessFlag_AddressSpace64Bit:
static constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag as_type) {
switch (static_cast<ams::svc::CreateProcessParameterFlag>(as_type & ams::svc::CreateProcessParameterFlag_AddressSpaceMask)) {
case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39:
return 39;
case ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated:
case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36:
return 36;
case ams::svc::CreateProcessFlag_AddressSpace32Bit:
case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias:
case ams::svc::CreateProcessParameterFlag_AddressSpace32Bit:
case ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved:
return 32;
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
}
@@ -196,7 +197,6 @@ namespace ams::kern {
KPageTableImpl m_impl;
KMemoryBlockManager m_memory_block_manager;
u32 m_allocate_option;
u32 m_address_space_width;
bool m_is_kernel;
bool m_enable_aslr;
bool m_enable_device_address_space_merge;
@@ -212,23 +212,24 @@ namespace ams::kern {
public:
constexpr explicit KPageTableBase(util::ConstantInitializeTag)
: m_address_space_start(Null<KProcessAddress>), m_address_space_end(Null<KProcessAddress>),
m_region_starts{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
m_region_ends{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
m_region_starts{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
m_region_ends{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
m_current_heap_end(Null<KProcessAddress>), m_alias_code_region_start(Null<KProcessAddress>),
m_alias_code_region_end(Null<KProcessAddress>), m_code_region_start(Null<KProcessAddress>), m_code_region_end(Null<KProcessAddress>),
m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(), m_alias_region_extra_size(),
m_general_lock(), m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize),
m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(),
m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(),
m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value()
m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(),
m_mapped_ipc_server_memory(), m_alias_region_extra_size(), m_general_lock(), m_map_physical_memory_lock(),
m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize),
m_allocate_option(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(),
m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(),
m_cached_physical_heap_region(), m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value()
{
/* ... */
}
explicit KPageTableBase() { /* ... */ }
NOINLINE void InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
void Finalize();
@@ -247,6 +248,22 @@ namespace ams::kern {
return this->Contains(addr, size) && m_region_starts[RegionType_Alias] <= addr && addr + size - 1 <= m_region_ends[RegionType_Alias] - 1;
}
constexpr bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const {
const auto start = m_region_starts[RegionType_ShadowStack];
const auto end = m_region_ends[RegionType_ShadowStack];
return start != end && addr < end && start < addr + size;
}
constexpr bool IsInShadowStackRegion(KProcessAddress addr) const {
const auto start = m_region_starts[RegionType_ShadowStack];
const auto end = m_region_ends[RegionType_ShadowStack];
return start <= addr && addr < end;
}
constexpr bool IsSafeUserPointer(KProcessAddress addr, size_t size) const {
return this->Contains(addr, size) && !this->IsInShadowStackRegion(addr, size);
}
bool IsInUnsafeAliasRegion(KProcessAddress addr, size_t size) const {
/* Even though Unsafe physical memory is KMemoryState_Normal, it must be mapped inside the alias code region. */
return this->CanContain(addr, size, ams::svc::MemoryState_AliasCode);
@@ -490,19 +507,21 @@ namespace ams::kern {
public:
KProcessAddress GetAddressSpaceStart() const { return m_address_space_start; }
KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; }
KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; }
KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; }
KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; }
KProcessAddress GetShadowStackRegionStart() const { return m_region_starts[RegionType_ShadowStack]; }
KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; }
KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; }
KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; }
KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; }
KProcessAddress GetAliasCodeRegionStart() const { return m_alias_code_region_start; }
size_t GetAddressSpaceSize() const { return m_address_space_end - m_address_space_start; }
size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; }
size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; }
size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; }
size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; }
size_t GetShadowStackRegionSize() const { return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack]; }
size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; }
size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; }
size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; }
size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; }
size_t GetAliasCodeRegionSize() const { return m_alias_code_region_end - m_alias_code_region_start; }

View File

@@ -113,6 +113,7 @@ namespace ams::kern {
u64 m_running_thread_idle_counts[cpu::NumCores];
u64 m_running_thread_switch_counts[cpu::NumCores];
KThread *m_pinned_threads[cpu::NumCores];
s64 m_exit_tag;
util::Atomic<s64> m_cpu_time;
util::Atomic<s64> m_num_process_switches;
util::Atomic<s64> m_num_thread_switches;
@@ -142,11 +143,11 @@ namespace ams::kern {
m_pinned_threads[core_id] = nullptr;
}
public:
explicit KProcess() : m_is_initialized(false) { /* ... */ }
explicit KProcess() : m_is_initialized(false), m_exit_tag(-1ll) { /* ... */ }
Result Initialize(const ams::svc::CreateProcessParameter &params, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal);
Result Initialize(const ams::svc::CreateProcessParameter &params, svc::KUserPointer<const u32 *> caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool);
void Exit();
void Exit(s64 exit_tag);
constexpr const char *GetName() const { return m_name; }
@@ -155,19 +156,22 @@ namespace ams::kern {
constexpr u64 GetProcessId() const { return m_process_id; }
constexpr State GetState() const { return m_state; }
constexpr s64 GetExitTag() const { return m_exit_tag; }
constexpr u64 GetCoreMask() const { return m_capabilities.GetCoreMask(); }
constexpr u64 GetPhysicalCoreMask() const { return m_capabilities.GetPhysicalCoreMask(); }
constexpr u64 GetPriorityMask() const { return m_capabilities.GetPriorityMask(); }
constexpr u32 GetIntendedKernelMajorVersion() const { return m_capabilities.GetIntendedKernelMajorVersion(); }
constexpr s32 GetIdealCoreId() const { return m_ideal_core_id; }
constexpr void SetIdealCoreId(s32 core_id) { m_ideal_core_id = core_id; }
constexpr bool CheckThreadPriority(s32 prio) const { return ((1ul << prio) & this->GetPriorityMask()) != 0; }
constexpr u32 GetCreateProcessFlags() const { return m_flags; }
constexpr u32 GetCreateProcessParameterFlags() const { return m_flags; }
constexpr bool Is64Bit() const { return m_flags & ams::svc::CreateProcessFlag_Is64Bit; }
constexpr bool Is64Bit() const { return m_flags & ams::svc::CreateProcessParameterFlag_64Bit; }
constexpr KProcessAddress GetEntryPoint() const { return m_code_address; }
@@ -184,7 +188,7 @@ namespace ams::kern {
constexpr bool IsSuspended() const { return m_is_suspended; }
constexpr void SetSuspended(bool suspended) { m_is_suspended = suspended; }
Result Terminate();
Result Terminate(s64 exit_tag);
constexpr bool IsTerminated() const {
return m_state == State_Terminated;
@@ -215,6 +219,7 @@ namespace ams::kern {
}
u32 GetAllocateOption() const { return m_page_table.GetAllocateOption(); }
size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); }
ThreadList &GetThreadList() { return m_thread_list; }
const ThreadList &GetThreadList() const { return m_thread_list; }
@@ -409,6 +414,10 @@ namespace ams::kern {
this->NotifyAvailable();
}
}
void SetExitTag(s64 exit_tag) {
m_exit_tag = exit_tag;
}
ALWAYS_INLINE Result InitializeHandleTable(s32 size) {
/* Try to initialize the handle table. */

View File

@@ -37,13 +37,12 @@ namespace ams::kern {
public:
/* This can be overridden as needed. */
static constexpr size_t SecureAppletMemorySize = 0;
protected:
/* Nintendo uses std::mt19937_t for randomness. */
/* To save space (and because mt19337_t isn't secure anyway), */
/* We will use TinyMT. */
static constinit inline bool s_uninitialized_random_generator{true};
static constinit inline util::TinyMT s_random_generator{util::ConstantInitialize};
static constinit inline KSpinLock s_random_lock;
private:
/* Randomness helpers. */
static void InitializeRandomGenerator(const void *seed, size_t size);
static void ReseedRandomGeneratorInternal();
static u32 GenerateRandomU32();
static u64 GenerateRandomU64Internal();
public:
class Init {
private:
@@ -66,7 +65,7 @@ namespace ams::kern {
static u64 GenerateRandomRange(u64 min, u64 max);
};
protected:
static NOINLINE void InitializePhase1Base(u64 seed);
static NOINLINE void InitializePhase1Base(const void *seed, size_t size);
public:
/* Initialization. */
static NOINLINE void ConfigureKTargetSystem();
@@ -78,6 +77,10 @@ namespace ams::kern {
static void GenerateRandom(u64 *dst, size_t count);
static u64 GenerateRandomRange(u64 min, u64 max);
static u64 GenerateRandomU64();
static void ReseedRandomGenerator();
/* Obtains random bytes while the generator is not yet initialized. Board-provided. */
static void GenerateRandomBytesForUninitialized(void *dst, size_t size);
/* Register access Access. */
static Result ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);

View File

@@ -26,6 +26,7 @@ namespace ams::kern {
private:
struct KTargetSystemData {
bool is_not_debug_mode;
bool is_not_debug_mode2;
bool disable_debug_logging;
bool disable_user_exception_handlers;
bool disable_debug_memory_fill;
@@ -37,6 +38,7 @@ namespace ams::kern {
static inline constinit bool s_is_uninitialized = true;
static inline constinit const volatile KTargetSystemData s_data = {
.is_not_debug_mode = false,
.is_not_debug_mode2 = false,
.disable_debug_logging = false,
.disable_user_exception_handlers = false,
.disable_debug_memory_fill = false,
@@ -48,6 +50,7 @@ namespace ams::kern {
static ALWAYS_INLINE void SetInitialized() { s_is_uninitialized = false; }
public:
static ALWAYS_INLINE bool IsDebugMode() { return !(s_is_uninitialized | s_data.is_not_debug_mode); }
static ALWAYS_INLINE bool IsDebugMode2() { return !(s_is_uninitialized | s_data.is_not_debug_mode2); }
static ALWAYS_INLINE bool IsDebugLoggingEnabled() { return !(s_is_uninitialized | s_data.disable_debug_logging); }
static ALWAYS_INLINE bool IsUserExceptionHandlersEnabled() { return !(s_is_uninitialized | s_data.disable_user_exception_handlers); }
static ALWAYS_INLINE bool IsDebugMemoryFillEnabled() { return !(s_is_uninitialized | s_data.disable_debug_memory_fill); }

View File

@@ -29,6 +29,7 @@ namespace ams::kern {
class KProcess;
class KConditionVariable;
class KAddressArbiter;
class KPageBuffer;
using KThreadFunction = void (*)(uintptr_t);
@@ -305,6 +306,8 @@ namespace ams::kern {
u32 *m_light_ipc_data;
KProcessAddress m_tls_address;
void *m_tls_heap_address;
KProcessAddress m_shadow_stack_address;
KPageBuffer *m_shadow_stack_page;
KLightLock m_activity_pause_lock;
SyncObjectBuffer m_sync_object_buffer;
s64 m_schedule_count;
@@ -341,18 +344,19 @@ namespace ams::kern {
bool m_debug_attached;
s8 m_priority_inheritance_count;
bool m_resource_limit_release_hint;
bool m_debug_unknown5;
public:
constexpr explicit KThread(util::ConstantInitializeTag)
: KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>(util::ConstantInitialize), KTimerTask(util::ConstantInitialize),
m_process_list_node{}, m_condvar_arbiter_tree_node{util::ConstantInitialize}, m_priority{-1}, m_condvar_tree{}, m_condvar_key{},
m_caller_save_fpu_registers{}, m_virtual_affinity_mask{}, m_physical_affinity_mask{}, m_thread_id{}, m_cpu_time{0}, m_address_key{Null<KProcessAddress>}, m_parent{},
m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null<KProcessAddress>}, m_tls_heap_address{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize},
m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null<KProcessAddress>}, m_tls_heap_address{}, m_shadow_stack_address{Null<KProcessAddress>}, m_shadow_stack_page{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize},
m_schedule_count{}, m_last_scheduled_tick{}, m_per_core_priority_queue_entry{}, m_wait_queue{}, m_held_lock_info_list{}, m_waiting_lock_info{},
m_pinned_waiter_list{}, m_debug_params{}, m_closed_object{}, m_address_key_value{}, m_suspend_request_flags{}, m_suspend_allowed_flags{}, m_synced_index{},
m_wait_result{svc::ResultNoSynchronizationObject()}, m_debug_exception_result{ResultSuccess()}, m_base_priority{}, m_base_priority_on_unpin{},
m_physical_ideal_core_id{}, m_virtual_ideal_core_id{}, m_num_kernel_waiters{}, m_current_core_id{}, m_core_id{}, m_original_physical_affinity_mask{},
m_original_physical_ideal_core_id{}, m_num_core_migration_disables{}, m_thread_state{}, m_termination_requested{false}, m_wait_cancelled{},
m_cancellable{}, m_signaled{}, m_initialized{}, m_debug_attached{}, m_priority_inheritance_count{}, m_resource_limit_release_hint{}
m_cancellable{}, m_signaled{}, m_initialized{}, m_debug_attached{}, m_priority_inheritance_count{}, m_resource_limit_release_hint{}, m_debug_unknown5{}
{
/* ... */
}
@@ -683,6 +687,9 @@ namespace ams::kern {
constexpr void SetDebugAttached() { m_debug_attached = true; }
constexpr bool IsAttachedToDebugger() const { return m_debug_attached; }
constexpr void SetDebugUnknown5(bool value) { m_debug_unknown5 = value; }
constexpr bool IsDebugUnknown5() const { return m_debug_unknown5; }
void AddCpuTime(s32 core_id, s64 amount) {
m_cpu_time += amount;
/* TODO: Debug kernels track per-core tick counts. Should we? */

View File

@@ -108,6 +108,8 @@ $(OFILES_SRC) : $(HFILES_BIN)
kern_libc_generic.o: CFLAGS += -fno-builtin
crypto_aes_impl.arch.arm64.o: CXXFLAGS := $(filter-out -mgeneral-regs-only,$(CXXFLAGS))
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------

View File

@@ -220,6 +220,8 @@ namespace ams::kern::arch::arm64::cpu {
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override {
MESOSPHERE_UNUSED(interrupt_id);
/* TODO: 23.0.0+ now yields here while m_target_cores doesn't have the current core id bit set. */
/* Evaluate if we should do the same. */
this->ProcessOperation();
m_target_cores &= ~(1ul << GetCurrentCoreId());
return nullptr;

View File

@@ -196,6 +196,7 @@ namespace ams::kern::arch::arm64 {
case EsrEc_Cp14McrMrc:
case EsrEc_Cp14Mrrc:
case EsrEc_SystemInstruction64:
case EsrEc_SveZen:
case EsrEc_BkptInstruction:
case EsrEc_BrkInstruction:
type = ams::svc::ExceptionType_InstructionAbort;
@@ -267,6 +268,7 @@ namespace ams::kern::arch::arm64 {
switch (ec) {
case EsrEc_Unknown:
case EsrEc_IllegalExecution:
case EsrEc_SveZen:
case EsrEc_BkptInstruction:
case EsrEc_BrkInstruction:
{
@@ -379,7 +381,7 @@ namespace ams::kern::arch::arm64 {
}
/* Exit the current process. */
cur_process.Exit();
cur_process.Exit(-1ll);
}
}
@@ -474,6 +476,7 @@ namespace ams::kern::arch::arm64 {
switch (ec) {
case EsrEc_Unknown:
case EsrEc_IllegalExecution:
case EsrEc_SveZen:
case EsrEc_BkptInstruction:
case EsrEc_BrkInstruction:
{
@@ -545,7 +548,7 @@ namespace ams::kern::arch::arm64 {
MESOSPHERE_EXCEPTION_LOG("Exception occurred. ");
/* Exit the current process. */
GetCurrentProcess().Exit();
GetCurrentProcess().Exit(-1ll);
}
/* NOTE: This function is called from ASM. */
@@ -564,6 +567,7 @@ namespace ams::kern::arch::arm64 {
switch ((esr >> 26) & 0x3F) {
case EsrEc_Unknown:
case EsrEc_IllegalExecution:
case EsrEc_SveZen:
case EsrEc_BkptInstruction:
case EsrEc_BrkInstruction:
far = context->pc;

View File

@@ -125,10 +125,10 @@ namespace ams::kern::arch::arm64 {
m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer();
/* Initialize the base page table. */
KPageTableBase::InitializeForKernel(true, table, start, end);
KPageTableBase::InitializeForKernel(table, start, end);
}
Result KPageTable::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) {
Result KPageTable::InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) {
/* Determine our ASID */
m_asid = process_index + 1;
MESOSPHERE_ABORT_UNLESS(0 < m_asid && m_asid < util::size(s_ttbr0_entries));
@@ -144,7 +144,7 @@ namespace ams::kern::arch::arm64 {
const size_t as_width = GetAddressSpaceWidth(flags);
const KProcessAddress as_start = 0;
const KProcessAddress as_end = (1ul << as_width);
R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, pool, GetVoidPointer(ttbr0_virt), as_start, as_end, code_address, code_size, system_resource, resource_limit));
R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, GetVoidPointer(ttbr0_virt), as_start, as_end, pool, code_address, code_size, system_resource, resource_limit));
/* Note that we've updated the table (since we created it). */
this->NoteUpdated();
@@ -729,6 +729,9 @@ namespace ams::kern::arch::arm64 {
}
}
MESOSPHERE_ASSERT(mapped_pages == num_pages);
/* TODO: Unused variable. */
AMS_UNUSED(mapped_pages);
/* Perform what coalescing we can. */
this->MergePages(orig_virt_addr, num_pages, page_list);

View File

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

View File

@@ -74,12 +74,6 @@ namespace ams::kern::board::nintendo::nx {
return value;
}
ALWAYS_INLINE u64 GenerateRandomU64FromSmc() {
u64 value;
smc::GenerateRandomBytes(std::addressof(value), sizeof(value));
return value;
}
ALWAYS_INLINE u64 GetConfigU64(smc::ConfigItem which) {
u64 value;
smc::GetConfig(&value, 1, which);
@@ -363,7 +357,12 @@ namespace ams::kern::board::nintendo::nx {
/* Return (possibly) adjusted size. */
/* NOTE: On 20.0.0+ (and even more-so 21.0.0+) the browser requires much more memory in the applet pool in order to function. */
/* Thus, we have to reduce our extra system memory size by 26 MB to compensate. */
if (kern::GetTargetFirmware() >= ams::TargetFirmware_21_0_0) {
/* NOTE: On 23.0.0+ we are patching memory allocation for each browser applet since there are only 3 of them now. */
/* Given that the root "Reserved" region is 0x43E000 bytes and the "ReservedTbd" subregion is 0x540000 bytes, we can safely reclaim 9MB.*/
if (kern::GetTargetFirmware() >= ams::TargetFirmware_23_0_0) {
constexpr size_t ExtraSystemMemoryForAtmosphere_23_0_0 = 16_MB;
return base_pool_size - ExtraSystemMemoryForAtmosphere_23_0_0 - KTraceBufferSize;
} else if (kern::GetTargetFirmware() >= ams::TargetFirmware_21_0_0) {
constexpr size_t ExtraSystemMemoryForAtmosphere_21_0_0 = 7_MB;
return base_pool_size - ExtraSystemMemoryForAtmosphere_21_0_0 - KTraceBufferSize;
} else if (kern::GetTargetFirmware() >= ams::TargetFirmware_20_0_0) {
@@ -417,7 +416,10 @@ namespace ams::kern::board::nintendo::nx {
{
/* Set whether we're in debug mode. */
{
ts->is_not_debug_mode = !GetConfigBool(smc::ConfigItem::IsDebugMode);
ts->is_not_debug_mode = !GetConfigBool(smc::ConfigItem::IsDebugMode);
/* TODO: 23.0.0+ split debug mode into 2 fields. Implement this properly for better accuracy. */
ts->is_not_debug_mode2 = ts->is_not_debug_mode;
/* If we're not in debug mode, we don't want to initialize uart logging. */
ts->disable_debug_logging = ts->is_not_debug_mode;
@@ -477,9 +479,9 @@ namespace ams::kern::board::nintendo::nx {
/* Initialize random and resource limit. */
{
u64 seed;
smc::GenerateRandomBytes(std::addressof(seed), sizeof(seed));
KSystemControlBase::InitializePhase1Base(seed);
u8 seed[32];
smc::GenerateRandomBytes(seed, sizeof(seed));
KSystemControlBase::InitializePhase1Base(seed, sizeof(seed));
}
/* Configure the Kernel Carveout region. */
@@ -524,32 +526,8 @@ namespace ams::kern::board::nintendo::nx {
}
/* Randomness. */
void KSystemControl::GenerateRandom(u64 *dst, size_t count) {
MESOSPHERE_INIT_ABORT_UNLESS(count <= 7);
smc::GenerateRandomBytes(dst, count * sizeof(u64));
}
u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
KScopedInterruptDisable intr_disable;
KScopedSpinLock lk(s_random_lock);
if (AMS_LIKELY(!s_uninitialized_random_generator)) {
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); });
} else {
return KSystemControlBase::GenerateUniformRange(min, max, GenerateRandomU64FromSmc);
}
}
u64 KSystemControl::GenerateRandomU64() {
KScopedInterruptDisable intr_disable;
KScopedSpinLock lk(s_random_lock);
if (AMS_LIKELY(!s_uninitialized_random_generator)) {
return s_random_generator.GenerateRandomU64();
} else {
return GenerateRandomU64FromSmc();
}
void KSystemControl::GenerateRandomBytesForUninitialized(void *dst, size_t size) {
smc::GenerateRandomBytes(dst, size);
}
void KSystemControl::SleepSystem() {

View File

@@ -223,6 +223,8 @@ namespace ams::kern::board::nintendo::nx::smc {
KScopedInterruptDisable di;
/* Ensure we successfully show the error. */
/* NOTE: On 23.0.0+ the SMC result is discarded. */
/* The function now ends with an unconditional infinite loop and interrupts are never restored. */
MESOSPHERE_ABORT_UNLESS(ShowErrorImpl(color));
}

View File

@@ -60,25 +60,6 @@ namespace ams::kern::init {
#undef DEFINE_SLAB_TYPE_ENUM_MEMBER
/* Constexpr counts. */
constexpr size_t SlabCountKProcess = 80;
constexpr size_t SlabCountKThread = 800;
constexpr size_t SlabCountKEvent = 900;
constexpr size_t SlabCountKInterruptEvent = 100;
constexpr size_t SlabCountKPort = 384;
constexpr size_t SlabCountKSharedMemory = 80;
constexpr size_t SlabCountKTransferMemory = 200;
constexpr size_t SlabCountKCodeMemory = 10;
constexpr size_t SlabCountKDeviceAddressSpace = 300;
constexpr size_t SlabCountKSession = 1133;
constexpr size_t SlabCountKLightSession = 100;
constexpr size_t SlabCountKObjectName = 7;
constexpr size_t SlabCountKResourceLimit = 5;
constexpr size_t SlabCountKDebug = cpu::NumCores;
constexpr size_t SlabCountKIoPool = 1;
constexpr size_t SlabCountKIoRegion = 6;
constexpr size_t SlabcountKSessionRequestMappings = 40;
constexpr size_t SlabCountExtraKThread = (1024 + 256 + 256) - SlabCountKThread;
namespace test {

View File

@@ -30,30 +30,36 @@ namespace ams::kern {
{ 36, ams::svc::AddressLargeMap36Start, ams::svc::AddressLargeMap36Size, KAddressSpaceInfo::Type_MapLarge, },
{ 36, Invalid, ams::svc::AddressMemoryRegionHeap36Size, KAddressSpaceInfo::Type_Heap, },
{ 36, Invalid, ams::svc::AddressMemoryRegionAlias36Size, KAddressSpaceInfo::Type_Alias, },
{ 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_Map39Bit, },
{ 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_MapHuge, },
{ 39, Invalid, ams::svc::AddressMemoryRegionSmall39Size, KAddressSpaceInfo::Type_MapSmall, },
{ 39, Invalid, ams::svc::AddressMemoryRegionHeap39Size, KAddressSpaceInfo::Type_Heap, },
{ 39, Invalid, ams::svc::AddressMemoryRegionAlias39Size, KAddressSpaceInfo::Type_Alias, },
{ 39, Invalid, ams::svc::AddressMemoryRegionStack39Size, KAddressSpaceInfo::Type_Stack, },
{ 42, ams::svc::AddressMap42Start, ams::svc::AddressMap42Size, KAddressSpaceInfo::Type_MapHuge, },
{ 42, Invalid, ams::svc::AddressMemoryRegionSmall42Size, KAddressSpaceInfo::Type_MapSmall, },
{ 42, Invalid, 0, KAddressSpaceInfo::Type_Heap, },
{ 42, Invalid, ams::svc::AddressMemoryRegionAlias42Size, KAddressSpaceInfo::Type_Alias, },
{ 42, Invalid, ams::svc::AddressMemoryRegionStack42Size, KAddressSpaceInfo::Type_Stack, },
};
constexpr u8 FlagsToAddressSpaceWidthTable[4] = {
32, 36, 32, 39
constexpr u8 FlagsToAddressSpaceWidthTable[5] = {
32, 36, 32, 39, 42
};
constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag flags) {
constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag flags) {
/* Convert the input flags to an array index. */
const size_t idx = (flags & ams::svc::CreateProcessFlag_AddressSpaceMask) >> ams::svc::CreateProcessFlag_AddressSpaceShift;
const size_t idx = (flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) >> ams::svc::CreateProcessParameterFlag_AddressSpaceShift;
MESOSPHERE_ABORT_UNLESS(idx < sizeof(FlagsToAddressSpaceWidthTable));
/* Return the width. */
return FlagsToAddressSpaceWidthTable[idx];
}
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32Bit) == 32);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated) == 36);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) == 32);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit) == 39);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace32Bit) == 32);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36) == 36);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved) == 32);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39) == 39);
static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42) == 42);
KAddressSpaceInfo &GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Type type) {
for (auto &info : AddressSpaceInfos) {
@@ -66,14 +72,14 @@ namespace ams::kern {
}
uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type, size_t code_size) {
uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(ams::svc::CreateProcessParameterFlag flags, KAddressSpaceInfo::Type type, size_t code_size) {
MESOSPHERE_UNUSED(code_size);
return GetAddressSpaceInfo(GetAddressSpaceWidth(flags), type).GetAddress();
}
size_t KAddressSpaceInfo::GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type) {
size_t KAddressSpaceInfo::GetAddressSpaceSize(ams::svc::CreateProcessParameterFlag flags, KAddressSpaceInfo::Type type) {
/* Extract the address space from the create process flags. */
const auto as_flags = (flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
const auto as_flags = (flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask);
/* Get the address space width. */
const auto as_width = GetAddressSpaceWidth(flags);
@@ -82,7 +88,7 @@ namespace ams::kern {
size_t as_size = GetAddressSpaceInfo(as_width, type).GetSize();
/* If we're getting size for 32-bit without alias, adjust the sizes accordingly. */
if (as_flags == ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) {
if (as_flags == ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved) {
switch (type) {
/* The heap space receives space that would otherwise go to the alias space. */
case KAddressSpaceInfo::Type_Heap:

View File

@@ -100,8 +100,8 @@ namespace ams::kern {
KProcessPageTable &target_pt = process->GetPageTable();
/* Verify that the regions are in range. */
R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(debugger_pt.Contains(buffer, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(debugger_pt.IsSafeUserPointer(buffer, size), svc::ResultInvalidCurrentMemory());
/* Iterate over the target process's memory blocks. */
KProcessAddress cur_address = address;
@@ -166,8 +166,8 @@ namespace ams::kern {
KProcessPageTable &target_pt = process->GetPageTable();
/* Verify that the regions are in range. */
R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(debugger_pt.Contains(buffer, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(debugger_pt.IsSafeUserPointer(buffer, size), svc::ResultInvalidCurrentMemory());
/* Iterate over the target process's memory blocks. */
KProcessAddress cur_address = address;
@@ -417,7 +417,7 @@ namespace ams::kern {
/* Terminate the process. */
/* NOTE: This result is seemingly-intentionally not checked by Nintendo. */
static_cast<void>(target->Terminate());
static_cast<void>(target->Terminate(-1ll));
R_SUCCEED();
}
@@ -756,11 +756,13 @@ namespace ams::kern {
case ams::svc::DebugException_UndefinedSystemCall:
{
MESOSPHERE_ASSERT(num_params >= 3);
info->info.exception.exception_address = params[1];
info->info.exception.exception_data_count = 1;
info->info.exception.exception_data[0] = params[2];
/* 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_data_count = 1;
info->info.exception.exception_data[0] = params[2];
}
}
break;
case ams::svc::DebugException_DebuggerAttached:
@@ -773,9 +775,12 @@ namespace ams::kern {
case ams::svc::DebugException_UserBreak:
{
MESOSPHERE_ASSERT(num_params >= 2);
info->info.exception.exception_address = params[1];
/* 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_data_count = 0;
for (size_t i = 2; i < num_params; ++i) {
info->info.exception.exception_data[info->info.exception.exception_data_count++] = params[i];
@@ -805,8 +810,11 @@ namespace ams::kern {
default:
{
MESOSPHERE_ASSERT(num_params >= 2);
info->info.exception.exception_address = params[1];
/* Keep the compiler happy, even though the assert has us covered. */
if (num_params >= 2) {
info->info.exception.exception_address = params[1];
}
}
break;
}
@@ -876,7 +884,7 @@ namespace ams::kern {
{
out->info.create_process.program_id = process->GetProgramId();
out->info.create_process.process_id = process->GetId();
out->info.create_process.flags = process->GetCreateProcessFlags();
out->info.create_process.flags = process->GetCreateProcessParameterFlags();
out->info.create_process.user_exception_context_address = GetInteger(process->GetProcessLocalRegionAddress());
std::memcpy(out->info.create_process.name, process->GetName(), sizeof(out->info.create_process.name));

View File

@@ -214,28 +214,28 @@ namespace ams::kern {
/* Apply other flags. */
if (this->Is64Bit()) {
out->flags |= ams::svc::CreateProcessFlag_Is64Bit;
out->flags |= ams::svc::CreateProcessParameterFlag_64Bit;
}
if (this->Is64BitAddressSpace()) {
out->flags |= (GetTargetFirmware() >= TargetFirmware_2_0_0) ? ams::svc::CreateProcessFlag_AddressSpace64Bit : ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated;
out->flags |= (GetTargetFirmware() >= TargetFirmware_2_0_0) ? ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39 : ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36;
} else {
out->flags |= ams::svc::CreateProcessFlag_AddressSpace32Bit;
out->flags |= ams::svc::CreateProcessParameterFlag_AddressSpace32Bit;
}
if (enable_aslr) {
out->flags |= ams::svc::CreateProcessFlag_EnableAslr;
out->flags |= ams::svc::CreateProcessParameterFlag_EnableAslr;
}
/* All initial processes should disable device address space merge. */
out->flags |= ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge;
out->flags |= ams::svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge;
/* Set and check code address. */
/* NOTE: Even though Nintendo passes a size to GetAddressSpaceStart at other call sites, they pass */
/* a number of pages here. Even though this is presumably only used for debug assertions, this is */
/* almost certainly a bug. */
using ASType = KAddressSpaceInfo::Type;
const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall;
const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(out->flags), as_type, out->code_num_pages);
const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(out->flags), as_type);
const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_MapHuge : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall;
const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessParameterFlag>(out->flags), as_type, out->code_num_pages);
const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(out->flags), as_type);
const uintptr_t map_end = map_start + map_size;
out->code_address = map_start + start_address;
MESOSPHERE_ABORT_UNLESS((out->code_address / PageSize) + out->code_num_pages <= (map_end / PageSize));

View File

@@ -88,14 +88,14 @@ namespace ams::kern {
}
}
void KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) {
void KPageTableBase::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
/* Initialize our members. */
m_address_space_width = (is_64_bit) ? BITSIZEOF(u64) : BITSIZEOF(u32);
m_address_space_start = KProcessAddress(GetInteger(start));
m_address_space_end = KProcessAddress(GetInteger(end));
m_is_kernel = true;
m_enable_aslr = true;
m_enable_device_address_space_merge = false;
m_allowed_exec_device_mapping = false;
for (auto i = 0; i < RegionType_Count; ++i) {
m_region_starts[i] = 0;
@@ -133,7 +133,7 @@ namespace ams::kern {
MESOSPHERE_R_ABORT_UNLESS(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
}
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
/* Validate the region. */
MESOSPHERE_ABORT_UNLESS(start <= code_address);
MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size);
@@ -151,9 +151,9 @@ namespace ams::kern {
m_alias_region_extra_size = 0;
/* Set our width and heap/alias sizes. */
m_address_space_width = GetAddressSpaceWidth(flags);
size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias);
size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap);
size_t address_space_width = GetAddressSpaceWidth(flags);
size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias);
size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap);
/* Set code regions and determine remaining sizes. */
KProcessAddress process_code_start;
@@ -162,12 +162,12 @@ namespace ams::kern {
size_t kernel_map_region_size;
KProcessAddress before_process_code_start, after_process_code_start;
size_t before_process_code_size, after_process_code_size;
if (m_address_space_width == 39) {
if (address_space_width == 39 || address_space_width == 42) {
stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Stack);
kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_MapSmall);
m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit);
m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit);
m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapHuge);
m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapHuge);
m_alias_code_region_start = m_code_region_start;
m_alias_code_region_end = m_code_region_end;
@@ -179,10 +179,10 @@ namespace ams::kern {
after_process_code_start = process_code_end;
after_process_code_size = m_code_region_end - process_code_end;
/* If we have a 39-bit address space and should, enable extra size to the alias region. */
if (flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) {
/* If we have a 39-bit address space and should, enable extra size for the address sanitizer. */
if (flags & ams::svc::CreateProcessParameterFlag_EnableAddressSanitizer) {
/* Extra size is 1/8th of the address space. */
m_alias_region_extra_size = (static_cast<size_t>(1) << m_address_space_width) / 8;
m_alias_region_extra_size = (static_cast<size_t>(1) << address_space_width) / 8;
alias_region_size += m_alias_region_extra_size;
}
@@ -208,9 +208,12 @@ namespace ams::kern {
after_process_code_size = GetSpaceSize(KAddressSpaceInfo::Type_MapLarge);
}
m_region_starts[RegionType_ShadowStack] = Null<KProcessAddress>;
m_region_ends[RegionType_ShadowStack] = Null<KProcessAddress>;
/* Set other basic fields. */
m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
m_enable_aslr = (flags & ams::svc::CreateProcessParameterFlag_EnableAslr) != 0;
m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge) == 0;
m_allowed_exec_device_mapping = false;
m_address_space_start = start;
m_address_space_end = end;
@@ -237,6 +240,9 @@ namespace ams::kern {
region_layouts[num_regions++] = { .size = alias_region_size, .type = RegionType_Alias, .alloc_index = 0, };
region_layouts[num_regions++] = { .size = heap_region_size, .type = RegionType_Heap, .alloc_index = 0, };
if (flags & ams::svc::CreateProcessParameterFlag_EnableShadowStack) {
region_layouts[num_regions++] = { .size = ams::svc::AddressShadowStackRegionSize, .type = RegionType_ShadowStack, .alloc_index = 0, };
}
/* Selection-sort the regions by size largest-to-smallest. */
for (size_t i = 0; i < num_regions - 1; ++i) {
@@ -347,151 +353,36 @@ namespace ams::kern {
const KProcessAddress process_code_last = process_code_end - 1;
auto IsInAddressSpace = [&](KProcessAddress addr) ALWAYS_INLINE_LAMBDA { return m_address_space_start <= addr && addr <= m_address_space_end; };
/* Ensure that the KernelMap region is valid. */
for (size_t k = 0; k < num_regions; ++k) {
if (const auto &kmap_region = region_layouts[k]; kmap_region.type == RegionType_KernelMap) {
/* If there's no kmap region, we have nothing to check. */
if (kmap_region.size == 0) {
break;
}
/* Check that the kmap region is within our address space. */
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_KernelMap]));
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_KernelMap]));
/* Check for overlap with process code. */
const KProcessAddress kmap_start = m_region_starts[RegionType_KernelMap];
const KProcessAddress kmap_last = m_region_ends[RegionType_KernelMap] - 1;
MESOSPHERE_ABORT_UNLESS(kernel_map_region_size == 0 || kmap_last < process_code_start || process_code_last < kmap_start);
/* Check for overlap with stack. */
for (size_t s = 0; s < num_regions; ++s) {
if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) {
if (stack_region.size != 0) {
const KProcessAddress stack_start = m_region_starts[RegionType_Stack];
const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1;
MESOSPHERE_ABORT_UNLESS((kernel_map_region_size == 0 && stack_region_size == 0) || kmap_last < stack_start || stack_last < kmap_start);
}
break;
}
}
/* Check for overlap with alias. */
for (size_t a = 0; a < num_regions; ++a) {
if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) {
if (alias_region.size != 0) {
const KProcessAddress alias_start = m_region_starts[RegionType_Alias];
const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1;
MESOSPHERE_ABORT_UNLESS(kmap_last < alias_start || alias_last < kmap_start);
}
break;
}
}
/* Check for overlap with heap. */
for (size_t h = 0; h < num_regions; ++h) {
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
if (heap_region.size != 0) {
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
MESOSPHERE_ABORT_UNLESS(kmap_last < heap_start || heap_last < kmap_start);
}
break;
}
}
}
/* Map each region type to its layout entry. */
const RegionLayoutInfo *region_layouts_by_type[RegionType_Count] = {};
for (size_t i = 0; i < num_regions; ++i) {
region_layouts_by_type[region_layouts[i].type] = std::addressof(region_layouts[i]);
}
/* Check that the Stack region is valid. */
for (size_t s = 0; s < num_regions; ++s) {
if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) {
/* If there's no stack region, we have nothing to check. */
if (stack_region.size == 0) {
break;
}
/* Check that the stack region is within our address space. */
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Stack]));
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Stack]));
/* Check for overlap with process code. */
const KProcessAddress stack_start = m_region_starts[RegionType_Stack];
const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1;
MESOSPHERE_ABORT_UNLESS(stack_region_size == 0 || stack_last < process_code_start || process_code_last < stack_start);
/* Check for overlap with alias. */
for (size_t a = 0; a < num_regions; ++a) {
if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) {
if (alias_region.size != 0) {
const KProcessAddress alias_start = m_region_starts[RegionType_Alias];
const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1;
MESOSPHERE_ABORT_UNLESS(stack_last < alias_start || alias_last < stack_start);
}
break;
}
}
/* Check for overlap with heap. */
for (size_t h = 0; h < num_regions; ++h) {
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
if (heap_region.size != 0) {
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
MESOSPHERE_ABORT_UNLESS(stack_last < heap_start || heap_last < stack_start);
}
break;
}
}
/* Validate each region. */
for (size_t i = 0; i < RegionType_Count; ++i) {
/* If the region isn't present, there's nothing to check. */
const RegionLayoutInfo * const region = region_layouts_by_type[i];
if (region == nullptr || region->size == 0) {
continue;
}
}
/* Check that the Alias region is valid. */
for (size_t a = 0; a < num_regions; ++a) {
if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) {
/* If there's no alias region, we have nothing to check. */
if (alias_region.size == 0) {
break;
/* Check that the region is within our address space. */
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[i]));
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[i]));
/* Check for overlap with process code. */
MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < process_code_start || process_code_last < m_region_starts[i]);
/* Check for overlap with every later region. */
for (size_t j = i; j < RegionType_ShadowStack; ++j) {
/* If the other region isn't present, there's nothing to check. */
const RegionLayoutInfo * const other = region_layouts_by_type[j + 1];
if (other == nullptr || other->size == 0) {
continue;
}
/* Check that the alias region is within our address space. */
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Alias]));
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Alias]));
/* Check for overlap with process code. */
const KProcessAddress alias_start = m_region_starts[RegionType_Alias];
const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1;
MESOSPHERE_ABORT_UNLESS(alias_last < process_code_start || process_code_last < alias_start);
/* Check for overlap with heap. */
for (size_t h = 0; h < num_regions; ++h) {
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
if (heap_region.size != 0) {
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
MESOSPHERE_ABORT_UNLESS(alias_last < heap_start || heap_last < alias_start);
}
break;
}
}
}
}
/* Check that the Heap region is valid. */
for (size_t h = 0; h < num_regions; ++h) {
if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) {
/* If there's no heap region, we have nothing to check. */
if (heap_region.size == 0) {
break;
}
/* Check that the heap region is within our address space. */
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Heap]));
MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Heap]));
/* Check for overlap with process code. */
const KProcessAddress heap_start = m_region_starts[RegionType_Heap];
const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1;
MESOSPHERE_ABORT_UNLESS(heap_last < process_code_start || process_code_last < heap_start);
MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < m_region_starts[j + 1] || m_region_ends[j + 1] - 1 < m_region_starts[i]);
}
}
}
@@ -561,6 +452,8 @@ namespace ams::kern {
case ams::svc::MemoryState_Static:
case ams::svc::MemoryState_ThreadLocal:
return m_region_starts[RegionType_KernelMap];
case ams::svc::MemoryState_ShadowStack:
return m_region_starts[RegionType_ShadowStack];
case ams::svc::MemoryState_Io:
case ams::svc::MemoryState_Shared:
case ams::svc::MemoryState_AliasCode:
@@ -596,6 +489,8 @@ namespace ams::kern {
case ams::svc::MemoryState_Static:
case ams::svc::MemoryState_ThreadLocal:
return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap];
case ams::svc::MemoryState_ShadowStack:
return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack];
case ams::svc::MemoryState_Io:
case ams::svc::MemoryState_Shared:
case ams::svc::MemoryState_AliasCode:
@@ -622,12 +517,20 @@ namespace ams::kern {
const KProcessAddress region_start = this->GetRegionAddress(state);
const size_t region_size = this->GetRegionSize(state);
if (region_size == 0) {
return false;
}
const bool is_in_region = region_start <= addr && addr < end && last <= region_start + region_size - 1;
const bool is_in_heap = !(end <= m_region_starts[RegionType_Heap] || m_region_ends[RegionType_Heap] <= addr || m_region_starts[RegionType_Heap] == m_region_ends[RegionType_Heap]);
const bool is_in_alias = !(end <= m_region_starts[RegionType_Alias] || m_region_ends[RegionType_Alias] <= addr || m_region_starts[RegionType_Alias] == m_region_ends[RegionType_Alias]);
switch (state) {
case ams::svc::MemoryState_Free:
case ams::svc::MemoryState_Normal:
case ams::svc::MemoryState_Ipc:
case ams::svc::MemoryState_NonSecureIpc:
case ams::svc::MemoryState_NonDeviceIpc:
case ams::svc::MemoryState_Kernel:
case ams::svc::MemoryState_ShadowStack:
return is_in_region;
case ams::svc::MemoryState_Io:
case ams::svc::MemoryState_Static:
@@ -645,17 +548,32 @@ namespace ams::kern {
case ams::svc::MemoryState_CodeOut:
case ams::svc::MemoryState_Coverage:
case ams::svc::MemoryState_Insecure:
return is_in_region && !is_in_heap && !is_in_alias;
case ams::svc::MemoryState_Normal:
MESOSPHERE_ASSERT(is_in_heap);
return is_in_region && !is_in_alias;
case ams::svc::MemoryState_Ipc:
case ams::svc::MemoryState_NonSecureIpc:
case ams::svc::MemoryState_NonDeviceIpc:
MESOSPHERE_ASSERT(is_in_alias);
return is_in_region && !is_in_heap;
default:
return false;
{
if (!is_in_region) {
return false;
}
const auto heap_start = m_region_starts[RegionType_Heap];
const auto heap_end = m_region_ends[RegionType_Heap];
if (heap_start != heap_end && addr < heap_end && heap_start < end) {
return false;
}
const auto alias_start = m_region_starts[RegionType_Alias];
const auto alias_end = m_region_ends[RegionType_Alias];
if (alias_start != alias_end && addr < alias_end && alias_start < end) {
return false;
}
const auto shadow_start = m_region_starts[RegionType_ShadowStack];
const auto shadow_end = m_region_ends[RegionType_ShadowStack];
if (shadow_start != shadow_end && addr < shadow_end && shadow_start < end) {
return false;
}
return true;
}
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
}
}
@@ -1997,15 +1915,15 @@ namespace ams::kern {
.m_address = GetInteger(m_address_space_end),
.m_size = 0 - GetInteger(m_address_space_end),
.m_state = static_cast<KMemoryState>(ams::svc::MemoryState_Inaccessible),
.m_device_disable_merge_left_count = 0,
.m_device_disable_merge_right_count = 0,
.m_ipc_lock_count = 0,
.m_device_use_count = 0,
.m_ipc_disable_merge_count = 0,
.m_permission = KMemoryPermission_None,
.m_attribute = KMemoryAttribute_None,
.m_original_permission = KMemoryPermission_None,
.m_ipc_lock_count = 0,
.m_device_use_count = 0,
.m_disable_merge_attribute = KMemoryBlockDisableMergeAttribute_None,
.m_ipc_disable_merge_count = 0,
.m_device_disable_merge_left_count = 0,
.m_device_disable_merge_right_count = 0,
};
out_page_info->flags = 0;
@@ -3287,7 +3205,7 @@ namespace ams::kern {
Result KPageTableBase::CopyMemoryFromLinearToUser(KProcessAddress dst_addr, size_t size, KProcessAddress src_addr, u32 src_state_mask, u32 src_state, KMemoryPermission src_test_perm, u32 src_attr_mask, u32 src_attr) {
/* Lightly validate the range before doing anything else. */
R_UNLESS(this->Contains(src_addr, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(this->IsSafeUserPointer(src_addr, size), svc::ResultInvalidCurrentMemory());
/* Copy the memory. */
{
@@ -3436,7 +3354,7 @@ namespace ams::kern {
Result KPageTableBase::CopyMemoryFromUserToLinear(KProcessAddress dst_addr, size_t size, u32 dst_state_mask, u32 dst_state, KMemoryPermission dst_test_perm, u32 dst_attr_mask, u32 dst_attr, KProcessAddress src_addr) {
/* Lightly validate the range before doing anything else. */
R_UNLESS(this->Contains(dst_addr, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(this->IsSafeUserPointer(dst_addr, size), svc::ResultInvalidCurrentMemory());
/* Copy the memory. */
{

View File

@@ -210,7 +210,7 @@ namespace ams::kern {
m_program_id = params.program_id;
m_code_address = params.code_address;
m_code_size = params.code_num_pages * PageSize;
m_is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
m_is_application = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication);
m_is_jit_debug = false;
#if defined(MESOSPHERE_ENABLE_PROCESS_CREATION_TIME)
@@ -226,7 +226,7 @@ namespace ams::kern {
}
/* Set max memory. */
m_max_process_memory = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(m_flags), KAddressSpaceInfo::Type_Heap);
m_max_process_memory = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(m_flags), KAddressSpaceInfo::Type_Heap);
/* Generate random entropy. */
KSystemControl::GenerateRandom(m_entropy, util::size(m_entropy));
@@ -264,6 +264,11 @@ namespace ams::kern {
m_is_default_application_system_resource = false;
m_is_immortal = immortal;
/* Reseed the random generator on application launch. */
if (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) {
KSystemControl::ReseedRandomGenerator();
}
/* Setup our system resource. */
if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) {
/* Create a secure system resource. */
@@ -279,7 +284,7 @@ namespace ams::kern {
m_system_resource = secure_resource;
} else {
/* Use the system-wide system resource. */
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
const bool is_app = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication);
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
m_is_default_application_system_resource = is_app;
@@ -293,8 +298,8 @@ namespace ams::kern {
/* Setup page table. */
{
const bool from_back = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) == 0;
R_TRY(m_page_table.Initialize(static_cast<ams::svc::CreateProcessFlag>(params.flags), from_back, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit, this->GetSlabIndex()));
const bool from_back = (params.flags & ams::svc::CreateProcessParameterFlag_EnableAslr) == 0;
R_TRY(m_page_table.Initialize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), from_back, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit, this->GetSlabIndex()));
}
ON_RESULT_FAILURE_2 { m_page_table.Finalize(); };
@@ -332,6 +337,11 @@ namespace ams::kern {
m_is_default_application_system_resource = false;
m_is_immortal = false;
/* Reseed the random generator on application launch. */
if (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) {
KSystemControl::ReseedRandomGenerator();
}
/* Get the memory sizes. */
const size_t code_num_pages = params.code_num_pages;
const size_t system_resource_num_pages = params.system_resource_num_pages;
@@ -358,7 +368,7 @@ namespace ams::kern {
} else {
/* Use the system-wide system resource. */
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
const bool is_app = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication);
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
m_is_default_application_system_resource = is_app;
@@ -372,8 +382,8 @@ namespace ams::kern {
/* Setup page table. */
{
const bool from_back = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) == 0;
R_TRY(m_page_table.Initialize(static_cast<ams::svc::CreateProcessFlag>(params.flags), from_back, pool, params.code_address, code_size, m_system_resource, res_limit, this->GetSlabIndex()));
const bool from_back = (params.flags & ams::svc::CreateProcessParameterFlag_EnableAslr) == 0;
R_TRY(m_page_table.Initialize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), from_back, pool, params.code_address, code_size, m_system_resource, res_limit, this->GetSlabIndex()));
}
ON_RESULT_FAILURE_2 { m_page_table.Finalize(); };
@@ -392,7 +402,7 @@ namespace ams::kern {
MESOSPHERE_ABORT_UNLESS(m_process_id <= ProcessIdMax);
/* If we should optimize memory allocations, do so. */
if (m_system_resource->IsSecureResource() && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
if (m_system_resource->IsSecureResource() && (params.flags & ams::svc::CreateProcessParameterFlag_OptimizeMemoryAllocation) != 0) {
R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(m_process_id, pool));
}
@@ -455,7 +465,7 @@ namespace ams::kern {
}
}
void KProcess::Exit() {
void KProcess::Exit(s64 exit_tag) {
MESOSPHERE_ASSERT_THIS();
/* Determine whether we need to start terminating. */
@@ -470,6 +480,7 @@ namespace ams::kern {
MESOSPHERE_ASSERT(m_state != State_Terminated);
if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_DebugBreak) {
this->ChangeState(State_Terminating);
this->SetExitTag(exit_tag);
needs_terminate = true;
}
}
@@ -490,7 +501,7 @@ namespace ams::kern {
MESOSPHERE_PANIC("Thread survived call to exit");
}
Result KProcess::Terminate() {
Result KProcess::Terminate(s64 exit_tag) {
MESOSPHERE_ASSERT_THIS();
/* Determine whether we need to start terminating */
@@ -506,6 +517,7 @@ namespace ams::kern {
if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_Crashed || m_state == State_DebugBreak) {
this->ChangeState(State_Terminating);
this->SetExitTag(exit_tag);
needs_terminate = true;
}
}
@@ -773,7 +785,7 @@ namespace ams::kern {
MESOSPHERE_ASSERT(m_num_running_threads.Load() > 0);
if (const auto prev = m_num_running_threads--; prev == 1) {
static_cast<void>(this->Terminate());
static_cast<void>(this->Terminate(-1ll));
}
}
@@ -970,6 +982,9 @@ namespace ams::kern {
/* Initialize the thread. */
R_TRY(KThread::InitializeUserThread(main_thread, reinterpret_cast<KThreadFunction>(GetVoidPointer(this->GetEntryPoint())), 0, stack_top, priority, m_ideal_core_id, this));
/* TODO: what is this? */
main_thread->SetDebugUnknown5(true);
/* Register the thread, and commit our reservation. */
KThread::Register(main_thread);
thread_reservation.Commit();
@@ -1189,7 +1204,7 @@ namespace ams::kern {
MESOSPHERE_ASSERT(this == GetCurrentProcessPointer());
/* If we aren't allowed to enter jit debug, don't. */
if ((m_flags & ams::svc::CreateProcessFlag_EnableDebug) == 0) {
if ((m_flags & ams::svc::CreateProcessParameterFlag_EnableJitDebug) == 0) {
return false;
}

View File

@@ -28,6 +28,8 @@ namespace ams::kern {
} else {
/* Allocate dynamic mappings as necessary. */
if (m_dynamic_mappings == nullptr) {
/* 23.0.0+ now checks for IsDynamicResourceLimitsEnabled before allocating from slab heap. */
R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), svc::ResultOutOfMemory());
m_dynamic_mappings = DynamicMappings::Allocate();
R_UNLESS(m_dynamic_mappings != nullptr, svc::ResultOutOfMemory());
}
@@ -44,16 +46,19 @@ namespace ams::kern {
Result KSessionRequest::SessionMappings::PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
MESOSPHERE_ASSERT(m_num_recv == 0);
MESOSPHERE_ASSERT(m_num_exch == 0);
R_RETURN(this->PushMap(client, server, size, state, m_num_send++));
ON_RESULT_SUCCESS { ++m_num_send; };
R_RETURN(this->PushMap(client, server, size, state, m_num_send));
}
Result KSessionRequest::SessionMappings::PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
MESOSPHERE_ASSERT(m_num_exch == 0);
R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv++));
ON_RESULT_SUCCESS { ++m_num_recv; };
R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv));
}
Result KSessionRequest::SessionMappings::PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++));
ON_RESULT_SUCCESS { ++m_num_exch; };
R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch));
}
void KSessionRequest::SessionMappings::Finalize() {

View File

@@ -14,6 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
#include <vapours/crypto/crypto_aes_encryptor.hpp>
#include <vapours/crypto/impl/crypto_ctr_drbg.hpp>
#if defined(ATMOSPHERE_ARCH_ARM64)
#include <mesosphere/arch/arm64/kern_secure_monitor_base.hpp>
#endif
@@ -27,6 +29,41 @@ namespace ams::kern {
}
namespace {
/* The kernel is otherwise FP/SIMD-free, but AES instructions require the NEON registers. */
class KScopedFpuEnable {
private:
u64 m_saved_cpacr_el1;
public:
ALWAYS_INLINE KScopedFpuEnable() : m_saved_cpacr_el1(cpu::GetCpacrEl1()) {
cpu::SetCpacrEl1(m_saved_cpacr_el1 | 0x100000);
cpu::InstructionMemoryBarrier();
}
ALWAYS_INLINE ~KScopedFpuEnable() {
cpu::SetCpacrEl1(m_saved_cpacr_el1);
cpu::InstructionMemoryBarrier();
}
};
using RandomGenerator = ::ams::crypto::impl::CtrDrbg<::ams::crypto::AesEncryptor128, 16, false>;
constexpr size_t RandomGeneratorOutputSize = 8 * RandomGenerator::OutSize;
constexpr u32 RandomGeneratorOutputCount = RandomGeneratorOutputSize / sizeof(u32);
constinit util::TypedStorage<RandomGenerator> s_random_generator = {};
constinit bool s_uninitialized_random_generator = true;
constinit u8 s_random_output[RandomGeneratorOutputSize] = {};
constinit u32 s_random_remaining = 0;
constinit KSpinLock s_random_lock;
void GenerateRandomSeed(void *dst, size_t size) {
KSystemControl::GenerateRandomBytesForUninitialized(dst, size);
}
}
/* Initialization. */
size_t KSystemControlBase::Init::GetRealMemorySize() {
return ams::kern::MainMemorySize;
@@ -102,25 +139,13 @@ namespace ams::kern {
/* Randomness for Initialization. */
void KSystemControlBase::Init::GenerateRandom(u64 *dst, size_t count) {
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
const u64 seed = KHardwareTimer::GetTick();
s_random_generator.Initialize(reinterpret_cast<const u32*>(std::addressof(seed)), sizeof(seed) / sizeof(u32));
s_uninitialized_random_generator = false;
}
for (size_t i = 0; i < count; ++i) {
dst[i] = s_random_generator.GenerateRandomU64();
dst[i] = KSystemControlBase::GenerateRandomU64();
}
}
u64 KSystemControlBase::Init::GenerateRandomRange(u64 min, u64 max) {
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
const u64 seed = KHardwareTimer::GetTick();
s_random_generator.Initialize(reinterpret_cast<const u32*>(std::addressof(seed)), sizeof(seed) / sizeof(u32));
s_uninitialized_random_generator = false;
}
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); });
return KSystemControlBase::GenerateRandomRange(min, max);
}
/* System Initialization. */
@@ -135,15 +160,17 @@ namespace ams::kern {
}
/* Initialize random and resource limit. */
KSystemControlBase::InitializePhase1Base(KHardwareTimer::GetTick());
u64 seed[4];
for (size_t i = 0; i < util::size(seed); ++i) {
seed[i] = KHardwareTimer::GetTick();
}
KSystemControlBase::InitializePhase1Base(seed, sizeof(seed));
}
void KSystemControlBase::InitializePhase1Base(u64 seed) {
/* Initialize the rng, if we somehow haven't already. */
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
s_random_generator.Initialize(reinterpret_cast<const u32*>(std::addressof(seed)), sizeof(seed) / sizeof(u32));
s_uninitialized_random_generator = false;
}
void KSystemControlBase::InitializePhase1Base(const void *seed, size_t size) {
/* Initialize the random generator. */
KSystemControlBase::InitializeRandomGenerator(seed, size);
s_uninitialized_random_generator = false;
/* Initialize debug logging. */
KDebugLog::Initialize();
@@ -170,6 +197,13 @@ namespace ams::kern {
KAddressSpaceInfo::SetAddressSpaceSize(39, KAddressSpaceInfo::Type_Alias, alias_size);
}
/* Update 42-bit address space infos. */
{
/* Heap should be equal to the total memory size, maximum 128 GB. */
/* Alias/Stack/MapSmall are left at their static defaults. */
KAddressSpaceInfo::SetAddressSpaceSize(42, KAddressSpaceInfo::Type_Heap, std::min(util::AlignUp(total_memory_size, 1_GB), 128_GB));
}
const auto &slab_counts = init::GetSlabResourceCounts();
MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_PhysicalMemoryMax, total_memory_size));
MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_ThreadCountMax, slab_counts.num_KThread));
@@ -206,13 +240,77 @@ namespace ams::kern {
R_THROW(svc::ResultNotImplemented());
}
/* Randomness helpers. Assume the caller holds the random lock. */
void KSystemControlBase::InitializeRandomGenerator(const void *seed, size_t size) {
MESOSPHERE_ASSERT(size == RandomGenerator::SeedSize);
KScopedFpuEnable fp_enabled;
/* Construct the generator, and derive the initial state from the seed. */
util::ConstructAt(s_random_generator);
util::GetReference(s_random_generator).Initialize(seed, size, nullptr, 0, nullptr, 0);
s_random_remaining = 0;
}
void KSystemControlBase::ReseedRandomGeneratorInternal() {
KScopedFpuEnable fp_enabled;
/* Pull fresh entropy, then derive a new state from it. */
u8 seed[RandomGenerator::SeedSize];
GenerateRandomSeed(seed, sizeof(seed));
util::GetReference(s_random_generator).Reseed(seed, sizeof(seed), nullptr, 0);
s_random_remaining = 0;
}
u32 KSystemControlBase::GenerateRandomU32() {
if (s_random_remaining == 0) {
KScopedFpuEnable fp_enabled;
auto &drbg = util::GetReference(s_random_generator);
/* Derive the next state, or reseed if we've exhausted this generation's entropy. */
if (AMS_UNLIKELY(!drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0))) {
u8 seed[RandomGenerator::SeedSize];
GenerateRandomSeed(seed, sizeof(seed));
drbg.Reseed(seed, sizeof(seed), nullptr, 0);
MESOSPHERE_ABORT_UNLESS(drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0));
}
s_random_remaining = RandomGeneratorOutputCount;
}
/* Consume a word from the output buffer, zeroizing it in place for backtracking resistance. */
const size_t index = RandomGeneratorOutputCount - s_random_remaining;
u32 value;
std::memcpy(std::addressof(value), s_random_output + sizeof(value) * index, sizeof(value));
std::memset(s_random_output + sizeof(value) * index, 0, sizeof(value));
--s_random_remaining;
return value;
}
u64 KSystemControlBase::GenerateRandomU64Internal() {
/* Fall back to the board's raw source while the generator is uninitialized. */
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
u64 value;
KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value));
return value;
}
const u64 high = KSystemControlBase::GenerateRandomU32();
const u64 low = KSystemControlBase::GenerateRandomU32();
return (high << 32) | low;
}
/* Randomness. */
void KSystemControlBase::GenerateRandom(u64 *dst, size_t count) {
KScopedInterruptDisable intr_disable;
KScopedSpinLock lk(s_random_lock);
for (size_t i = 0; i < count; ++i) {
dst[i] = s_random_generator.GenerateRandomU64();
dst[i] = KSystemControlBase::GenerateRandomU64Internal();
}
}
@@ -220,14 +318,46 @@ namespace ams::kern {
KScopedInterruptDisable intr_disable;
KScopedSpinLock lk(s_random_lock);
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); });
/* While uninitialized, fall back to a raw single-draw modulo. */
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
u64 value;
KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value));
const u64 difference = max - min;
if (difference == std::numeric_limits<u64>::max()) {
return value;
}
return min + (value % (difference + 1));
}
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return KSystemControlBase::GenerateRandomU64Internal(); });
}
u64 KSystemControlBase::GenerateRandomU64() {
KScopedInterruptDisable intr_disable;
KScopedSpinLock lk(s_random_lock);
return s_random_generator.GenerateRandomU64();
return KSystemControlBase::GenerateRandomU64Internal();
}
void KSystemControlBase::ReseedRandomGenerator() {
/* This must be unreachable while the generator is uninitialized. */
MESOSPHERE_ABORT_UNLESS(!s_uninitialized_random_generator);
KScopedInterruptDisable intr_disable;
KScopedSpinLock lk(s_random_lock);
KSystemControlBase::ReseedRandomGeneratorInternal();
}
void KSystemControlBase::GenerateRandomBytesForUninitialized(void *dst, size_t size) {
/* The default board has no secure monitor; fall back to the hardware timer. */
u8 *dst_8 = static_cast<u8 *>(dst);
for (size_t offset = 0; offset < size; offset += sizeof(u64)) {
const u64 tick = KHardwareTimer::GetTick();
std::memcpy(dst_8 + offset, std::addressof(tick), std::min(sizeof(tick), size - offset));
}
}
void KSystemControlBase::SleepSystem() {

View File

@@ -214,6 +214,10 @@ namespace ams::kern {
m_tls_address = 0;
m_tls_heap_address = 0;
/* Set shadow stack address and page. */
m_shadow_stack_address = Null<KProcessAddress>;
m_shadow_stack_page = nullptr;
/* Set parent and condvar tree. */
m_parent = nullptr;
m_condvar_tree = nullptr;
@@ -281,6 +285,29 @@ namespace ams::kern {
R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address)));
m_tls_heap_address = owner->GetThreadLocalRegionPointer(m_tls_address);
std::memset(m_tls_heap_address, 0, ams::svc::ThreadLocalRegionSize);
/* If the owning process has a shadow stack, allocate and map a page for this thread. */
if (owner->GetCreateProcessParameterFlags() & ams::svc::CreateProcessParameterFlag_EnableShadowStack) {
/* Allocate the backing page. */
KPageBuffer *page = KPageBuffer::AllocateChecked<PageSize>();
if (page == nullptr) {
owner->DeleteThreadLocalRegion(m_tls_address);
m_tls_address = Null<KProcessAddress>;
R_THROW(svc::ResultOutOfMemory());
}
/* If we fail to map the page, free it and undo the TLS region we just created. */
ON_RESULT_FAILURE {
KPageBuffer::Free(page);
owner->DeleteThreadLocalRegion(m_tls_address);
m_tls_address = Null<KProcessAddress>;
};
/* Map the page into the process's shadow stack region. */
R_TRY(owner->GetPageTable().MapPages(std::addressof(m_shadow_stack_address), 1, PageSize, page->GetPhysicalAddress(), KMemoryState_ShadowStack, KMemoryPermission_UserReadWrite));
m_shadow_stack_page = page;
}
}
/* Set parent, if relevant. */
@@ -390,6 +417,12 @@ namespace ams::kern {
m_parent->UnregisterThread(this);
}
/* If the thread has a shadow stack, unmap and free its page. */
if (m_shadow_stack_address != Null<KProcessAddress>) {
MESOSPHERE_R_ABORT_UNLESS(m_parent->GetPageTable().UnmapPages(m_shadow_stack_address, 1, KMemoryState_ShadowStack));
KPageBuffer::Free(m_shadow_stack_page);
}
/* If the thread has a local region, delete it. */
if (m_tls_address != Null<KProcessAddress>) {
m_parent->DeleteThreadLocalRegion(m_tls_address);

View File

@@ -21,8 +21,10 @@ namespace ams::kern::svc {
namespace {
constexpr bool IsKernelAddress(uintptr_t address) {
return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
constexpr bool IsValidAddress(uintptr_t address) {
if (KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd) return false;
if (GetCurrentProcess().GetPageTable().IsInShadowStackRegion(address)) return false;
return true;
}
constexpr bool IsValidSignalType(ams::svc::SignalType type) {
@@ -50,7 +52,7 @@ namespace ams::kern::svc {
Result WaitForAddress(uintptr_t address, ams::svc::ArbitrationType arb_type, int64_t value, int64_t timeout_ns) {
/* Validate input. */
R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)), svc::ResultInvalidCurrentMemory());
R_UNLESS(AMS_LIKELY(IsValidAddress(address)), svc::ResultInvalidCurrentMemory());
if (arb_type == ams::svc::ArbitrationType_WaitIfEqual64) {
R_UNLESS(util::IsAligned(address, sizeof(int64_t)), svc::ResultInvalidAddress());
} else {
@@ -79,7 +81,7 @@ namespace ams::kern::svc {
Result SignalToAddress(uintptr_t address, ams::svc::SignalType signal_type, int32_t value, int32_t count) {
/* Validate input. */
R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)), svc::ResultInvalidCurrentMemory());
R_UNLESS(AMS_LIKELY(IsValidAddress(address)), svc::ResultInvalidCurrentMemory());
R_UNLESS(util::IsAligned(address, sizeof(int32_t)), svc::ResultInvalidAddress());
R_UNLESS(IsValidSignalType(signal_type), svc::ResultInvalidEnumValue());

View File

@@ -83,7 +83,7 @@ namespace ams::kern::svc {
R_SUCCEED_IF(size == 0);
/* Validate that the region is within range. */
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(address, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(address, size), svc::ResultInvalidCurrentMemory()); /* did N intend ResultInvalidPointer like everywhere else? */
/* Flush the cache. */
R_TRY(cpu::FlushDataCache(reinterpret_cast<void *>(address), size));

View File

@@ -21,13 +21,15 @@ namespace ams::kern::svc {
namespace {
constexpr bool IsKernelAddress(uintptr_t address) {
return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
constexpr bool IsValidAddress(uintptr_t address) {
if (KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd) return false;
if (GetCurrentProcess().GetPageTable().IsInShadowStackRegion(address)) return false;
return true;
}
Result WaitProcessWideKeyAtomic(uintptr_t address, uintptr_t cv_key, uint32_t tag, int64_t timeout_ns) {
/* Validate input. */
R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)), svc::ResultInvalidCurrentMemory());
R_UNLESS(AMS_LIKELY(IsValidAddress(address)), svc::ResultInvalidPointer());
R_UNLESS(util::IsAligned(address, sizeof(int32_t)), svc::ResultInvalidAddress());
/* Convert timeout from nanoseconds to ticks. */

View File

@@ -97,6 +97,8 @@ namespace ams::kern::svc {
/* Only allow invoking the svc on development hardware or if force debug prod. */
R_UNLESS(KTargetSystem::IsDebugMode() || GetCurrentProcess().CanForceDebugProd(), svc::ResultNotImplemented());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_info.GetUnsafePointer()), sizeof(EventInfoType)), svc::ResultInvalidPointer());
/* Get the debug object. */
KScopedAutoObject debug = GetCurrentProcess().GetHandleTable().GetObject<KDebug>(debug_handle);
R_UNLESS(debug.IsNotNull(), svc::ResultInvalidHandle());
@@ -142,6 +144,7 @@ namespace ams::kern::svc {
/* Copy the threads from userspace. */
uint64_t thread_ids[MaximumDebuggableThreadCount];
if (num_thread_ids > 0) {
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_thread_ids.GetUnsafePointer()), num_thread_ids * sizeof(uint64_t)), svc::ResultInvalidPointer());
R_TRY(user_thread_ids.CopyArrayTo(thread_ids, num_thread_ids));
}
@@ -172,6 +175,8 @@ namespace ams::kern::svc {
/* Only allow invoking the svc on development hardware or if force debug prod. */
R_UNLESS(KTargetSystem::IsDebugMode() || GetCurrentProcess().CanForceDebugProd(), svc::ResultNotImplemented());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_context.GetUnsafePointer()), sizeof(ams::svc::ThreadContext)), svc::ResultInvalidPointer());
/* Validate the context flags. */
R_UNLESS((context_flags | ams::svc::ThreadContextFlag_All) == ams::svc::ThreadContextFlag_All, svc::ResultInvalidEnumValue());
@@ -193,6 +198,8 @@ namespace ams::kern::svc {
/* Only allow invoking the svc on development hardware. */
R_UNLESS(KTargetSystem::IsDebugMode(), svc::ResultNotImplemented());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_context.GetUnsafePointer()), sizeof(ams::svc::ThreadContext)), svc::ResultInvalidPointer());
/* Validate the context flags. */
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
{
@@ -243,6 +250,8 @@ namespace ams::kern::svc {
template<typename T>
Result QueryDebugProcessMemory(KUserPointer<T *> out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle debug_handle, uint64_t address) {
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_memory_info.GetUnsafePointer()), sizeof(T)), svc::ResultInvalidPointer());
/* Get an ams::svc::MemoryInfo for the region. */
ams::svc::MemoryInfo info = {};
R_TRY(QueryDebugProcessMemory(std::addressof(info), out_page_info, debug_handle, address));
@@ -429,6 +438,11 @@ namespace ams::kern::svc {
*out_32 = affinity_mask;
}
break;
case ams::svc::DebugThreadParam_Unknown5:
{
*out_32 = thread->IsDebugUnknown5();
}
break;
default:
R_THROW(ams::svc::ResultInvalidEnumValue());
}

View File

@@ -26,7 +26,7 @@ namespace ams::kern::svc {
R_SUCCEED_IF(len == 0);
/* Ensure that the data being output is in range. */
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(debug_str.GetUnsafePointer()), len), svc::ResultInvalidCurrentMemory());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(debug_str.GetUnsafePointer()), len), svc::ResultInvalidPointer());
/* Output the string. */
R_RETURN(KDebugLog::PrintUserString(debug_str, len));

View File

@@ -70,7 +70,7 @@ namespace ams::kern::svc {
}
/* Exit the current process. */
GetCurrentProcess().Exit();
GetCurrentProcess().Exit(-1ll);
}
}

View File

@@ -109,6 +109,15 @@ namespace ams::kern::svc {
case ams::svc::InfoType_AliasRegionExtraSize:
*out = process->GetPageTable().GetAliasRegionExtraSize();
break;
case ams::svc::InfoType_AddressSpaceSize:
*out = process->GetAddressSpaceSize();
break;
case ams::svc::InfoType_ShadowStackRegionAddress:
*out = GetInteger(process->GetPageTable().GetShadowStackRegionStart());
break;
case ams::svc::InfoType_ShadowStackRegionSize:
*out = process->GetPageTable().GetShadowStackRegionSize();
break;
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
}
@@ -138,6 +147,9 @@ namespace ams::kern::svc {
case ams::svc::InfoType_IsApplication:
case ams::svc::InfoType_FreeThreadCount:
case ams::svc::InfoType_AliasRegionExtraSize:
case ams::svc::InfoType_AddressSpaceSize:
case ams::svc::InfoType_ShadowStackRegionAddress:
case ams::svc::InfoType_ShadowStackRegionSize:
{
/* These info types don't support non-zero subtypes. */
R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination());

View File

@@ -110,7 +110,7 @@ namespace ams::kern::svc {
/* Copy user handles. */
if (num_handles > 0) {
/* Ensure that we can try to get the handles. */
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer());
/* Get the handles. */
R_TRY(user_handles.CopyArrayTo(handles, num_handles));

View File

@@ -21,13 +21,15 @@ namespace ams::kern::svc {
namespace {
constexpr bool IsKernelAddress(uintptr_t address) {
return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
constexpr bool IsValidAddress(uintptr_t address) {
if (KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd) return false;
if (GetCurrentProcess().GetPageTable().IsInShadowStackRegion(address)) return false;
return true;
}
Result ArbitrateLock(ams::svc::Handle thread_handle, uintptr_t address, uint32_t tag) {
/* Validate the input address. */
R_UNLESS(!IsKernelAddress(address), svc::ResultInvalidCurrentMemory());
R_UNLESS(IsValidAddress(address), svc::ResultInvalidCurrentMemory());
R_UNLESS(util::IsAligned(address, sizeof(u32)), svc::ResultInvalidAddress());
R_RETURN(KConditionVariable::WaitForAddress(thread_handle, address, tag));
@@ -35,7 +37,7 @@ namespace ams::kern::svc {
Result ArbitrateUnlock(uintptr_t address) {
/* Validate the input address. */
R_UNLESS(!IsKernelAddress(address), svc::ResultInvalidCurrentMemory());
R_UNLESS(IsValidAddress(address), svc::ResultInvalidCurrentMemory());
R_UNLESS(util::IsAligned(address, sizeof(u32)), svc::ResultInvalidAddress());
R_RETURN(KConditionVariable::SignalToAddress(address));

View File

@@ -21,11 +21,22 @@ namespace ams::kern::svc {
namespace {
static Result GetPortName(char (&name)[KObjectName::NameLengthMax], KUserPointer<const char *> user_name) {
/* Copy the provided name from user memory to kernel memory. */
R_TRY(user_name.CopyStringTo(name, sizeof(name)));
/* Oddly enough N here first copies then validates if it's not in forbidden range. */
const auto name_len = util::Strnlen(name, sizeof(name));
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_name.GetUnsafePointer()), name_len + 1), svc::ResultInvalidPointer());
R_SUCCEED();
}
Result ManageNamedPort(ams::svc::Handle *out_server_handle, KUserPointer<const char *> user_name, s32 max_sessions) {
/* Copy the provided name from user memory to kernel memory. */
char name[KObjectName::NameLengthMax] = {};
R_TRY(user_name.CopyStringTo(name, sizeof(name)));
R_TRY(GetPortName(name, user_name));
/* Validate that sessions and name are valid. */
R_UNLESS(max_sessions >= 0, svc::ResultOutOfRange());
R_UNLESS(name[sizeof(name) - 1] == '\x00', svc::ResultOutOfRange());
@@ -106,7 +117,7 @@ namespace ams::kern::svc {
Result ConnectToNamedPort(ams::svc::Handle *out, KUserPointer<const char *> user_name) {
/* Copy the provided name from user memory to kernel memory. */
char name[KObjectName::NameLengthMax] = {};
R_TRY(user_name.CopyStringTo(name, sizeof(name)));
R_TRY(GetPortName(name, user_name));
/* Validate that name is valid. */
R_UNLESS(name[sizeof(name) - 1] == '\x00', svc::ResultOutOfRange());

View File

@@ -25,8 +25,9 @@ namespace ams::kern::svc {
return (0 <= core_id && core_id < static_cast<int32_t>(cpu::NumVirtualCores));
}
void ExitProcess() {
GetCurrentProcess().Exit();
void ExitProcess(int64_t exit_tag) {
const uint32_t intended_kernel_major_version = GetCurrentProcess().GetIntendedKernelMajorVersion();
GetCurrentProcess().Exit(intended_kernel_major_version <= 26 ? -1ll : exit_tag);
MESOSPHERE_PANIC("Process survived call to exit");
}
@@ -79,13 +80,47 @@ namespace ams::kern::svc {
/* Validate that the pointer is in range. */
if (max_out_count > 0) {
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(out_process_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidCurrentMemory());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_process_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidPointer());
}
/* Get the process list. */
R_RETURN(KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count));
}
constexpr size_t GetProcessSlotT0Sz(ams::svc::CreateProcessParameterFlag flags) {
if ((flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) == ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42) {
return (64 - 42);
} else {
return (64 - 39);
}
}
KProcess *CreateProcessForAddressSpace(ams::svc::CreateProcessParameterFlag flags) {
/* Find a process slab slot whose root page table is meant for the requested address space. */
const size_t desired_t0sz = GetProcessSlotT0Sz(flags);
KProcess *process = nullptr;
KProcess *rejected[init::SlabCountKProcess];
size_t num_rejected = 0;
while ((process = KProcess::Create()) != nullptr) {
/* Stop once we find a slot whose T0SZ matches. */
if ((KProcessPageTable::GetProcessTcrEl1(process->GetSlabIndex()) & 0x3F) == desired_t0sz) {
break;
}
/* Otherwise, park the process and try the next slot. */
rejected[num_rejected++] = process;
process = nullptr;
}
/* Release every process we parked while searching. */
for (size_t i = 0; i < num_rejected; ++i) {
rejected[i]->Close();
}
return process;
}
Result CreateProcess(ams::svc::Handle *out, const ams::svc::CreateProcessParameter &params, KUserPointer<const uint32_t *> user_caps, int32_t num_caps) {
/* Validate the capabilities pointer. */
R_UNLESS(num_caps >= 0, svc::ResultInvalidPointer());
@@ -94,14 +129,17 @@ namespace ams::kern::svc {
R_UNLESS(((num_caps * sizeof(u32)) / sizeof(u32)) == static_cast<size_t>(num_caps), svc::ResultInvalidPointer());
/* Validate that the pointer is in range. */
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(user_caps.GetUnsafePointer()), num_caps * sizeof(u32)), svc::ResultInvalidPointer());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_caps.GetUnsafePointer()), num_caps * sizeof(u32)), svc::ResultInvalidPointer());
}
/* Validate that the parameter flags are valid. */
R_UNLESS((params.flags & ~ams::svc::CreateProcessFlag_All) == 0, svc::ResultInvalidEnumValue());
R_UNLESS((params.flags & ~ams::svc::CreateProcessParameterFlag_All) == 0, svc::ResultInvalidEnumValue());
/* The 64KB page size is not yet allowed. */
R_UNLESS((params.flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) != ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42, svc::ResultInvalidCombination());
/* Validate that 64-bit process is okay. */
const bool is_64_bit = (params.flags & ams::svc::CreateProcessFlag_Is64Bit) != 0;
const bool is_64_bit = (params.flags & ams::svc::CreateProcessParameterFlag_64Bit) != 0;
if constexpr (sizeof(void *) < sizeof(u64)) {
R_UNLESS(!is_64_bit, svc::ResultInvalidCombination());
}
@@ -110,34 +148,35 @@ namespace ams::kern::svc {
uintptr_t map_start, map_end;
size_t map_size;
const size_t code_size = params.code_num_pages * PageSize;
switch (params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) {
case ams::svc::CreateProcessFlag_AddressSpace32Bit:
case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias:
switch (params.flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) {
case ams::svc::CreateProcessParameterFlag_AddressSpace32Bit:
case ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved:
{
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall);
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall);
map_end = map_start + map_size;
}
break;
case ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated:
case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36:
{
/* 64-bit address space requires 64-bit process. */
R_UNLESS(is_64_bit, svc::ResultInvalidCombination());
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall);
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall);
map_end = map_start + map_size;
}
break;
case ams::svc::CreateProcessFlag_AddressSpace64Bit:
case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39:
case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42:
{
/* 64-bit address space requires 64-bit process. */
R_UNLESS(is_64_bit, svc::ResultInvalidCombination());
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Map39Bit, code_size);
map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Map39Bit);
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapHuge, code_size);
map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapHuge);
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Heap);
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_Heap);
}
break;
default:
@@ -146,11 +185,11 @@ namespace ams::kern::svc {
/* Validate the pool partition. */
if (GetTargetFirmware() >= TargetFirmware_5_0_0) {
switch (params.flags & ams::svc::CreateProcessFlag_PoolPartitionMask) {
case ams::svc::CreateProcessFlag_PoolPartitionApplication:
case ams::svc::CreateProcessFlag_PoolPartitionApplet:
case ams::svc::CreateProcessFlag_PoolPartitionSystem:
case ams::svc::CreateProcessFlag_PoolPartitionSystemNonSecure:
switch (params.flags & ams::svc::CreateProcessParameterFlag_PoolPartitionMask) {
case ams::svc::CreateProcessParameterFlag_PoolPartitionApplication:
case ams::svc::CreateProcessParameterFlag_PoolPartitionApplet:
case ams::svc::CreateProcessParameterFlag_PoolPartitionSystem:
case ams::svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure:
break;
default:
R_THROW(svc::ResultInvalidEnumValue());
@@ -166,10 +205,10 @@ namespace ams::kern::svc {
/* Check that the number of extra resource pages is >= 0. */
R_UNLESS(params.system_resource_num_pages >= 0, svc::ResultInvalidSize());
/* Validate that the alias region extra size is allowed, if enabled. */
if (params.flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) {
/* Validate that the address sanitizer is allowed, if enabled. */
if (params.flags & ams::svc::CreateProcessParameterFlag_EnableAddressSanitizer) {
/* Check that we have a 64-bit address space. */
R_UNLESS((params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace64Bit, svc::ResultInvalidState());
R_UNLESS((params.flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) == ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39, svc::ResultInvalidState());
/* Check that the system resource page count is non-zero. */
R_UNLESS(params.system_resource_num_pages > 0, svc::ResultInvalidState());
@@ -205,8 +244,8 @@ namespace ams::kern::svc {
R_UNLESS(total_pages < (kern::MainMemorySizeMax / PageSize), svc::ResultOutOfMemory());
/* Check that optimized memory allocation is used only for applications. */
const bool optimize_allocs = (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0;
const bool is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
const bool optimize_allocs = (params.flags & ams::svc::CreateProcessParameterFlag_OptimizeMemoryAllocation) != 0;
const bool is_application = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) != 0;
R_UNLESS(!optimize_allocs || is_application, svc::ResultBusy());
/* Check that the user-provided capabilities are accessible and refer to valid regions. */
@@ -215,8 +254,8 @@ namespace ams::kern::svc {
/* Get the current handle table. */
auto &handle_table = GetCurrentProcess().GetHandleTable();
/* Create the new process. */
KProcess *process = KProcess::Create();
/* Create the new process, ensuring its page table slot matches the requested address space. */
KProcess *process = CreateProcessForAddressSpace(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags));
R_UNLESS(process != nullptr, svc::ResultOutOfResource());
/* Ensure that the only reference to the process is in the handle table when we're done. */
@@ -232,19 +271,19 @@ namespace ams::kern::svc {
/* Get the pool for the process. */
const auto pool = [](u32 flags) ALWAYS_INLINE_LAMBDA -> KMemoryManager::Pool {
if (GetTargetFirmware() >= TargetFirmware_5_0_0) {
switch (flags & ams::svc::CreateProcessFlag_PoolPartitionMask) {
case ams::svc::CreateProcessFlag_PoolPartitionApplication:
switch (flags & ams::svc::CreateProcessParameterFlag_PoolPartitionMask) {
case ams::svc::CreateProcessParameterFlag_PoolPartitionApplication:
return KMemoryManager::Pool_Application;
case ams::svc::CreateProcessFlag_PoolPartitionApplet:
case ams::svc::CreateProcessParameterFlag_PoolPartitionApplet:
return KMemoryManager::Pool_Applet;
case ams::svc::CreateProcessFlag_PoolPartitionSystem:
case ams::svc::CreateProcessParameterFlag_PoolPartitionSystem:
return KMemoryManager::Pool_System;
case ams::svc::CreateProcessFlag_PoolPartitionSystemNonSecure:
case ams::svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure:
default:
return KMemoryManager::Pool_SystemNonSecure;
}
} else if (GetTargetFirmware() >= TargetFirmware_4_0_0) {
if ((flags & ams::svc::CreateProcessFlag_DeprecatedUseSecureMemory) != 0) {
if ((flags & ams::svc::CreateProcessParameterFlag_DeprecatedUseSecureMemory) != 0) {
return KMemoryManager::Pool_Secure;
} else {
return static_cast<KMemoryManager::Pool>(KSystemControl::GetCreateProcessMemoryPool());
@@ -319,7 +358,7 @@ namespace ams::kern::svc {
R_RETURN(process->Run(priority, static_cast<size_t>(aligned_stack_size)));
}
Result TerminateProcess(ams::svc::Handle process_handle) {
Result TerminateProcess(ams::svc::Handle process_handle, int64_t exit_tag) {
/* Get the target process. */
KProcess *process = GetCurrentProcess().GetHandleTable().GetObject<KProcess>(process_handle).ReleasePointerUnsafe();
R_UNLESS(process != nullptr, svc::ResultInvalidHandle());
@@ -329,13 +368,13 @@ namespace ams::kern::svc {
ON_SCOPE_EXIT { process->Close(); };
/* Terminate the process. */
R_TRY(process->Terminate());
R_TRY(process->Terminate(exit_tag));
} else {
/* We're terminating ourselves. Close our reference immediately. */
process->Close();
/* Exit. */
ExitProcess();
ExitProcess(exit_tag);
}
R_SUCCEED();
@@ -373,6 +412,20 @@ namespace ams::kern::svc {
}
}
break;
case ams::svc::ProcessInfoType_Unknown1:
{
/* TODO: 23.0.0+ added a new process info type. Figure out what this is. */
/* For now just call it an exit tag since it's only set during Exit or Terminate. */
int64_t exit_tag;
{
KScopedLightLock proc_lk(process->GetStateLock());
exit_tag = process->GetExitTag();
}
*out = exit_tag;
}
break;
default:
R_THROW(svc::ResultInvalidEnumValue());
}
@@ -385,7 +438,9 @@ namespace ams::kern::svc {
/* ============================= 64 ABI ============================= */
void ExitProcess64() {
return ExitProcess();
/* TODO: 23.0.0+ changed the actual SVC handler. */
/* For now just pass the default value for the exit tag. */
return ExitProcess(-1ll);
}
Result GetProcessId64(uint64_t *out_process_id, ams::svc::Handle process_handle) {
@@ -405,7 +460,9 @@ namespace ams::kern::svc {
}
Result TerminateProcess64(ams::svc::Handle process_handle) {
R_RETURN(TerminateProcess(process_handle));
/* TODO: 23.0.0+ changed the actual SVC handler. */
/* For now just pass the default value for the exit tag. */
R_RETURN(TerminateProcess(process_handle, -1ll));
}
Result GetProcessInfo64(int64_t *out_info, ams::svc::Handle process_handle, ams::svc::ProcessInfoType info_type) {
@@ -415,7 +472,9 @@ namespace ams::kern::svc {
/* ============================= 64From32 ABI ============================= */
void ExitProcess64From32() {
return ExitProcess();
/* TODO: 23.0.0+ changed the actual SVC handler. */
/* For now just pass the default value for the exit tag. */
return ExitProcess(-1ll);
}
Result GetProcessId64From32(uint64_t *out_process_id, ams::svc::Handle process_handle) {
@@ -435,7 +494,9 @@ namespace ams::kern::svc {
}
Result TerminateProcess64From32(ams::svc::Handle process_handle) {
R_RETURN(TerminateProcess(process_handle));
/* TODO: 23.0.0+ changed the actual SVC handler. */
/* For now just pass the default value for the exit tag. */
R_RETURN(TerminateProcess(process_handle, -1ll));
}
Result GetProcessInfo64From32(int64_t *out_info, ams::svc::Handle process_handle, ams::svc::ProcessInfoType info_type) {

View File

@@ -148,7 +148,7 @@ namespace ams::kern::svc {
/* Validate that the mapping is in range. */
auto &page_table = process->GetPageTable();
R_UNLESS(page_table.Contains(src_address, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidCurrentMemory());
R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidMemoryRegion());
/* Map the memory. */
R_TRY(page_table.MapCodeMemory(dst_address, src_address, size));
@@ -175,7 +175,7 @@ namespace ams::kern::svc {
/* Validate that the mapping is in range. */
auto &page_table = process->GetPageTable();
R_UNLESS(page_table.Contains(src_address, size), svc::ResultInvalidCurrentMemory());
R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidCurrentMemory());
R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidMemoryRegion());
/* Unmap the memory. */
R_TRY(page_table.UnmapCodeMemory(dst_address, src_address, size));

View File

@@ -37,6 +37,8 @@ namespace ams::kern::svc {
template<typename T>
Result QueryProcessMemory(KUserPointer<T *> out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle process_handle, uint64_t address) {
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_memory_info.GetUnsafePointer()), sizeof(T)), svc::ResultInvalidPointer());
/* Get an ams::svc::MemoryInfo for the region. */
ams::svc::MemoryInfo info = {};
R_TRY(QueryProcessMemory(std::addressof(info), out_page_info, process_handle, address));

View File

@@ -28,6 +28,8 @@ namespace ams::kern::svc {
/* ============================= 64 ABI ============================= */
void CallSecureMonitor64(ams::svc::lp64::SecureMonitorArguments *args) {
/* TODO: 23.0.0+ added a second argument to CallSecureMonitorFromUser. */
/* On NX, CallSecureMonitor64 always passes 0 for this argument. */
KSystemControl::CallSecureMonitorFromUser(args);
}

View File

@@ -82,7 +82,7 @@ namespace ams::kern::svc {
/* Copy user handles. */
if (num_handles > 0) {
/* Ensure that we can try to get the handles. */
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer());
/* Get the handles. */
R_TRY(user_handles.CopyArrayTo(handles, num_handles));

View File

@@ -204,6 +204,8 @@ namespace ams::kern::svc {
/* Get the thread from its handle. */
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_context.GetUnsafePointer()), sizeof(ams::svc::ThreadContext)), svc::ResultInvalidPointer());
/* Require the handle be to a non-current thread in the current process. */
R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(), svc::ResultInvalidHandle());
@@ -228,7 +230,7 @@ namespace ams::kern::svc {
/* Validate that the pointer is in range. */
if (max_out_count > 0) {
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(out_thread_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidCurrentMemory());
R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_thread_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidPointer());
}
/* Get the handle table. */

View File

@@ -31,10 +31,11 @@ namespace ams::cfg {
OverrideStatusFlag_AddressSpaceMask = ((1u << 2) - 1) << OverrideStatusFlag_AddressSpaceShift,
#if defined(ATMOSPHERE_OS_HORIZON)
OverrideStatusFlag_AddressSpace32Bit = (svc::CreateProcessFlag_AddressSpace32Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace64BitDeprecated = (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace32BitWithoutAlias = (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace64Bit = (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace32Bit = (svc::CreateProcessParameterFlag_AddressSpace32Bit >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace64Bit36 = (svc::CreateProcessParameterFlag_AddressSpace64Bit36 >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace32BitNoReserved = (svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace64Bit39 = (svc::CreateProcessParameterFlag_AddressSpace64Bit39 >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace64Bit42 = (svc::CreateProcessParameterFlag_AddressSpace64Bit42 >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
#endif
};

View File

@@ -195,6 +195,8 @@
HANDLER(PscTransitionStateInfo, 154 ) \
HANDLER(FsProxyErrorInfo3, 155 ) \
HANDLER(BluetoothErrorInfo, 156 ) \
HANDLER(SystemConfigInfo, 157 ) \
HANDLER(ClockContextInfo, 158 ) \
HANDLER(TestNx, 1000) \
HANDLER(NANDTypeInfo, 1001) \
HANDLER(NANDExtendedCsd, 1002) \
@@ -239,9 +241,9 @@
HANDLER(WirelessAPMacAddress, 35, WirelessAPMacAddressInfo, FieldType_String, FieldFlag_None ) \
HANDLER(GlobalIPAddress, 36, GlobalIPAddressInfo, FieldType_String, FieldFlag_None ) \
HANDLER(EnableWirelessInterfaceFlag, 37, EnableWirelessInterfaceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableWifiFlag, 38, EnableWifiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableBluetoothFlag, 39, EnableBluetoothInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableNFCFlag, 40, EnableNFCInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableWifiFlag, 38, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableBluetoothFlag, 39, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableNFCFlag, 40, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NintendoZoneSSIDListVersion, 41, NintendoZoneSSIDListVersionInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LANAdapterMacAddress, 42, LANAdapterMacAddressInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ApplicationID, 43, ApplicationInfo, FieldType_String, FieldFlag_None ) \
@@ -259,9 +261,9 @@
HANDLER(ApplicationRunningFlag, 55, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(DataCorruptionDetectedFlag, 56, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ProductModel, 57, ProductModelInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CurrentLanguage, 58, CurrentLanguageInfo, FieldType_String, FieldFlag_None ) \
HANDLER(UseNetworkTimeProtocolFlag, 59, UseNetworkTimeProtocolInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TimeZone, 60, TimeZoneInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CurrentLanguage, 58, SystemConfigInfo, FieldType_String, FieldFlag_None ) \
HANDLER(UseNetworkTimeProtocolFlag, 59, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TimeZone, 60, SystemConfigInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ControllerFirmware, 61, ControllerFirmwareInfo, FieldType_String, FieldFlag_None ) \
HANDLER(VideoOutputSetting, 62, VideoOutputInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NANDFreeSpace, 63, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
@@ -272,23 +274,23 @@
HANDLER(HdmiAudioOutputMode, 68, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
HANDLER(SpeakerAudioOutputMode, 69, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
HANDLER(HeadphoneAudioOutputMode, 70, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
HANDLER(MuteOnHeadsetUnpluggedFlag, 71, MuteOnHeadsetUnpluggedInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(MuteOnHeadsetUnpluggedFlag, 71, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NumUserRegistered, 72, NumUserRegisteredInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(StorageAutoOrganizeFlag, 73, DataDeletionInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ControllerVibrationVolume, 74, ControllerVibrationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LockScreenFlag, 75, LockScreenInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ControllerVibrationVolume, 74, SystemConfigInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LockScreenFlag, 75, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(InternalBatteryLotNumber, 76, InternalBatteryLotNumberInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LeftControllerSerialNumber, 77, LeftControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RightControllerSerialNumber, 78, RightControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NotifyInGameDownloadCompletionFlag, 79, NotificationInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NotificationSoundFlag, 80, NotificationInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NotifyInGameDownloadCompletionFlag, 79, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NotificationSoundFlag, 80, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TVResolutionSetting, 81, TVInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RGBRangeSetting, 82, TVInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ReduceScreenBurnFlag, 83, TVInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TVAllowsCecFlag, 84, TVInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(HandheldModeTimeToScreenSleep, 85, SleepInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ConsoleModeTimeToScreenSleep, 86, SleepInfo, FieldType_String, FieldFlag_None ) \
HANDLER(StopAutoSleepDuringContentPlayFlag, 87, SleepInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(HandheldModeTimeToScreenSleep, 85, SystemConfigInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ConsoleModeTimeToScreenSleep, 86, SystemConfigInfo, FieldType_String, FieldFlag_None ) \
HANDLER(StopAutoSleepDuringContentPlayFlag, 87, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(LastConnectionTestDownloadSpeed, 88, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(LastConnectionTestUploadSpeed, 89, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(DEPRECATED_ServerFQDN, 90, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
@@ -611,7 +613,7 @@
HANDLER(ElapsedTimeSincePowerOn, 407, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ElapsedTimeSinceLastAwake, 408, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(OccurrenceTick, 409, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(RetailInteractiveDisplayFlag, 410, RetailInteractiveDisplayInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(RetailInteractiveDisplayFlag, 410, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(FatFsError, 411, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FatFsExtraError, 412, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FatFsErrorDrive, 413, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
@@ -627,7 +629,7 @@
HANDLER(Is720P60Hz, 423, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
HANDLER(PcmChannelMax, 424, MonitorCapability, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(CrashReportHash, 425, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ErrorReportSharePermission, 426, ErrorReportSharePermissionInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(ErrorReportSharePermission, 426, SystemConfigInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(VideoCodecTypeEnum, 427, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(VideoBitRate, 428, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(VideoFrameRate, 429, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
@@ -673,10 +675,10 @@
HANDLER(FsPatrolReadAllocateBufferFailureCount, 469, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SteadyClockInternalOffset, 470, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SteadyClockCurrentTimePointValue, 471, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(UserClockContextOffset, 472, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(UserClockContextTimeStampValue, 473, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(NetworkClockContextOffset, 474, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(NetworkClockContextTimeStampValue, 475, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(UserClockContextOffset, 472, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(UserClockContextTimeStampValue, 473, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(NetworkClockContextOffset, 474, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(NetworkClockContextTimeStampValue, 475, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemAbortFlag, 476, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ApplicationAbortFlag, 477, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NifmErrorCode, 478, ConnectionStatusInfo, FieldType_String, FieldFlag_None ) \
@@ -819,16 +821,16 @@
HANDLER(ErrorContext, 615, ErrorInfoAuto, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ErrorContextSize, 616, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(ErrorContextTotalSize, 617, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SystemPhysicalMemoryLimit, 618, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemThreadCountLimit, 619, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemEventCountLimit, 620, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemTransferMemoryCountLimit, 621, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemSessionCountLimit, 622, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemPhysicalMemoryPeak, 623, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemThreadCountPeak, 624, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemEventCountPeak, 625, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemTransferMemoryCountPeak, 626, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemSessionCountPeak, 627, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemPhysicalMemoryLimit, 618, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemThreadCountLimit, 619, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemEventCountLimit, 620, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemTransferMemoryCountLimit, 621, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemSessionCountLimit, 622, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemPhysicalMemoryPeak, 623, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemThreadCountPeak, 624, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemEventCountPeak, 625, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemTransferMemoryCountPeak, 626, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemSessionCountPeak, 627, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(GpuCrashHash, 628, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(TouchScreenPanelGpioValue, 629, TouchScreenInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(BrowserCertificateHostName, 630, ErrorInfo, FieldType_String, FieldFlag_None ) \
@@ -886,10 +888,10 @@
HANDLER(AppletId, 682, ApplicationInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(PrevReportIdentifier, 683, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
HANDLER(SyslogStartupTimeBase, 684, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(NxdmpIsAttached, 685, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ScreenshotIsAttached, 686, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(SyslogIsAttached, 687, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(SaveSyslogResult, 688, AttachmentFileInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NxdmpIsAttached, 685, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
HANDLER(ScreenshotIsAttached, 686, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
HANDLER(SyslogIsAttached, 687, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
HANDLER(SaveSyslogResult, 688, ErrorInfoAuto, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(EncryptionKeyGeneration, 689, ErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FsBufferManagerNonBlockingRetriedCount, 690, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsPooledBufferNonBlockingRetriedCount, 691, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
@@ -897,11 +899,11 @@
HANDLER(LastConnectionTestUploadSpeed64, 693, ConnectionInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(EncryptionKeyV1, 694, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(GpuCrashDumpAttachmentId, 695, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(GpuCrashDumpIsAttached, 696, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(GpuCrashDumpIsAttached, 696, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
HANDLER(CallerIdentifier, 697, ErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(WlanMainState, 698, WlanInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(WlanSubState, 699, WlanInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AdspSyslogIsAttached, 702, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(AdspSyslogIsAttached, 702, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
HANDLER(LastHalfAwakeTime, 703, HalfAwakeStateInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(LastHalfAwakeTimeAfterBackgroundTaskDone, 704, HalfAwakeStateInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(LastHalfAwakeTimeAfterStateUnlocked, 705, HalfAwakeStateInfo, FieldType_NumericI64, FieldFlag_None ) \
@@ -979,6 +981,17 @@
HANDLER(FsSaveDataFileSystemPeakMountCount, 777, FsProxyErrorInfo3, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(TestBool, 778, Test, FieldType_Bool, FieldFlag_None ) \
HANDLER(TestI8Array, 779, Test, FieldType_I8Array, FieldFlag_None ) \
HANDLER(CloudFrontAmzCfId, 780, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(SslProcessHeapAllocatable, 781, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AppletSyslogIsAttached, 782, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
HANDLER(FsBisSaveDataFailedRetryMountCount, 783, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsSdSaveDataFailedRetryMountCount, 784, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsBisSaveDataRecoveredRetryMountCount, 785, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsSdSaveDataRecoveredRetryMountCount, 786, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(BrowserEngineOpenUrl, 787, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(FsVariant, 788, SystemSettingInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(KnownServerFqdnId, 789, ErrorInfoAuto, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AcpStreamPlaySaveDataKeyType, 790, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(TestStringNx, 1000, TestNx, FieldType_String, FieldFlag_None ) \
HANDLER(BoostModeCurrentLimit, 1001, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(ChargeConfiguration, 1002, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \

View File

@@ -111,6 +111,7 @@ namespace ams::erpt {
struct CreateReportOptionFlag {
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>;
@@ -271,5 +272,14 @@ namespace ams::erpt {
char product_model[16];
const char *region;
};
struct SubmitAttachmentOptionFlag {
using Lz4Compression = util::BitFlagSet<BITSIZEOF(u32), SubmitAttachmentOptionFlag>::Flag<0>;
using Unknown0x10000 = util::BitFlagSet<BITSIZEOF(u32), SubmitAttachmentOptionFlag>::Flag<16>; /* TODO: Figure out what this is. Always forced to 1. */
};
using SubmitAttachmentOptionFlagSet = util::BitFlagSet<BITSIZEOF(u32), SubmitAttachmentOptionFlag>;
static_assert(util::is_pod<SubmitAttachmentOptionFlagSet>::value);
static_assert(sizeof(SubmitAttachmentOptionFlagSet) == sizeof(u32));
}

View File

@@ -34,14 +34,15 @@
AMS_SF_METHOD_INFO(C, H, 7, Result, RegisterRunningApplicationInfo, (ncm::ApplicationId app_id, ncm::ProgramId program_id), (app_id, program_id), hos::Version_21_0_0) \
AMS_SF_METHOD_INFO(C, H, 8, Result, ClearApplicationLaunchTime, (), (), hos::Version_6_0_0, hos::Version_20_5_0) \
AMS_SF_METHOD_INFO(C, H, 8, Result, UnregisterRunningApplicationInfo, (), (), hos::Version_21_0_0) \
AMS_SF_METHOD_INFO(C, H, 9, Result, SubmitAttachment, (ams::sf::Out<erpt::AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_8_0_0) \
AMS_SF_METHOD_INFO(C, H, 9, Result, SubmitAttachmentDeprecated, (ams::sf::Out<erpt::AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_8_0_0, hos::Version_22_5_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachmentsDeprecated, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer), (report_type, ctx_buffer, str_buffer, attachment_ids_buffer), hos::Version_8_0_0, hos::Version_10_2_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachmentsDeprecated2, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result), (report_type, ctx_buffer, str_buffer, attachment_ids_buffer, result), hos::Version_11_0_0, hos::Version_16_1_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachments, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result, erpt::CreateReportOptionFlagSet flags), (report_type, ctx_buffer, str_buffer, attachment_ids_buffer, result, flags), hos::Version_17_0_0) \
AMS_SF_METHOD_INFO(C, H, 11, Result, CreateReportV1, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, Result result), (report_type, ctx_buffer, str_buffer, meta_buffer, result), hos::Version_11_0_0) \
AMS_SF_METHOD_INFO(C, H, 12, Result, CreateReport, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, Result result, erpt::CreateReportOptionFlagSet flags), (report_type, ctx_buffer, str_buffer, meta_buffer, result, flags), hos::Version_17_0_0) \
AMS_SF_METHOD_INFO(C, H, 13, Result, SubmitAttachmentWithLz4Compression, (ams::sf::Out<erpt::AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_20_0_0) \
AMS_SF_METHOD_INFO(C, H, 13, Result, SubmitAttachmentWithLz4Compression, (ams::sf::Out<erpt::AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_20_0_0, hos::Version_22_5_0) \
AMS_SF_METHOD_INFO(C, H, 14, Result, CreateReportWithSpecifiedReprotId, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result, erpt::CreateReportOptionFlagSet flags, const erpt::ReportId &report_id), (report_type, ctx_buffer, str_buffer, meta_buffer, attachment_ids_buffer, result, flags, report_id), hos::Version_20_0_0) \
AMS_SF_METHOD_INFO(C, H, 15, Result, SubmitAttachment, (ams::sf::Out<erpt::AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data, erpt::SubmitAttachmentOptionFlagSet flags), (out, attachment_name, attachment_data, flags), hos::Version_23_0_0) \
AMS_SF_METHOD_INFO(C, H, 20, Result, RegisterRunningApplet, (ncm::ProgramId program_id), (program_id), hos::Version_12_0_0) \
AMS_SF_METHOD_INFO(C, H, 21, Result, UnregisterRunningApplet, (ncm::ProgramId program_id), (program_id), hos::Version_12_0_0) \
AMS_SF_METHOD_INFO(C, H, 22, Result, UpdateAppletSuspendedDuration, (ncm::ProgramId program_id, TimeSpanType duration), (program_id, duration), hos::Version_12_0_0) \

View File

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

View File

@@ -21,17 +21,17 @@
#include <stratosphere/gpio/gpio_select_pad_name.hpp>
#include <stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp>
#define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, s32 pad_descriptor), (out, pad_descriptor) ) \
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name) ) \
AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTest, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name) ) \
AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActive, (ams::sf::Out<bool> out, gpio::GpioPadName pad_name), (out, pad_name), hos::Version_Min, hos::Version_6_2_0) \
AMS_SF_METHOD_INFO(C, H, 4, Result, GetWakeEventActiveFlagSet, (ams::sf::Out<gpio::WakeBitFlag> out), (out), hos::Version_Min, hos::Version_6_2_0) \
AMS_SF_METHOD_INFO(C, H, 5, Result, SetWakeEventActiveFlagSetForDebug, (gpio::GpioPadName pad_name, bool is_enabled), (pad_name, is_enabled), hos::Version_Min, hos::Version_6_2_0) \
AMS_SF_METHOD_INFO(C, H, 6, Result, SetWakePinDebugMode, (s32 mode), (mode) ) \
AMS_SF_METHOD_INFO(C, H, 7, Result, OpenSession2, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, DeviceCode device_code, ddsf::AccessMode access_mode), (out, device_code, access_mode), hos::Version_5_0_0 ) \
AMS_SF_METHOD_INFO(C, H, 8, Result, IsWakeEventActive2, (ams::sf::Out<bool> out, DeviceCode device_code), (out, device_code), hos::Version_5_0_0 ) \
AMS_SF_METHOD_INFO(C, H, 9, Result, SetWakeEventActiveFlagSetForDebug2, (DeviceCode device_code, bool is_enabled), (device_code, is_enabled), hos::Version_5_0_0 ) \
AMS_SF_METHOD_INFO(C, H, 10, Result, SetRetryValues, (u32 arg0, u32 arg1), (arg0, arg1), hos::Version_6_0_0 )
#define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDevDeprecated, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, s32 pad_descriptor), (out, pad_descriptor)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSessionDeprecated, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTestDeprecated, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActiveDeprecated, (ams::sf::Out<bool> out, gpio::GpioPadName pad_name), (out, pad_name), hos::Version_1_0_0, hos::Version_6_2_0) \
AMS_SF_METHOD_INFO(C, H, 4, Result, GetWakeEventActiveFlagSetDeprecated, (ams::sf::Out<gpio::WakeBitFlag> out), (out), hos::Version_1_0_0, hos::Version_6_2_0) \
AMS_SF_METHOD_INFO(C, H, 5, Result, SetWakeEventActiveFlagSetForDebugDeprecated, (gpio::GpioPadName pad_name, bool is_enabled), (pad_name, is_enabled), hos::Version_1_0_0, hos::Version_6_2_0) \
AMS_SF_METHOD_INFO(C, H, 6, Result, SetWakePinDebugMode, (s32 mode), (mode)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, OpenSession, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, DeviceCode device_code, ddsf::AccessMode access_mode), (out, device_code, access_mode), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 8, Result, IsWakeEventActive, (ams::sf::Out<bool> out, DeviceCode device_code), (out, device_code), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 9, Result, SetWakeEventActiveFlagSetForDebug, (DeviceCode device_code, bool is_enabled), (device_code, is_enabled), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, DumpStateForDebug, (u32 arg0, u32 arg1), (arg0, arg1), hos::Version_6_0_0)
AMS_SF_DEFINE_INTERFACE(ams::gpio::sf, IManager, AMS_GPIO_I_MANAGER_INTERFACE_INFO, 0xD219501E)

View File

@@ -18,24 +18,28 @@
#include <vapours.hpp>
#include <stratosphere/gpio/gpio_types.hpp>
#define AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, SetDirection, (gpio::Direction direction), (direction) ) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetDirection, (ams::sf::Out<gpio::Direction> out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 2, Result, SetInterruptMode, (gpio::InterruptMode mode), (mode) ) \
AMS_SF_METHOD_INFO(C, H, 3, Result, GetInterruptMode, (ams::sf::Out<gpio::InterruptMode> out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 4, Result, SetInterruptEnable, (bool enable), (enable) ) \
AMS_SF_METHOD_INFO(C, H, 5, Result, GetInterruptEnable, (ams::sf::Out<bool> out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out<gpio::InterruptStatus> out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 7, Result, ClearInterruptStatus, (), () ) \
AMS_SF_METHOD_INFO(C, H, 8, Result, SetValue, (gpio::GpioValue value), (value) ) \
AMS_SF_METHOD_INFO(C, H, 9, Result, GetValue, (ams::sf::Out<gpio::GpioValue> out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 10, Result, BindInterrupt, (ams::sf::OutCopyHandle out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 11, Result, UnbindInterrupt, (), () ) \
AMS_SF_METHOD_INFO(C, H, 12, Result, SetDebounceEnabled, (bool enable), (enable) ) \
AMS_SF_METHOD_INFO(C, H, 13, Result, GetDebounceEnabled, (ams::sf::Out<bool> out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 14, Result, SetDebounceTime, (s32 ms), (ms) ) \
AMS_SF_METHOD_INFO(C, H, 15, Result, GetDebounceTime, (ams::sf::Out<s32> out), (out) ) \
AMS_SF_METHOD_INFO(C, H, 16, Result, SetValueForSleepState, (gpio::GpioValue value), (value), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 16, Result, GetValueForSleepState, (ams::sf::Out<gpio::GpioValue> out), (out), hos::Version_6_0_0)
#define AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, SetDirectionDeprecated, (gpio::Direction direction), (direction)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetDirection, (ams::sf::Out<gpio::Direction> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, SetInterruptMode, (gpio::InterruptMode mode), (mode)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, GetInterruptMode, (ams::sf::Out<gpio::InterruptMode> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, SetInterruptEnable, (bool enable), (enable)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, GetInterruptEnable, (ams::sf::Out<bool> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out<gpio::InterruptStatus> out), (out), hos::Version_1_0_0, hos::Version_16_1_0) \
AMS_SF_METHOD_INFO(C, H, 7, Result, ClearInterruptStatus, (), (), hos::Version_1_0_0, hos::Version_16_1_0) \
AMS_SF_METHOD_INFO(C, H, 8, Result, SetValue, (gpio::GpioValue value), (value)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, GetValue, (ams::sf::Out<gpio::GpioValue> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 10, Result, BindInterrupt, (ams::sf::OutCopyHandle out), (out)) \
AMS_SF_METHOD_INFO(C, H, 11, Result, UnbindInterrupt, (), ()) \
AMS_SF_METHOD_INFO(C, H, 12, Result, SetDebounceEnabled, (bool enable), (enable)) \
AMS_SF_METHOD_INFO(C, H, 13, Result, GetDebounceEnabled, (ams::sf::Out<bool> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 14, Result, SetDebounceTime, (s32 ms), (ms)) \
AMS_SF_METHOD_INFO(C, H, 15, Result, GetDebounceTime, (ams::sf::Out<s32> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 16, Result, SetValueForSleepState, (gpio::GpioValue value), (value), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 17, Result, GetMaxDebounceTime, (ams::sf::Out<gpio::GpioValue> out), (out), hos::Version_6_0_0) \
AMS_SF_METHOD_INFO(C, H, 18, Result, SetDirectionInput, (), (), hos::Version_12_0_0) \
AMS_SF_METHOD_INFO(C, H, 19, Result, SetDirectionOutput, (gpio::GpioValue value), (value), hos::Version_12_0_0) \
AMS_SF_METHOD_INFO(C, H, 20, Result, SetUnknownEnabled, (bool enable), (enable), hos::Version_23_0_0) \
AMS_SF_METHOD_INFO(C, H, 21, Result, GetUnknownEnabled, (ams::sf::Out<bool> out), (out), hos::Version_23_0_0)
AMS_SF_DEFINE_INTERFACE(ams::gpio::sf, IPadSession, AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO, 0x7448A8A7)

View File

@@ -101,6 +101,9 @@ namespace ams::hos {
Version_21_1_0 = ::ams::TargetFirmware_21_1_0,
Version_21_2_0 = ::ams::TargetFirmware_21_2_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_23_0_0 = ::ams::TargetFirmware_23_0_0,
Version_Current = ::ams::TargetFirmware_Current,

View File

@@ -20,11 +20,11 @@
#include <stratosphere/i2c/i2c_select_device_name.hpp>
#include <stratosphere/i2c/sf/i2c_sf_i_session.hpp>
#define AMS_I2C_I_MANAGER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode), (out, bus_idx, slave_address, addressing_mode, speed_mode) ) \
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, i2c::I2cDevice device), (out, device) ) \
AMS_SF_METHOD_INFO(C, H, 2, Result, HasDevice, (ams::sf::Out<bool> out, i2c::I2cDevice device), (out, device), hos::Version_Min, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 3, Result, HasDeviceForDev, (ams::sf::Out<bool> out, i2c::I2cDevice device), (out, device), hos::Version_Min, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 4, Result, OpenSession2, (ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, DeviceCode device_code), (out, device_code), hos::Version_6_0_0 )
#define AMS_I2C_I_MANAGER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode), (out, bus_idx, slave_address, addressing_mode, speed_mode)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, i2c::I2cDevice device), (out, device)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, HasDevice, (ams::sf::Out<bool> out, i2c::I2cDevice device), (out, device), hos::Version_1_0_0, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 3, Result, HasDeviceForDev, (ams::sf::Out<bool> out, i2c::I2cDevice device), (out, device), hos::Version_1_0_0, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 4, Result, OpenSession2, (ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, DeviceCode device_code), (out, device_code), hos::Version_6_0_0)
AMS_SF_DEFINE_INTERFACE(ams::i2c::sf, IManager, AMS_I2C_I_MANAGER_INTERFACE_INFO, 0xE4C9D8F0)

View File

@@ -18,13 +18,13 @@
#include <vapours.hpp>
#include <stratosphere/i2c/i2c_types.hpp>
#define AMS_I2C_I_SESSION_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, SendOld, (const ams::sf::InBuffer &in_data, i2c::TransactionOption option), (in_data, option), hos::Version_Min, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 1, Result, ReceiveOld, (const ams::sf::OutBuffer &out_data, i2c::TransactionOption option), (out_data, option), hos::Version_Min, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 2, Result, ExecuteCommandListOld, (const ams::sf::OutBuffer &rcv_buf, const ams::sf::InPointerArray<i2c::I2cCommand> &command_list), (rcv_buf, command_list), hos::Version_Min, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, Send, (const ams::sf::InAutoSelectBuffer &in_data, i2c::TransactionOption option), (in_data, option) ) \
AMS_SF_METHOD_INFO(C, H, 11, Result, Receive, (const ams::sf::OutAutoSelectBuffer &out_data, i2c::TransactionOption option), (out_data, option) ) \
AMS_SF_METHOD_INFO(C, H, 12, Result, ExecuteCommandList, (const ams::sf::OutAutoSelectBuffer &rcv_buf, const ams::sf::InPointerArray<i2c::I2cCommand> &command_list), (rcv_buf, command_list) ) \
AMS_SF_METHOD_INFO(C, H, 13, Result, SetRetryPolicy, (s32 max_retry_count, s32 retry_interval_us), (max_retry_count, retry_interval_us), hos::Version_6_0_0 )
#define AMS_I2C_I_SESSION_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, SendOld, (const ams::sf::InBuffer &in_data, i2c::TransactionOption option), (in_data, option), hos::Version_1_0_0, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 1, Result, ReceiveOld, (const ams::sf::OutBuffer &out_data, i2c::TransactionOption option), (out_data, option), hos::Version_1_0_0, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 2, Result, ExecuteCommandListOld, (const ams::sf::OutBuffer &rcv_buf, const ams::sf::InPointerArray<i2c::I2cCommand> &command_list), (rcv_buf, command_list), hos::Version_1_0_0, hos::Version_5_1_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, Send, (const ams::sf::InAutoSelectBuffer &in_data, i2c::TransactionOption option), (in_data, option)) \
AMS_SF_METHOD_INFO(C, H, 11, Result, Receive, (const ams::sf::OutAutoSelectBuffer &out_data, i2c::TransactionOption option), (out_data, option)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, ExecuteCommandList, (const ams::sf::OutAutoSelectBuffer &rcv_buf, const ams::sf::InPointerArray<i2c::I2cCommand> &command_list), (rcv_buf, command_list)) \
AMS_SF_METHOD_INFO(C, H, 13, Result, SetRetryPolicy, (s32 max_retry_count, s32 retry_interval_us), (max_retry_count, retry_interval_us), hos::Version_6_0_0, hos::Version_22_5_0)
AMS_SF_DEFINE_INTERFACE(ams::i2c::sf, ISession, AMS_I2C_I_SESSION_INTERFACE_INFO, 0x40154EFE)

View File

@@ -489,7 +489,7 @@ namespace ams::kvdb {
private:
Result SaveArchiveToFile(const char *path, const void *buf, size_t size) {
/* Try to delete the archive, but allow deletion failure. */
fs::DeleteFile(path);
R_DISCARD(fs::DeleteFile(path));
/* Create new archive. */
R_TRY(fs::CreateFile(path, size));
@@ -514,7 +514,7 @@ namespace ams::kvdb {
R_TRY(SaveArchiveToFile(m_temp_path.Get(), buffer.Get(), buffer.GetSize()));
/* Try to delete the saved archive, but allow deletion failure. */
fs::DeleteFile(m_path.Get());
R_DISCARD(fs::DeleteFile(m_path.Get()));
/* Rename the path. */
R_TRY(fs::RenameFile(m_temp_path.Get(), m_path.Get()));

View File

@@ -50,9 +50,9 @@ namespace ams::ldr {
ProgramInfoFlag_AllowDebug = (1 << 2),
};
enum CreateProcessFlag {
CreateProcessFlag_EnableDebug = (1 << 0),
CreateProcessFlag_DisableAslr = (1 << 1),
enum CreateProcessParameterFlag {
CreateProcessParameterFlag_EnableJitDebug = (1 << 0),
CreateProcessParameterFlag_DisableAslr = (1 << 1),
};
struct ProgramArguments {
@@ -194,10 +194,10 @@ namespace ams::ldr {
};
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(PoolPartition_Application == (svc::CreateProcessFlag_PoolPartitionApplication >> svc::CreateProcessFlag_PoolPartitionShift));
static_assert(PoolPartition_Applet == (svc::CreateProcessFlag_PoolPartitionApplet >> svc::CreateProcessFlag_PoolPartitionShift));
static_assert(PoolPartition_System == (svc::CreateProcessFlag_PoolPartitionSystem >> svc::CreateProcessFlag_PoolPartitionShift));
static_assert(PoolPartition_SystemNonSecure == (svc::CreateProcessFlag_PoolPartitionSystemNonSecure >> svc::CreateProcessFlag_PoolPartitionShift));
static_assert(PoolPartition_Application == (svc::CreateProcessParameterFlag_PoolPartitionApplication >> svc::CreateProcessParameterFlag_PoolPartitionShift));
static_assert(PoolPartition_Applet == (svc::CreateProcessParameterFlag_PoolPartitionApplet >> svc::CreateProcessParameterFlag_PoolPartitionShift));
static_assert(PoolPartition_System == (svc::CreateProcessParameterFlag_PoolPartitionSystem >> svc::CreateProcessParameterFlag_PoolPartitionShift));
static_assert(PoolPartition_SystemNonSecure == (svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure >> svc::CreateProcessParameterFlag_PoolPartitionShift));
#endif
u8 signature[0x100];
@@ -223,37 +223,43 @@ namespace ams::ldr {
struct Npdm {
static constexpr u32 Magic = util::FourCC<'M','E','T','A'>::Code;
enum MetaFlag {
MetaFlag_Is64Bit = (1 << 0),
enum MetaFlag0 {
MetaFlag0_Is64BitInstruction = (1 << 0),
MetaFlag_AddressSpaceTypeShift = 1,
MetaFlag_AddressSpaceTypeMask = (7 << MetaFlag_AddressSpaceTypeShift),
MetaFlag0_ProcessAddressSpaceShift = 1,
MetaFlag0_ProcessAddressSpaceMask = (7 << MetaFlag0_ProcessAddressSpaceShift),
MetaFlag_OptimizeMemoryAllocation = (1 << 4),
MetaFlag_DisableDeviceAddressSpaceMerge = (1 << 5),
MetaFlag_EnableAliasRegionExtraSize = (1 << 6),
MetaFlag_PreventCodeReads = (1 << 7),
MetaFlag0_OptimizeMemoryAllocation = (1 << 4),
MetaFlag0_DisableDeviceAddressSpaceMerge = (1 << 5),
MetaFlag0_EnableAddressSanitizer = (1 << 6),
MetaFlag0_PreventCodeReads = (1 << 7),
};
enum AddressSpaceType {
AddressSpaceType_32Bit = 0,
AddressSpaceType_64BitDeprecated = 1,
AddressSpaceType_32BitWithoutAlias = 2,
AddressSpaceType_64Bit = 3,
enum MetaFlag1 {
MetaFlag1_EnableShadowStack = (1 << 0),
};
enum ProcessAddressSpace {
ProcessAddressSpace_32Bit = 0,
ProcessAddressSpace_64Bit36 = 1,
ProcessAddressSpace_32BitNoReserved = 2,
ProcessAddressSpace_64Bit39 = 3,
ProcessAddressSpace_64Bit42 = 4,
};
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(AddressSpaceType_32Bit == (svc::CreateProcessFlag_AddressSpace32Bit >> svc::CreateProcessFlag_AddressSpaceShift));
static_assert(AddressSpaceType_64BitDeprecated == (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift));
static_assert(AddressSpaceType_32BitWithoutAlias == (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift));
static_assert(AddressSpaceType_64Bit == (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift));
static_assert(ProcessAddressSpace_32Bit == (svc::CreateProcessParameterFlag_AddressSpace32Bit >> svc::CreateProcessParameterFlag_AddressSpaceShift));
static_assert(ProcessAddressSpace_64Bit36 == (svc::CreateProcessParameterFlag_AddressSpace64Bit36 >> svc::CreateProcessParameterFlag_AddressSpaceShift));
static_assert(ProcessAddressSpace_32BitNoReserved == (svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved >> svc::CreateProcessParameterFlag_AddressSpaceShift));
static_assert(ProcessAddressSpace_64Bit39 == (svc::CreateProcessParameterFlag_AddressSpace64Bit39 >> svc::CreateProcessParameterFlag_AddressSpaceShift));
static_assert(ProcessAddressSpace_64Bit42 == (svc::CreateProcessParameterFlag_AddressSpace64Bit42 >> svc::CreateProcessParameterFlag_AddressSpaceShift));
#endif
u32 magic;
u32 signature_key_generation;
u8 reserved_08[4];
u8 flags;
u8 reserved_0D;
u8 flags0;
u8 flags1;
u8 main_thread_priority;
u8 default_cpu_id;
u8 reserved_10[4];

View File

@@ -398,6 +398,9 @@ namespace ams::ncm {
static const SystemAppletId Story;
static const SystemAppletId SystemWeb;
static const SystemAppletId OpenWeb;
static const SystemAppletId End;
};
@@ -433,6 +436,9 @@ namespace ams::ncm {
inline constexpr const SystemAppletId SystemAppletId::Story = { 0x0100000000001020ul };
inline constexpr const SystemAppletId SystemAppletId::SystemWeb = { 0x0100000000001042ul };
inline constexpr const SystemAppletId SystemAppletId::OpenWeb = { 0x0100000000001043ul };
inline constexpr const SystemAppletId SystemAppletId::End = { 0x0100000000001FFFul };
inline constexpr bool IsSystemAppletId(const ProgramId &program_id) {
@@ -500,6 +506,8 @@ namespace ams::ncm {
static const LibraryAppletId LoginShare;
static const LibraryAppletId WifiWebAuth;
static const LibraryAppletId MyPage;
static const LibraryAppletId SystemWeb;
static const LibraryAppletId OpenWeb;
};
@@ -515,6 +523,8 @@ namespace ams::ncm {
inline constexpr const LibraryAppletId LibraryAppletId::LoginShare = { SystemAppletId::LoginShare.value };
inline constexpr const LibraryAppletId LibraryAppletId::WifiWebAuth = { SystemAppletId::WifiWebAuth.value };
inline constexpr const LibraryAppletId LibraryAppletId::MyPage = { SystemAppletId::MyPage.value };
inline constexpr const LibraryAppletId LibraryAppletId::SystemWeb = { SystemAppletId::SystemWeb.value };
inline constexpr const LibraryAppletId LibraryAppletId::OpenWeb = { SystemAppletId::OpenWeb.value };
inline constexpr bool IsLibraryAppletId(const ProgramId &id) {
return id == LibraryAppletId::Auth ||
@@ -528,7 +538,9 @@ namespace ams::ncm {
id == LibraryAppletId::OfflineWeb ||
id == LibraryAppletId::LoginShare ||
id == LibraryAppletId::WifiWebAuth ||
id == LibraryAppletId::MyPage;
id == LibraryAppletId::MyPage ||
id == LibraryAppletId::SystemWeb ||
id == LibraryAppletId::OpenWeb;
}
inline constexpr bool IsLibraryAppletId(const LibraryAppletId &) {
@@ -558,6 +570,8 @@ namespace ams::ncm {
static const WebAppletId OfflineWeb;
static const WebAppletId LoginShare;
static const WebAppletId WifiWebAuth;
static const WebAppletId SystemWeb;
static const WebAppletId OpenWeb;
};
inline constexpr const WebAppletId WebAppletId::Web = { LibraryAppletId::Web.value };
@@ -565,13 +579,17 @@ namespace ams::ncm {
inline constexpr const WebAppletId WebAppletId::OfflineWeb = { LibraryAppletId::OfflineWeb.value };
inline constexpr const WebAppletId WebAppletId::LoginShare = { LibraryAppletId::LoginShare.value };
inline constexpr const WebAppletId WebAppletId::WifiWebAuth = { LibraryAppletId::WifiWebAuth.value };
inline constexpr const WebAppletId WebAppletId::SystemWeb = { LibraryAppletId::SystemWeb.value };
inline constexpr const WebAppletId WebAppletId::OpenWeb = { LibraryAppletId::OpenWeb.value };
inline constexpr bool IsWebAppletId(const ProgramId &id) {
return id == WebAppletId::Web ||
id == WebAppletId::Shop ||
id == WebAppletId::OfflineWeb ||
id == WebAppletId::LoginShare ||
id == WebAppletId::WifiWebAuth;
id == WebAppletId::WifiWebAuth ||
id == WebAppletId::SystemWeb ||
id == WebAppletId::OpenWeb;
}
inline constexpr bool IsWebAppletId(const WebAppletId &) {

View File

@@ -33,8 +33,8 @@ namespace ams::pgl {
virtual ~EventObserverInterface() { /* ... */ }
virtual Result GetSystemEvent(os::SystemEventType *out) = 0;
virtual Result GetProcessEventInfo(pm::ProcessEventInfo *out) = 0;
virtual Result GetShellEvent(os::SystemEventType *out) = 0;
virtual Result GetShellEventInfo(pm::ProcessEventInfo *out) = 0;
};
class EventObserverByCmif final : public EventObserverInterface {
@@ -45,9 +45,9 @@ namespace ams::pgl {
public:
explicit EventObserverByCmif(ams::sf::SharedPointer<pgl::sf::IEventObserver> intf) : m_cmif_interface(intf) { /* ... */ }
public:
virtual Result GetSystemEvent(os::SystemEventType *out) override {
virtual Result GetShellEvent(os::SystemEventType *out) override {
ams::sf::NativeHandle handle;
R_TRY(m_cmif_interface->GetProcessEventHandle(std::addressof(handle)));
R_TRY(m_cmif_interface->GetShellEvent(std::addressof(handle)));
os::AttachReadableHandleToSystemEvent(out, handle.GetOsHandle(), handle.IsManaged(), os::EventClearMode_AutoClear);
handle.Detach();
@@ -55,8 +55,8 @@ namespace ams::pgl {
R_SUCCEED();
}
virtual Result GetProcessEventInfo(pm::ProcessEventInfo *out) override {
R_RETURN(m_cmif_interface->GetProcessEventInfo(out));
virtual Result GetShellEventInfo(pm::ProcessEventInfo *out) override {
R_RETURN(m_cmif_interface->GetShellEventInfo(out));
}
};
@@ -70,15 +70,15 @@ namespace ams::pgl {
template<typename... Args>
explicit EventObserverByTipc(Args &&... args) : m_tipc_interface(std::forward<Args>(args)...) { /* ... */ }
public:
virtual Result GetSystemEvent(os::SystemEventType *out) override {
virtual Result GetShellEvent(os::SystemEventType *out) override {
os::NativeHandle handle;
R_TRY(m_tipc_interface.GetProcessEventHandle(std::addressof(handle)));
R_TRY(m_tipc_interface.GetShellEvent(std::addressof(handle)));
os::AttachReadableHandleToSystemEvent(out, handle, true, os::EventClearMode_AutoClear);
R_SUCCEED();
}
virtual Result GetProcessEventInfo(pm::ProcessEventInfo *out) override {
R_RETURN(m_tipc_interface.GetProcessEventInfo(ams::tipc::Out<pm::ProcessEventInfo>(out)));
virtual Result GetShellEventInfo(pm::ProcessEventInfo *out) override {
R_RETURN(m_tipc_interface.GetShellEventInfo(ams::tipc::Out<pm::ProcessEventInfo>(out)));
}
};
@@ -112,12 +112,12 @@ namespace ams::pgl {
std::swap(m_impl, rhs.m_impl);
}
public:
Result GetSystemEvent(os::SystemEventType *out) {
R_RETURN(m_impl->GetSystemEvent(out));
Result GetShellEvent(os::SystemEventType *out) {
R_RETURN(m_impl->GetShellEvent(out));
}
Result GetProcessEventInfo(pm::ProcessEventInfo *out) {
R_RETURN(m_impl->GetProcessEventInfo(out));
Result GetShellEventInfo(pm::ProcessEventInfo *out) {
R_RETURN(m_impl->GetShellEventInfo(out));
}
};

View File

@@ -27,15 +27,15 @@ namespace ams::pgl {
Result LaunchProgram(os::ProcessId *out, const ncm::ProgramLocation &loc, u32 process_flags, u8 pgl_flags);
Result TerminateProcess(os::ProcessId process_id);
Result LaunchProgramFromHost(os::ProcessId *out, const char *content_path, u32 process_flags);
Result GetHostContentMetaInfo(pgl::ContentMetaInfo *out, const char *content_path);
Result GetApplicationProcessId(os::ProcessId *out);
Result GetProgramLaunchPropertyFromHost(pgl::ProgramLaunchProperty *out, const char *content_path);
Result GetRunningApplicationProcessId(os::ProcessId *out);
Result BoostSystemMemoryResourceLimit(u64 size);
Result IsProcessTracked(bool *out, os::ProcessId process_id);
Result IsRunningProcess(bool *out, os::ProcessId process_id);
Result EnableApplicationCrashReport(bool enabled);
Result IsApplicationCrashReportEnabled(bool *out);
Result EnableApplicationAllThreadDumpOnCrash(bool enabled);
Result TriggerApplicationSnapShotDumper(const char *arg, SnapShotDumpType dump_type);
Result GetEventObserver(pgl::EventObserver *out);
Result TriggerSnapShotDumper(const char *arg, SnapShotDumpType dump_type);
Result CreateShellEvent(pgl::EventObserver *out);
Result EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled);
}

View File

@@ -35,15 +35,15 @@ namespace ams::pgl {
Full = 2,
};
/* TODO: Is this really nn::ncm::Content<Something>Info? */
struct ContentMetaInfo {
struct ProgramLaunchProperty {
u64 id;
u32 version;
ncm::ContentType content_type;
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 ProgramLaunchProperty Make(u64 id, u32 version, ncm::ContentType content_type, u8 id_offset) {
return {
.id = id,
.version = version,
@@ -52,6 +52,6 @@ namespace ams::pgl {
};
}
};
static_assert(sizeof(ContentMetaInfo) == 0x10 && util::is_pod<ContentMetaInfo>::value);
static_assert(sizeof(ProgramLaunchProperty) == 0x10 && util::is_pod<ProgramLaunchProperty>::value);
}

View File

@@ -21,8 +21,8 @@
#include <stratosphere/pgl/pgl_types.hpp>
#define AMS_PGL_SF_I_EVENT_OBSERVER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GetProcessEventHandle, (ams::sf::OutCopyHandle out), (out)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetProcessEventInfo, (ams::sf::Out<pm::ProcessEventInfo> out), (out))
AMS_SF_METHOD_INFO(C, H, 0, Result, GetShellEvent, (ams::sf::OutCopyHandle out), (out)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetShellEventInfo, (ams::sf::Out<pm::ProcessEventInfo> out), (out))
AMS_SF_DEFINE_INTERFACE(ams::pgl::sf, IEventObserver, AMS_PGL_SF_I_EVENT_OBSERVER_INTERFACE_INFO, 0x00000000);

View File

@@ -25,16 +25,15 @@
AMS_SF_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::sf::Out<os::ProcessId> out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags), (out, loc, pm_flags, pgl_flags)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, LaunchProgramFromHost, (ams::sf::Out<os::ProcessId> out, const ams::sf::InBuffer &content_path, u32 pm_flags), (out, content_path, pm_flags)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, GetHostContentMetaInfo, (ams::sf::Out<pgl::ContentMetaInfo> out, const ams::sf::InBuffer &content_path), (out, content_path)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, GetApplicationProcessId, (ams::sf::Out<os::ProcessId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, GetProgramLaunchPropertyFromHost, (ams::sf::Out<pgl::ProgramLaunchProperty> out, const ams::sf::InBuffer &content_path), (out, content_path)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, GetRunningApplicationProcessId, (ams::sf::Out<os::ProcessId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, BoostSystemMemoryResourceLimit, (u64 size), (size)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, IsProcessTracked, (ams::sf::Out<bool> out, os::ProcessId process_id), (out, process_id)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, IsRunningProcess, (ams::sf::Out<bool> out, os::ProcessId process_id), (out, process_id)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, EnableApplicationCrashReport, (bool enabled), (enabled)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, IsApplicationCrashReportEnabled, (ams::sf::Out<bool> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \
AMS_SF_METHOD_INFO(C, H, 11, Result, GetProcessId, (ams::sf::Out<os::ProcessId> out, ncm::ProgramId program_id), (out, program_id)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, TriggerApplicationSnapShotDumper, (pgl::SnapShotDumpType dump_type, const ams::sf::InBuffer &arg), (dump_type, arg)) \
AMS_SF_METHOD_INFO(C, H, 20, Result, GetShellEventObserver, (ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, TriggerSnapShotDumper, (pgl::SnapShotDumpType dump_type, const ams::sf::InBuffer &arg), (dump_type, arg), hos::Version_10_0_0) \
AMS_SF_METHOD_INFO(C, H, 20, Result, CreateShellEvent, (ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 21, Result, Command21NotImplemented, (ams::sf::Out<u64> out, u32 in, const ams::sf::InBuffer &buf1, const ams::sf::InBuffer &buf2), (out, in, buf1, buf2), hos::Version_11_0_0)
AMS_SF_DEFINE_INTERFACE(ams::pgl::sf, IShellInterface, AMS_PGL_I_SHELL_INTERFACE_INTERFACE_INFO, 0x00000000);

View File

@@ -30,15 +30,16 @@ namespace ams::pgl::srv {
Result LaunchProgramImpl(os::ProcessId *out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags);
Result TerminateProcessImpl(os::ProcessId process_id);
Result LaunchProgramFromHostImpl(os::ProcessId *out, const void *content_path, size_t content_path_size, u32 pm_flags);
Result GetHostContentMetaInfoImpl(pgl::ContentMetaInfo *out, const void *content_path, size_t content_path_size);
Result GetApplicationProcessIdImpl(os::ProcessId *out);
Result GetProgramLaunchPropertyFromHostImpl(pgl::ProgramLaunchProperty *out, const void *content_path, size_t content_path_size);
Result GetRunningApplicationProcessIdImpl(os::ProcessId *out);
Result BoostSystemMemoryResourceLimitImpl(u64 size);
Result IsProcessTrackedImpl(bool *out, os::ProcessId process_id);
Result IsRunningProcessImpl(bool *out, os::ProcessId process_id);
Result EnableApplicationCrashReportImpl(bool enabled);
Result IsApplicationCrashReportEnabledImpl(bool *out);
Result EnableApplicationAllThreadDumpOnCrashImpl(bool enabled);
Result GetProcessId(os::ProcessId *out, ncm::ProgramId program_id);
Result TriggerApplicationSnapShotDumperImpl(SnapShotDumpType dump_type, const void *arg, size_t arg_size);
Result GetProcessIdImpl(os::ProcessId *out, ncm::ProgramId program_id);
Result TriggerSnapShotDumperImpl(SnapShotDumpType dump_type, const void *arg, size_t arg_size);
Result EnableApplicationCrashReport2Impl(os::ProcessId process_id, bool enabled);
};
class ShellInterfaceCmif : public ShellInterfaceCommon {
@@ -56,17 +57,15 @@ namespace ams::pgl::srv {
Result LaunchProgram(ams::sf::Out<os::ProcessId> out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags);
Result TerminateProcess(os::ProcessId process_id);
Result LaunchProgramFromHost(ams::sf::Out<os::ProcessId> out, const ams::sf::InBuffer &content_path, u32 pm_flags);
Result GetHostContentMetaInfo(ams::sf::Out<pgl::ContentMetaInfo> out, const ams::sf::InBuffer &content_path);
Result GetApplicationProcessId(ams::sf::Out<os::ProcessId> out);
Result GetProgramLaunchPropertyFromHost(ams::sf::Out<pgl::ProgramLaunchProperty> out, const ams::sf::InBuffer &content_path);
Result GetRunningApplicationProcessId(ams::sf::Out<os::ProcessId> out);
Result BoostSystemMemoryResourceLimit(u64 size);
Result IsProcessTracked(ams::sf::Out<bool> out, os::ProcessId process_id);
Result IsRunningProcess(ams::sf::Out<bool> out, os::ProcessId process_id);
Result EnableApplicationCrashReport(bool enabled);
Result IsApplicationCrashReportEnabled(ams::sf::Out<bool> out);
Result EnableApplicationAllThreadDumpOnCrash(bool enabled);
Result GetProcessId(ams::sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
Result TriggerApplicationSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg);
Result GetShellEventObserver(ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out);
Result TriggerSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg);
Result CreateShellEvent(ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out);
Result Command21NotImplemented(ams::sf::Out<u64> out, u32 in, const ams::sf::InBuffer &buf1, const ams::sf::InBuffer &buf2);
};
static_assert(pgl::sf::IsIShellInterface<ShellInterfaceCmif>);
@@ -81,15 +80,16 @@ namespace ams::pgl::srv {
Result LaunchProgram(ams::tipc::Out<os::ProcessId> out, const ncm::ProgramLocation loc, u32 pm_flags, u8 pgl_flags);
Result TerminateProcess(os::ProcessId process_id);
Result LaunchProgramFromHost(ams::tipc::Out<os::ProcessId> out, const ams::tipc::InBuffer content_path, u32 pm_flags);
Result GetHostContentMetaInfo(ams::tipc::Out<pgl::ContentMetaInfo> out, const ams::tipc::InBuffer content_path);
Result GetApplicationProcessId(ams::tipc::Out<os::ProcessId> out);
Result GetProgramLaunchPropertyFromHost(ams::tipc::Out<pgl::ProgramLaunchProperty> out, const ams::tipc::InBuffer content_path);
Result GetRunningApplicationProcessId(ams::tipc::Out<os::ProcessId> out);
Result BoostSystemMemoryResourceLimit(u64 size);
Result IsProcessTracked(ams::tipc::Out<bool> out, os::ProcessId process_id);
Result IsRunningProcess(ams::tipc::Out<bool> out, os::ProcessId process_id);
Result EnableApplicationCrashReport(bool enabled);
Result IsApplicationCrashReportEnabled(ams::tipc::Out<bool> out);
Result EnableApplicationAllThreadDumpOnCrash(bool enabled);
Result GetProcessId(ams::tipc::Out<os::ProcessId> out, ncm::ProgramId program_id);
Result GetShellEventObserver(ams::tipc::OutMoveHandle out);
Result CreateShellEvent(ams::tipc::OutMoveHandle out);
Result EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled);
};
static_assert(pgl::tipc::IsIShellInterface<ShellInterfaceTipc>);

View File

@@ -22,8 +22,8 @@
#include <stratosphere/pgl/pgl_types.hpp>
#define AMS_PGL_TIPC_I_EVENT_OBSERVER_INTERFACE_INFO(C, H) \
AMS_TIPC_METHOD_INFO(C, H, 0, Result, GetProcessEventHandle, (ams::tipc::OutCopyHandle out), (out)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, GetProcessEventInfo, (ams::tipc::Out<pm::ProcessEventInfo> out), (out))
AMS_TIPC_METHOD_INFO(C, H, 0, Result, GetShellEvent, (ams::tipc::OutCopyHandle out), (out)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, GetShellEventInfo, (ams::tipc::Out<pm::ProcessEventInfo> out), (out))
AMS_TIPC_DEFINE_INTERFACE(ams::pgl::tipc, IEventObserver, AMS_PGL_TIPC_I_EVENT_OBSERVER_INTERFACE_INFO);

View File

@@ -22,17 +22,19 @@
#include <stratosphere/pgl/pgl_types.hpp>
#include <stratosphere/pgl/tipc/pgl_tipc_i_event_observer.hpp>
#define AMS_PGL_TIPC_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \
AMS_TIPC_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::tipc::Out<os::ProcessId> out, const ncm::ProgramLocation loc, u32 pm_flags, u8 pgl_flags), (out, loc, pm_flags, pgl_flags)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 2, Result, LaunchProgramFromHost, (ams::tipc::Out<os::ProcessId> out, const ams::tipc::InBuffer content_path, u32 pm_flags), (out, content_path, pm_flags)) \
AMS_TIPC_METHOD_INFO(C, H, 4, Result, GetHostContentMetaInfo, (ams::tipc::Out<pgl::ContentMetaInfo> out, const ams::tipc::InBuffer content_path), (out, content_path)) \
AMS_TIPC_METHOD_INFO(C, H, 5, Result, GetApplicationProcessId, (ams::tipc::Out<os::ProcessId> out), (out)) \
AMS_TIPC_METHOD_INFO(C, H, 6, Result, BoostSystemMemoryResourceLimit, (u64 size), (size)) \
AMS_TIPC_METHOD_INFO(C, H, 7, Result, IsProcessTracked, (ams::tipc::Out<bool> out, os::ProcessId process_id), (out, process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 8, Result, EnableApplicationCrashReport, (bool enabled), (enabled)) \
AMS_TIPC_METHOD_INFO(C, H, 9, Result, IsApplicationCrashReportEnabled, (ams::tipc::Out<bool> out), (out)) \
AMS_TIPC_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \
AMS_TIPC_METHOD_INFO(C, H, 20, Result, GetShellEventObserver, (ams::tipc::OutMoveHandle out), (out))
#define AMS_PGL_TIPC_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \
AMS_TIPC_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::tipc::Out<os::ProcessId> out, const ncm::ProgramLocation loc, u32 pm_flags, u8 pgl_flags), (out, loc, pm_flags, pgl_flags)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 2, Result, LaunchProgramFromHost, (ams::tipc::Out<os::ProcessId> out, const ams::tipc::InBuffer content_path, u32 pm_flags), (out, content_path, pm_flags)) \
AMS_TIPC_METHOD_INFO(C, H, 4, Result, GetProgramLaunchPropertyFromHost, (ams::tipc::Out<pgl::ProgramLaunchProperty> out, const ams::tipc::InBuffer content_path), (out, content_path)) \
AMS_TIPC_METHOD_INFO(C, H, 5, Result, GetRunningApplicationProcessId, (ams::tipc::Out<os::ProcessId> out), (out)) \
AMS_TIPC_METHOD_INFO(C, H, 6, Result, BoostSystemMemoryResourceLimit, (u64 size), (size)) \
AMS_TIPC_METHOD_INFO(C, H, 7, Result, IsRunningProcess, (ams::tipc::Out<bool> out, os::ProcessId process_id), (out, process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 8, Result, EnableApplicationCrashReport, (bool enabled), (enabled)) \
AMS_TIPC_METHOD_INFO(C, H, 9, Result, IsApplicationCrashReportEnabled, (ams::tipc::Out<bool> out), (out)) \
AMS_TIPC_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \
AMS_TIPC_METHOD_INFO(C, H, 11, Result, GetProcessId, (ams::tipc::Out<os::ProcessId> out, ncm::ProgramId program_id), (out, program_id), hos::Version_19_0_0) \
AMS_TIPC_METHOD_INFO(C, H, 20, Result, CreateShellEvent, (ams::tipc::OutMoveHandle out), (out)) \
AMS_TIPC_METHOD_INFO(C, H, 31, Result, EnableApplicationCrashReport2, (os::ProcessId process_id, bool enabled), (process_id, enabled), hos::Version_23_0_0)
AMS_TIPC_DEFINE_INTERFACE(ams::pgl::tipc, IShellInterface, AMS_PGL_TIPC_I_SHELL_INTERFACE_INTERFACE_INFO);

View File

@@ -19,12 +19,12 @@
#include <stratosphere/ro/ro_types.hpp>
#include <stratosphere/sf.hpp>
#define AMS_RO_I_RO_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, MapManualLoadModuleMemory, (sf::Out<u64> out_load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size), (out_load_address, client_pid, nro_address, nro_size, bss_address, bss_size)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, UnmapManualLoadModuleMemory, (const sf::ClientProcessId &client_pid, u64 nro_address), (client_pid, nro_address)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size), (client_pid, nrr_address, nrr_size)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address), (client_pid, nrr_address)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle &&process_h), (client_pid, std::move(process_h))) \
AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterProcessModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h), (client_pid, nrr_address, nrr_size, std::move(process_h)), hos::Version_7_0_0)
#define AMS_RO_I_RO_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, MapManualLoadModuleMemory, (sf::Out<u64> out_load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size), (out_load_address, client_pid, nro_address, nro_size, bss_address, bss_size)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, UnmapManualLoadModuleMemory, (const sf::ClientProcessId &client_pid, u64 nro_address), (client_pid, nro_address)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size), (client_pid, nrr_address, nrr_size)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address), (client_pid, nrr_address)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle &&process_h), (client_pid, std::move(process_h))) \
AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterModuleInfoWithUserProcessHandle, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h), (client_pid, nrr_address, nrr_size, std::move(process_h)), hos::Version_7_0_0)
AMS_SF_DEFINE_INTERFACE(ams::ro::impl, IRoInterface, AMS_RO_I_RO_INTERFACE_INTERFACE_INFO, 0xA52C55A9)

View File

@@ -17,6 +17,7 @@
#pragma once
#include <vapours.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/rocrt/rocrt.hpp>
namespace ams::ro {
@@ -40,30 +41,30 @@ namespace ams::ro {
u64 program_id_mask;
u64 program_id_pattern;
u8 reserved_10[0x10];
u8 modulus[RsaKeySize];
u8 signature[RsaKeySize];
u8 public_key[RsaKeySize];
u8 sign[RsaKeySize];
};
static_assert(sizeof(NrrCertification) == NrrCertification::RsaKeySize + NrrCertification::SignedSize);
class NrrHeader {
public:
static constexpr u32 Magic = util::FourCC<'N','R','R','0'>::Code;
static constexpr u32 Signature = util::FourCC<'N','R','R','0'>::Code;
private:
u32 m_magic;
u32 m_signature;
u32 m_key_generation;
u8 m_reserved_08[0x08];
NrrCertification m_certification;
u8 m_signature[0x100];
u8 m_sign[0x100];
ncm::ProgramId m_program_id;
u32 m_size;
u8 m_nrr_kind; /* 7.0.0+ */
u8 m_reserved_33D[3];
u32 m_hashes_offset;
u32 m_num_hashes;
u32 m_hash_list_offset_address;
u32 m_num_hash;
u8 m_reserved_348[8];
public:
bool IsMagicValid() const {
return m_magic == Magic;
return m_signature == Signature;
}
bool IsProgramIdValid() const {
@@ -85,11 +86,11 @@ namespace ams::ro {
}
u32 GetNumHashes() const {
return m_num_hashes;
return m_num_hash;
}
size_t GetHashesOffset() const {
return m_hashes_offset;
return m_hash_list_offset_address;
}
uintptr_t GetHashes() const {
@@ -101,7 +102,7 @@ namespace ams::ro {
}
const u8 *GetCertificationSignature() const {
return m_certification.signature;
return m_certification.sign;
}
const u8 *GetCertificationSignedArea() const {
@@ -109,11 +110,11 @@ namespace ams::ro {
}
const u8 *GetCertificationModulus() const {
return m_certification.modulus;
return m_certification.public_key;
}
const u8 *GetSignature() const {
return m_signature;
return m_sign;
}
const u8 *GetSignedArea() const {
@@ -131,32 +132,45 @@ namespace ams::ro {
constexpr size_t NrrHeader::GetSignedAreaOffset() {
return AMS_OFFSETOF(NrrHeader, m_program_id);
}
static constexpr size_t RocrtHeaderSize = 0x10;
struct RocrtHeader {
rocrt::ModuleHeaderLocation module_header_location;
u32 reserved;
};
static_assert(sizeof(RocrtHeader) == RocrtHeaderSize);
class NroHeader {
public:
static constexpr u32 Magic = util::FourCC<'N','R','O','0'>::Code;
static constexpr u32 Signature = util::FourCC<'N','R','O','0'>::Code;
static constexpr u32 FlagAlignedHeader = 1;
static constexpr u32 FlagCompress = 2;
private:
u32 m_entrypoint_insn;
u32 m_mod_offset;
u8 m_reserved_08[0x8];
u32 m_magic;
u8 m_version;
RocrtHeader m_rocrt;
u32 m_signature;
u32 m_version;
u32 m_size;
u32 m_flags;
u32 m_text_offset;
u32 m_text_memory_offset;
u32 m_text_size;
u32 m_ro_offset;
u32 m_ro_memory_offset;
u32 m_ro_size;
u32 m_rw_offset;
u32 m_rw_size;
u32 m_data_memory_offset;
u32 m_data_size;
u32 m_bss_size;
u8 m_reserved_3C[0x4];
u32 m_additional_header_offset; /* 23.0.0+ */
ModuleId m_module_id;
u8 m_reserved_60[0x20];
u32 m_dso_handle_offset;
u32 m_reserved_64;
u32 m_embedded_offset;
u32 m_embedded_size;
u32 m_dyn_str_offset;
u32 m_dyn_str_size;
u32 m_dyn_sym_offset;
u32 m_dyn_sym_size;
public:
bool IsMagicValid() const {
return m_magic == Magic;
return m_signature == Signature;
}
u32 GetVersion() const {
@@ -174,9 +188,13 @@ namespace ams::ro {
bool IsAlignedHeader() const {
return m_flags & FlagAlignedHeader;
}
bool IsCompress() const {
return m_flags & FlagCompress;
}
u32 GetTextOffset() const {
return m_text_offset;
return m_text_memory_offset;
}
u32 GetTextSize() const {
@@ -184,7 +202,7 @@ namespace ams::ro {
}
u32 GetRoOffset() const {
return m_ro_offset;
return m_ro_memory_offset;
}
u32 GetRoSize() const {
@@ -192,21 +210,60 @@ namespace ams::ro {
}
u32 GetRwOffset() const {
return m_rw_offset;
return m_data_memory_offset;
}
u32 GetRwSize() const {
return m_rw_size;
return m_data_size;
}
u32 GetBssSize() const {
return m_bss_size;
}
u32 GetAdditionalHeaderOffset() const {
return m_additional_header_offset;
}
const ModuleId *GetModuleId() const {
return std::addressof(m_module_id);
}
};
static_assert(sizeof(NroHeader) == 0x80, "NroHeader definition!");
class AdditionalNroHeader {
public:
static constexpr u32 Signature = util::FourCC<'N','R','A','0'>::Code;
private:
u32 m_signature;
u8 m_reserved_04[0xC];
u32 m_compressed_size;
u32 m_reserved_14;
u32 m_hash_size;
u32 m_hash_offset;
u8 m_reserved_20[0x40];
u8 m_hash[0x20];
public:
bool IsMagicValid() const {
return m_signature == Signature;
}
u32 GetCompressedSize() const {
return m_compressed_size;
}
u32 GetHashSize() const {
return m_hash_size;
}
u32 GetHashOffset() const {
return m_hash_offset;
}
const u8 *GetHash() const {
return m_hash;
}
};
static_assert(sizeof(AdditionalNroHeader) == 0x80, "AdditionalNroHeader definition!");
}

View File

@@ -29,11 +29,18 @@ namespace ams::rocrt {
u32 exception_info_start_offset;
u32 exception_info_end_offset;
u32 module_offset;
u32 relro_start_offset; /* 19.0.0+ */
u32 full_relro_end_offset; /* 19.0.0+ */
u32 nx_debug_link_start_offset; /* 19.0.0+ */
u32 nx_debug_link_end_offset; /* 19.0.0+ */
u32 note_gnu_build_id_start_offset; /* 19.0.0+ */
u32 note_gnu_build_id_end_offset; /* 19.0.0+ */
};
struct ModuleHeaderLocation {
u32 pad;
u32 version;
u32 header_offset;
u32 version_offset;
};
constexpr inline u32 CheckModuleHeaderSignature(const ModuleHeader *header) {

Some files were not shown because too many files have changed in this diff Show More