Author SHA1 Message Date
niklascfw b29e92192e Merge upstream Atmosphere master into boot-storage 2026-10-16 20:19:15 +02:00
niklascfw a53e983269 Revert "Replaced 1st stage boot logo with NiklasCFW"
This reverts commit 144570aa48.
2026-10-16 20:17:23 +02:00
hexkyz 6b0c077b4c git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "cf48d2337"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "cf48d2337"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-10-16 00:17:09 +01:00
hexkyz ff43bc566a git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "11a2fd2a2"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "11a2fd2a2"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-10-16 00:16:30 +01:00
hexkyz 6eb8c3e7ce docs: add changelog for 1.12.1 2026-10-16 00:14:22 +01:00
hexkyz a8258fb31f ams: bump version and add enum version support for 23.0.1 2026-10-15 22:35:01 +01:00
hexkyz d9654e3bd0 emummc: update README for 23.0.1 2026-10-15 22:29:04 +01:00
hexkyz 43c6da000c dns.mitm: allow bsdsocket to cleanup 2026-10-15 22:06:50 +01:00
hexkyz 0165f5dcc1 web: better browser memory patching strategy 2026-10-15 20:25:15 +01:00
hexkyz 2fec688983 libstrat: account for sockaddr as well in windows target 2026-10-14 22:23:03 +01:00
hexkyz 90cd78a3a3 dns.mitm: trust bsdsocket to generate query ids
Further testing confirmed that bsdsocket ensures each query is unique and per-process.
Not only this allows us to simplify the mitm logic, but also fix a noticeable slowdown that was being caused by clients not being informed that bsdsocket's queue was full.
2026-10-14 22:08:48 +01:00
Chris Bräucker 4c233196dd Fall back to RSA device certificate for cal0 authenticity check (#2887)
* Fix device ID check in cal0 backup path

Only the ECC device certificate was used, which may be absent on some devices. Adds a fallback to use the RSA device certificate which is present on those.

* Move cert validity check into device ID check

* Fix ecc case condition

in cases where ECC is not blank and not valid, instead of aborting, it falls through to RSA
2026-10-14 19:48:41 +01:00
hexkyz 06870a20e7 libstrat: synchronize zstd.inc with https://github.com/hexkyz/zstd/tree/zbic
Implement a more robust platform check cherry-picked from zstd's dev branch
2026-10-12 20:37:25 +01:00
borntohonk fa19cc38b7 libstrat: fix building for non-windows targets (#2881) 2026-10-12 20:04:08 +01:00
hexkyz c7e6c35e90 libstrat: fix building for windows target 2026-10-11 22:59:40 +01:00
hexkyz eccd393126 fs.mitm: add entries for regional versions of Trails in the Sky 2nd Chapter (closes #2879) 2026-10-11 22:38:45 +01:00
hexkyz 4106801486 dns.mitm: forward queries for hostnames not in the hosts file 2026-10-11 22:21:31 +01:00
niklascfw 8592b1a303 Merge upstream Atmosphere master into boot-storage 2026-10-10 12:45:28 +02:00
hexkyz 0e9cd964c0 fs.mitm: mitm StorageForBatchRead as well as previously missing FileSystem/DataStorage commands 2026-10-09 20:09:52 +01:00
fl0be 36cc9a9f49 set state Initialized/Created for Shared/Transfer mem type (#2873) 2026-10-06 21:02:20 +01:00
hexkyz f5cd912604 dns.mitm: implement mitm for the new c-ares resolver and update serializer code 2026-10-06 02:25:38 +01:00
MasaGratoR c8b7316581 Add Trails in the Sky 2nd Chapter to ApplicationsWithDynamicHeap (#2870) 2026-10-02 19:22:56 +01:00
Niklas080208 144570aa48 Replaced 1st stage boot logo with NiklasCFW 2026-09-29 21:27:26 +02:00
Niklas080208 b72f8a76f2 Merge upstream Atmosphere master into boot-storage 2026-09-29 20:54:57 +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
niklascfw c5aa01f34c Merge upstream Atmosphere master into boot-storage
Bring in latest upstream changes including zstd/zbic loader refactor,
pinmux named options, and erpt ClearFsInfo fixes.
2026-07-17 12:26:29 +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 e622146012 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-17 00:59:16 +02:00
hexkyz f2a9d514bf erpt: add new ID for 22.5.0 2026-06-17 00:59:16 +02:00
hexkyz 420b7a9e80 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-17 00:59:16 +02:00
hexkyz bab4076204 emummc: update readme for 22.5.0 2026-06-17 00:59:16 +02:00
hexkyz 9cb05016fc 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-17 00:59:16 +02:00
hexkyz 09c57657ea 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-17 00:59:16 +02:00
hexkyz 7ea0498447 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-17 00:59:16 +02:00
hexkyz f2cb68972c docs: add gcc16 to changelog 2026-06-17 00:59:16 +02:00
hexkyz 3423a8291f ams: basic support for compiling with gcc 16 2026-06-17 00:59:16 +02:00
hexkyz a5f6e5e660 docs: add changelog for 1.11.2 2026-06-17 00:59:16 +02:00
hexkyz 93e10994cb meso: fix longstanding bad asm copy-paste 2026-06-17 00:59:16 +02:00
hexkyz b6edd46b41 emummc: update for 22.5.0 2026-06-17 00:59:16 +02:00
hexkyz 3861571def loader: update USB 3.0 patches for 22.5.0 2026-06-17 00:59:16 +02:00
hexkyz 5accc43671 ams: add enum recognition for 22.5.0 2026-06-17 00:59:16 +02:00
hexkyz 3446630692 Merge pull request #2811 from ZachyCatGames/patch-1
pgl: GetHostContentMetaInfo returns a ncm::ContentMetaType
2026-06-17 00:59:05 +02:00
hexkyz 60cc15953d Merge pull request #2800 from masagrator/patch-1
fs.mitm: Add "Until Then" as another game which needs stolen heap for layeredfs
2026-06-17 00:58:56 +02:00
hexkyz 5388824be1 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "d3083af18"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "d3083af18"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 22:11:17 +01:00
hexkyz 974a1025b8 erpt: add new ID for 22.5.0 2026-06-16 22:10:07 +01:00
hexkyz 9d21cfca4c git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "f6b3a28ec"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "f6b3a28ec"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:21:53 +01:00
hexkyz 1478f3443e emummc: update readme for 22.5.0 2026-06-16 21:21:24 +01:00
hexkyz f527e7fc48 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "24946ac76"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "24946ac76"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:17:37 +01:00
hexkyz 7dccf3bffa git subrepo pull (merge) emummc
subrepo:
  subdir:   "emummc"
  merged:   "6cecd09b2"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "bde9957f1"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:17:11 +01:00
hexkyz 4ea042510b git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "e4100b5f5"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "e4100b5f5"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-06-16 21:15:53 +01:00
hexkyz d97f520058 docs: add gcc16 to changelog 2026-06-16 21:12:42 +01:00
hexkyz 3a3a2ca99b ams: basic support for compiling with gcc 16 2026-06-16 21:10:23 +01:00
hexkyz fcd46b4419 docs: add changelog for 1.11.2 2026-06-16 19:32:59 +01:00
hexkyz c046eeacdd meso: fix longstanding bad asm copy-paste 2026-06-16 19:22:54 +01:00
hexkyz 4181169f80 emummc: update for 22.5.0 2026-06-16 19:18:26 +01:00
hexkyz 47cfe05bb0 loader: update USB 3.0 patches for 22.5.0 2026-06-16 18:51:10 +01:00
hexkyz c497ffda75 ams: add enum recognition for 22.5.0 2026-06-16 18:41:32 +01:00
hexkyz 15c434f185 Merge pull request #2811 from ZachyCatGames/patch-1
pgl: GetHostContentMetaInfo returns a ncm::ContentMetaType
2026-05-30 00:32:39 +01:00
Zachary Kirtz 7d38bf16cd pgl: GetHostContentMetaInfo returns a ncm::ContentMetaType 2026-05-29 01:16:11 -05:00
hexkyz 2c7e2bfaae Merge pull request #2800 from masagrator/patch-1
fs.mitm: Add "Until Then" as another game which needs stolen heap for layeredfs
2026-04-25 19:55:43 +01:00
MasaGratoR e655fd4b01 fs.mitm: Add "Until Then" as another game which needs stolen heap for layeredfs 2026-04-24 22:30:25 +02:00
naga cfb5e8107f compile fix 2026-04-19 04:16:07 +02:00
NaGa 6703eb990c . 2026-04-14 04:12:32 +02:00
hexkyz d1b0f5cd21 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-08 16:57:30 +02:00
hexkyz cc5ff34d59 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-08 16:57:30 +02:00
hexkyz 1d550bc2cd Merge pull request #2786 from alula/alula
ams: add enum recognition for 22.1.0
2026-04-08 16:57:24 +02:00
hexkyz 1deee702c4 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-08 16:57:16 +02:00
NaGa af3613b521 emuSD/Boot fix 2026-04-08 16:56:50 +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 234c80df04 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 21:39:24 +02:00
hexkyz bfc0ea89bb docs: add changelog for 1.11.0 2026-04-04 21:39:24 +02:00
hexkyz b3772c0968 pgl: no need to initialize lr services when already using our own 2026-04-04 21:39:24 +02:00
hexkyz 29a158bb08 Merge pull request #2768 from masagrator/patch-1
Update services in PGL to match 21.0.0
2026-04-04 21:39:04 +02:00
hexkyz 88aaae0848 emummc: fix offsets
22.0.0 now boots under emummc
2026-04-04 21:38:58 +02:00
Alula 18151d354b erpt: Fix rare aborts caused by ResultInvalidPowerState 2026-04-04 21:38:54 +02:00
hexkyz aa2df9b753 Merge pull request #2763 from masagrator/patch-1
Fix off by 1 bug + allocation error + missing initialize in PGL
2026-04-04 21:38:41 +02:00
hexkyz 923dbe02b3 Merge pull request #2734 from ndeadly/r_discard
libvapours: add R_DISCARD macro
2026-04-04 21:38:33 +02:00
hexkyz 652869f207 loader: remove unused file 2026-04-04 21:38:28 +02:00
hexkyz 28d5feaa9e loader: patch am to recover homebrew compatibility
This patch is to be removed if/once hbmenu/libnx re-designs the exiting logic
2026-04-04 21:38:18 +02:00
hexkyz 6ed1413b23 loader/util: fully implement zstd bic variant
Implement both compression and decompression utilities and simplify loader logic
2026-04-04 21:38:18 +02:00
Alula 9d11621f1a erpt: use official name for erpt::IManager cmd 7 2026-04-04 21:37:56 +02:00
Alula 9c4159cc2d erpt: revert GetReportSizeMax to not potentially break old firmwares 2026-04-04 21:37:56 +02:00
Alula 44d1ffc5b7 loader: update for 22.0.0 2026-04-04 21:37:40 +02:00
Alula 1c97db2525 loader: the two unknown titles are LGE/LGP for China 2026-04-04 21:37:40 +02:00
Alula f452642e71 loader/strat: Add amalgamated zstd 1.5.7 with ZBIC patches 2026-04-04 21:37:40 +02:00
hexkyz ed4c9d53ea Merge emummc changes from pull request #2743
Remaining changes are duplicated in pull request #2744
2026-04-04 21:37:29 +02:00
hexkyz e7e9158dbe loader: add USB 3.0 patches for 22.0.0
Additionally remove duplicated entry for 20.1.0, just use the 20.0.0 one.
2026-04-04 21:37:29 +02:00
CTCaer 0a31b2e7e0 exosphere: allow memory mode to be used on retail 2026-04-04 21:33:00 +02:00
CTCaer 979eb86a48 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-04-04 21:30:29 +02:00
Alula 63409d8a13 erpt: rename old ControllerStyleList field 2026-04-04 21:30:19 +02:00
Alulaandnvnprogram 82018c0004 erpt: Implement 22.0.0 commands and changes
Co-authored-by: nvnprogram <97150065+nvnprogram@users.noreply.github.com>
2026-04-04 21:30:19 +02:00
Alula 424a32bc7a erpt: make FieldType u8 to match Nintendo 2026-04-04 21:30:19 +02:00
Alula 0a46f80eec kern: don't allow mapping device pages as executable on abi 26.x+ 2026-04-04 21:30:19 +02:00
Alula 7872e2bb13 kern: make KProcess layout accurate to N's code 2026-04-04 21:30:19 +02:00
Alula b6b374a98b kern: N made this an u32 for some reason 2026-04-04 21:30:19 +02:00
Alula 7ff6ac0399 pinmux: add a build time option to configure JC rail uart 2026-04-04 21:30:18 +02:00
Alula 250cdc5d2e fs: DisableAutoSaveDataCreation was removed in 22 2026-04-04 21:30:18 +02:00
Alula 57c341c8e1 svc: bump supported kernel version 2026-04-04 21:30:18 +02:00
Alula 688091abc9 kern: write thread handle to tls +0x110 on creation 2026-04-04 21:30:18 +02:00
Alula db41e33507 fusee/exo/ams: update with new keydata/version enums 2026-04-04 21:30:18 +02:00
hexkyz b794d96c2c erpt: style fix 2026-04-04 21:30:18 +02:00
hexkyz 872d91deaf erpt: add new IDs for 22.0.0 2026-04-04 21:30:18 +02:00
hexkyz 0126b96f8a erpt: types are now a byte in 22.0.0 2026-04-04 21:30:18 +02:00
hexkyz 9c482e6b03 Merge pull request #2703 from HydrationMan/master
Update fusee_display.cpp - add missing newline
2026-04-04 21:30:05 +02:00
hexkyz aae3ccf581 Merge pull request #2726 from ndeadly/svc-shim-compat
libstrat: update GetDebugEvent svc shim for compatibility with libnx changes
2026-04-04 21:30:01 +02:00
Michael Scire bf21711e30 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "9a8703e71"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "9a8703e71"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2026-04-04 21:29:01 +02: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
hexkyz 93a82c0441 loader: patch am to recover homebrew compatibility
This patch is to be removed if/once hbmenu/libnx re-designs the exiting logic
2026-04-02 01:42:53 +01:00
hexkyz 082115187a loader/util: fully implement zstd bic variant
Implement both compression and decompression utilities and simplify loader logic
2026-04-02 01:30:45 +01:00
hexkyz db388385b0 Merge pull request #2761 from alula/22_support
22.0.0 support part 3
2026-04-02 01:17:19 +01: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
Alula 8a7c2872c3 erpt: use official name for erpt::IManager cmd 7 2026-04-01 05:57:28 +02:00
Alula 6acdc05c89 erpt: revert GetReportSizeMax to not potentially break old firmwares 2026-04-01 05:46:04 +02:00
hexkyz 32bb6b17ab Merge pull request #2753 from alula/22_support
Basic ("the console boots and functions as expected") 22.0.0 support - Part 2
2026-04-01 03:10:19 +01:00
Alula 27455329b3 loader: update for 22.0.0 2026-03-28 01:43:19 +01:00
Alula 7d334f09ee loader: the two unknown titles are LGE/LGP for China 2026-03-27 23:57:44 +01:00
Alula 8c0ff851f2 loader/strat: Add amalgamated zstd 1.5.7 with ZBIC patches 2026-03-27 23:51:04 +01:00
hexkyz b108318996 Merge pull request #2744 from alula/22_support
Basic ("the console boots and functions as expected") 22.0.0 support
2026-03-20 00:22:10 +00:00
hexkyz 5dfdc6e8b0 Merge emummc changes from pull request #2743
Remaining changes are duplicated in pull request #2744
2026-03-20 00:17:19 +00:00
hexkyz 14e63cb04c loader: add USB 3.0 patches for 22.0.0
Additionally remove duplicated entry for 20.1.0, just use the 20.0.0 one.
2026-03-20 00:02:42 +00: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
Alula 49e2330ed8 erpt: rename old ControllerStyleList field 2026-03-18 23:40:40 +01:00
Alulaandnvnprogram 1847db06f8 erpt: Implement 22.0.0 commands and changes
Co-authored-by: nvnprogram <97150065+nvnprogram@users.noreply.github.com>
2026-03-18 23:33:55 +01:00
Alula f028802fb8 erpt: make FieldType u8 to match Nintendo 2026-03-18 23:30:06 +01:00
Alula b29dbeae3d kern: don't allow mapping device pages as executable on abi 26.x+ 2026-03-18 23:25:24 +01:00
Alula 4e653f67e5 kern: make KProcess layout accurate to N's code 2026-03-18 23:25:24 +01:00
Alula a985bdb1d4 kern: N made this an u32 for some reason 2026-03-18 23:25:24 +01:00
Alula 5b0a4830d4 pinmux: add a build time option to configure JC rail uart 2026-03-18 23:25:24 +01:00
Alula 26990b3be9 fs: DisableAutoSaveDataCreation was removed in 22 2026-03-18 23:25:24 +01:00
Alula 76bceffbd5 svc: bump supported kernel version 2026-03-18 23:25:24 +01:00
Alula 0ee6277be9 kern: write thread handle to tls +0x110 on creation 2026-03-18 23:25:24 +01:00
Alula 9cc82c6f80 fusee/exo/ams: update with new keydata/version enums 2026-03-18 23:25:24 +01:00
hexkyz 6b831406d6 erpt: style fix 2026-03-18 21:35:18 +00:00
hexkyz 23ebd4d677 erpt: add new IDs for 22.0.0 2026-03-18 21:32:35 +00:00
hexkyz 00f987dd38 erpt: types are now a byte in 22.0.0 2026-03-18 21:18:05 +00:00
ndeadly f8a5a6c015 libvapours: add R_DISCARD macro 2026-02-23 01:09:11 +01:00
hexkyz 61ac03e22d Merge pull request #2703 from HydrationMan/master
Update fusee_display.cpp - add missing newline
2026-02-05 21:47:59 +00:00
hexkyz 208b60696c Merge pull request #2726 from ndeadly/svc-shim-compat
libstrat: update GetDebugEvent svc shim for compatibility with libnx changes
2026-02-05 21:37:17 +00:00
ndeadly dfb936ed11 libstrat: update GetDebugEvent svc shim for compatibility with libnx changes 2026-02-03 22:59:47 +01:00
Michael Scire 5056ab21af git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "9a8703e71"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "9a8703e71"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2026-01-15 15:39:39 -07:00
Michael Scire 74dcb6c9de git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "8ab963b0b"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "8ab963b0b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2026-01-15 03:46:55 +01:00
Michael Scire ad04b2215d ams/emummc: update for 21.2.0 2026-01-15 03:46:49 +01:00
Michael Scire eb34f9789c git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "8ab963b0b"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "8ab963b0b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2026-01-13 23:25:52 -07:00
Michael Scire 1e88f37892 ams/emummc: update for 21.2.0 2026-01-13 23:24:53 -07:00
Kane cd72f9f33e Update fusee_display.cpp - add missing newline
Add newline that would otherwise cause text concatenation when it comes to suggestedFix content being appended.
2026-01-01 23:16:38 +13:00
NaGa 4d5f6bcdbf fix compilation error 2025-12-16 06:09:37 +01:00
Michael Scire 246e29e594 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "6cc765fca"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "6cc765fca"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-12-09 06:42:13 +01:00
Michael Scire 39925c3802 ams: add enum recognition for 21.1.0 2025-12-09 06:42:13 +01:00
Michael Scire 21c0f75a29 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "6cc765fca"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "6cc765fca"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-12-08 18:41:44 -07:00
Michael Scire 3cb5d5f957 ams: add enum recognition for 21.1.0 2025-12-08 18:41:01 -07:00
Michael Scire c5c0c78a6c loader: fix valid-nso-set checks to be accurate (closes #2660) 2025-12-04 03:20:15 +01:00
Michael Scire 015c80f3f3 kern: eshop actually requires an extra mb 2025-12-04 03:20:15 +01:00
Michael Scire e99172f21a loader: add USB 3.0 patches for 21.0.0 2025-12-04 03:20:15 +01:00
Michael Scire e197cd0e7c kern: fix comparison typo 2025-12-04 03:20:15 +01:00
Michael Scire 816e627bdf ro: fix loading of aligned-header NROs 2025-12-04 03:20:15 +01:00
Michael Scire 24280084a8 kern: 21.0.0 requires an even smaller memory pool... 2025-12-04 03:20:15 +01:00
NaGa c81152f761 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "3c57b20ba"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "3c57b20ba"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-12-04 03:20:04 +01:00
NaGa 52dc41b0bb git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "6e2c09c79"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "6e2c09c79"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-12-04 03:15:28 +01:00
Michael Scire b90e861281 docs: add changelog for 1.10.0 2025-12-04 03:13:19 +01:00
Michael Scire d3563235c7 emummc: update for 21.0.0 2025-12-04 03:13:19 +01:00
Michael Scire f3754cb50b loader: fix sd-cmpt 2025-12-04 03:13:19 +01:00
Michael Scire 80edcb3f69 loader: update for 20.0.0/21.0.0 2025-12-04 03:13:19 +01:00
Michael Scire 0b2a14ae99 pgl/pm: add GetProcessId command 2025-12-04 03:13:08 +01:00
Michael Scire 9be23a366e kern: fix debug build for [[nodiscard]] changes 2025-12-04 03:13:08 +01:00
Michael Scire c72534def6 kern: fix whoops introduced by nodiscard refactor 2025-12-04 03:13:08 +01:00
Michael Scire a878a6bbb2 erpt: implement new 21.0.0 commands 2025-12-04 03:13:08 +01:00
Michael Scire 9cdc2c22f6 erpt: fix ids, failed to copy the new categories 2025-12-04 03:13:08 +01:00
Michael Scire f123104774 fatal: add new HashedTraceContext command 2025-12-04 03:13:08 +01:00
Michael Scire 5eef055d74 erpt: add new IDs for 21.0.0 2025-12-04 03:13:07 +01:00
Michael Scire cea188c31f kern: RESERVED_2F now set by HandleFpuException 2025-12-04 03:12:52 +01:00
Michael Scire d457f05204 kern: exception flags are now atomic.
This is a really weird one, because they didn't actually update the
code which updates these flags in asm, these still use ldrb/orr/strb.
But every access to these via c++ is now an atomic ldxrb/stxrb loop.
Maybe they just forgot to update the asm?
2025-12-04 03:12:52 +01:00
Michael Scire 84454fa095 kern: pass u32 directly to CopyMemoryToUserSize32Bit 2025-12-04 03:12:52 +01:00
Michael Scire 59f3fc70a5 ams: mark ams::Result [[nodiscard]] (partially complete).
NOTE: This work is not yet fully complete; kernel is done, but
it was taking an exceedingly long time to get through libstratosphere.
Thus, I've temporarily added -Wno-error=unused-result for libstratosphere/stratosphere.

All warnings should be fixed to do the same thing Nintendo does as relevant, but this
is taking a phenomenally long time and is not actually the most important work to do,
so it can be put off for some time to prioritize other tasks for 21.0.0 support.
2025-12-04 03:12:52 +01:00
Michael Scire b7fe85a34c kern: Nintendo now also devirtualizes KAutoObject::DynamicCast 2025-12-04 03:09:41 +01:00
Michael Scire 1978309b3e kern: write cpu tick differential to tls +0x108 on thread switch 2025-12-04 03:09:41 +01:00
Michael Scire 689e25ccb0 fusee/exo/ams: update with new keydata/version enums 2025-12-04 03:09:41 +01:00
Michael Scire af0a8bddf9 fs.mitm: add another game which needs stolen heap for layeredfs 2025-12-04 03:08:35 +01:00
Michael Scire 86fd8d66e1 fssystem: fix support for parsing newer-format BKTR NCAs
Apparently, at some point they started allowing maxlayers=3, which caused this code to not work.

Looking at latest FS, they always reference DataStorage instead of level+2 for the final level.

This fixes parsing update romfs for newer games, e.g. Super Mario Galaxy 2.
2025-12-04 03:07:59 +01:00
Michael Scire 00d1cdb533 loader: fix valid-nso-set checks to be accurate (closes #2660) 2025-11-22 15:57:35 -07:00
Michael Scire d9fc6e99eb kern: eshop actually requires an extra mb 2025-11-15 17:35:47 -07:00
Michael Scire c08a13a546 loader: add USB 3.0 patches for 21.0.0 2025-11-15 17:03:49 -07:00
Michael Scire b5b6189c85 kern: fix comparison typo 2025-11-15 16:51:15 -07:00
Michael Scire 28a378ca0d ro: fix loading of aligned-header NROs 2025-11-15 16:47:57 -07:00
Michael Scire 540d00e097 kern: 21.0.0 requires an even smaller memory pool... 2025-11-15 16:47:44 -07:00
Michael Scire bfe98bc5b8 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "6e2c09c79"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "6e2c09c79"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-11-15 12:58:41 -07:00
Michael Scire 4928bcb003 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "3c57b20ba"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "3c57b20ba"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-11-15 12:57:18 -07:00
Michael Scire d61ee942d9 docs: add changelog for 1.10.0 2025-11-15 12:55:47 -07:00
Michael Scire f59e6a936b emummc: update for 21.0.0 2025-11-15 12:31:07 -07:00
Michael Scire 129c61c256 loader: fix sd-cmpt 2025-11-15 12:31:07 -07:00
Michael Scire db71eefd9f loader: update for 20.0.0/21.0.0 2025-11-15 12:31:07 -07:00
Michael Scire 4b32a2b964 pgl/pm: add GetProcessId command 2025-11-15 12:31:07 -07:00
Michael Scire 0fb9481e59 kern: fix debug build for [[nodiscard]] changes 2025-11-15 12:31:07 -07:00
Michael Scire c05d91f44a kern: fix whoops introduced by nodiscard refactor 2025-11-15 12:31:07 -07:00
Michael Scire e1d82a13f3 erpt: implement new 21.0.0 commands 2025-11-15 12:31:07 -07:00
Michael Scire 4f1201a022 erpt: fix ids, failed to copy the new categories 2025-11-15 12:31:07 -07:00
Michael Scire 4201bbff63 fatal: add new HashedTraceContext command 2025-11-15 12:31:07 -07:00
Michael Scire 94c36a3255 erpt: add new IDs for 21.0.0 2025-11-15 12:31:07 -07:00
Michael Scire 6b0ef21b83 kern: RESERVED_2F now set by HandleFpuException 2025-11-15 12:31:07 -07:00
Michael Scire ac382f69e7 kern: exception flags are now atomic.
This is a really weird one, because they didn't actually update the
code which updates these flags in asm, these still use ldrb/orr/strb.
But every access to these via c++ is now an atomic ldxrb/stxrb loop.
Maybe they just forgot to update the asm?
2025-11-15 12:31:07 -07:00
Michael Scire 2a44550dbe kern: pass u32 directly to CopyMemoryToUserSize32Bit 2025-11-15 12:31:07 -07:00
Michael Scire 3bc1951820 ams: mark ams::Result [[nodiscard]] (partially complete).
NOTE: This work is not yet fully complete; kernel is done, but
it was taking an exceedingly long time to get through libstratosphere.
Thus, I've temporarily added -Wno-error=unused-result for libstratosphere/stratosphere.

All warnings should be fixed to do the same thing Nintendo does as relevant, but this
is taking a phenomenally long time and is not actually the most important work to do,
so it can be put off for some time to prioritize other tasks for 21.0.0 support.
2025-11-15 12:31:07 -07:00
Michael Scire 418fde40a8 kern: Nintendo now also devirtualizes KAutoObject::DynamicCast 2025-11-15 12:31:07 -07:00
Michael Scire e36051359c kern: write cpu tick differential to tls +0x108 on thread switch 2025-11-15 12:31:07 -07:00
Michael Scire 18bb1fdea0 fusee/exo/ams: update with new keydata/version enums 2025-11-15 12:31:07 -07:00
Michael Scire c8e39a54d2 fs.mitm: add another game which needs stolen heap for layeredfs 2025-10-07 23:12:07 -07:00
Michael Scire 11a46e4579 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "583ae0fbf"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "583ae0fbf"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-10-07 17:34:00 -07:00
Michael Scire 652519da2e fssystem: fix support for parsing newer-format BKTR NCAs
Apparently, at some point they started allowing maxlayers=3, which caused this code to not work.

Looking at latest FS, they always reference DataStorage instead of level+2 for the final level.

This fixes parsing update romfs for newer games, e.g. Super Mario Galaxy 2.
2025-10-07 17:30:12 -07:00
Michael Scire de9b02007b git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "efd3d931a"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "efd3d931a"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-09-29 18:45:20 -07:00
Michael Scire 982f0e4fd4 ams: bump version, add enum support for 20.5.0 2025-09-29 18:44:40 -07:00
Michael Scire d7936d3fa4 exo: improve offset-table fix (save 8 bytes) 2025-09-02 19:50:08 -07:00
Michael Scire 1c0ea680b6 docs: add note about deadlock fix 2025-09-02 18:37:24 -07:00
Michael Scire b8ed942ae4 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "bbd085442"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "bbd085442"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-09-02 18:36:29 -07:00
Michael Scire 98bc030b37 ams.mitm: fix deadlock when building multiple romfs simultaneously (closes #1972) 2025-09-02 18:35:42 -07:00
Michael Scire 081e76a2b5 ams: bump version, add enum support for 20.4.0 2025-09-02 18:29:51 -07:00
Michael Scire e8de1e3c34 exo: fix register access tables to page start 2025-09-02 18:29:50 -07:00
comex 41b28bb0c4 build: portability fixes
- Invoke Python scripts with `python3` if `python` is not available.

  Despite SciresM preferring Python 2, the scripts used in the build all
  worked in Python 3 already, so this is just a Makefile change.

- Export `MAKE` to work around a GNU bug.

  See the comment for details.

- `rmdir --ignore-fail-on-non-empty` -> `rmdir 2>/dev/null`

  macOS `rmdir` doesn't support `--ignore-fail-on-non-empty`.

  This is a slight downgrade in functionality, because now we ignore all
  errors from `rmdir` rather than just 'Directory not empty'.  I could
  have avoided this with a more complicated fix, but the benefit strikes
  me as not worth the complexity.  Let me know if you disagree.

- Append `$(DEVKITPRO)/tools/bin/` to `$PATH` when invoking
  `build_romfs`.

  This avoids the need to add devkitPro directories to `$PATH` when
  building Atmosphere.

  If you already have `build_romfs` in your PATH, then that will still
  take precedence.  (This seemed like the nicer option, though I don't
  have strong opinions.)
2025-08-16 16:22:32 -07:00
comex 3197b1e25b nanovg: disable some compiler warnings
Disable all warnings seen on devkitA64 GCC 15.1.0:

- Several false-positive `-Wmisleading-indentation` warnings (the
  indentation is not actually misleading)

- One `-Wuse-after-free` warning, which looks alarming and represents
  very dubious design, but is ultimately harmless (a freed pointer is
  passed to a function that doesn't use it).

- Some `-Wunused-function` warnings in `simd/neon.h`
2025-08-08 14:16:03 -07:00
comex 822cbbbc8b daybreak: fix strncpy compiler warning
GCC warned that the output string would not be nul-terminated if the
input string was too long.  Fix this by subtracting 1 from the size
argument, as is done for other `strncpy` calls in the file.  (It would
probably be better to avoid `strncpy` entirely, but this is just a
simple fix.)
2025-08-08 14:16:03 -07:00
comex 4237f52ee2 haze: fix duplicate-macro warnings
haze was including both `<switch.h>` and `vapours/types.hpp` which both
define `R_SUCCEEDED` and `R_FAILED`, producing compiler warnings.

The intent is that `vapours/types.hpp` only gets included when targeting
not-Switch and/or not-EL0.  But the check didn't account for
Troposphère.  Fix that.
2025-08-08 14:16:03 -07:00
Michael Scire 8b8e4438e8 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "bc7a0fc11"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "bc7a0fc11"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-07-29 15:17:41 -07:00
Michael Scire debfff9f62 ams: bump version, support 20.3.0 2025-07-29 15:16:51 -07:00
Michael Scire c77acb32be fs.mitm: steal some heap when building romfs for kotor2 (closes #2564) 2025-07-22 00:36:51 -07:00
Michael Scire af859d9e65 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "af10bca1b"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "af10bca1b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-07-16 10:23:50 -07:00
Michael Scire a487efad6b ams: bump version, add 1.9.2 changelog 2025-07-16 10:23:05 -07:00
Michael Scire 7e0eb10e32 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "4e3615355"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "4e3615355"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-07-14 18:24:52 -07:00
Michael Scire 4a3e2b5c57 ams: add enum version support for 20.1.x/20.2.0 2025-07-14 18:24:09 -07:00
lsp199308 d8a37b4b71 loader: add usb 3.0 enable patches for 20.1.0 (#2556)
* loader: add usb 3.0 enable patches for 20.1.0
2025-06-03 01:04:52 -07:00
Michael Scire b11850b3a3 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "0f72b2ceb"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "0f72b2ceb"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-05-28 19:34:34 -07:00
Michael Scire 77603bf7e5 docs: add basic changelog for 1.9.1 2025-05-28 19:33:49 -07:00
Marcus Carter 6b01ebca9e Clarify that code type 0xC4 uses a 64-bit value in cheats.md by formatting the key values as such
Changes the formatting of the key values at `Code Type 0xC4: Begin Extended Keypress Conditional Block` in cheats.md so that it is perfectly clear that those values are 64-bit values rather than 32-bit or 28-bit like `Code Type 0x8: Begin Keypress Conditional Block`, and also for the fact that the formatting matches the rest of the document and is thus cleaner.
2025-05-28 14:47:45 -07:00
Michael Scire 17be65b4b9 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "a8e5f1a18"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "a8e5f1a18"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2025-05-28 12:29:54 -07:00
Michael Scire 409c3cf9e1 emummc: note 20.1.0 support in README 2025-05-28 12:29:17 -07:00
Michael Scire f4e1d0bf9f kern: move spendsgir static assert 2025-05-28 12:18:51 -07:00
Michael Scire ae65b5df0c fusee/emummc: add support for FS 20.1.0 2025-05-28 12:02:56 -07:00
Michael Scire 0a299a3d40 erpt: update IDs for 20.1.0 2025-05-28 11:48:04 -07:00
Michael Scire 801438953d kern: save/restore spendsgir in KInterruptController::Save/RestoreCoreLocal 2025-05-28 10:54:52 -07:00
Michael Scire 3fbc59cce1 kern: wait 100us after synchronizing cores before saving interrupt state on sleep 2025-05-28 10:48:42 -07:00
Michael Scire f646d9c8f9 kern: use KLightLock for KCoreBarrierInterruptHandler 2025-05-28 10:44:31 -07:00
Michael Scire 69cc653e7f Add version enums for 20.1.0 2025-05-28 10:32:26 -07:00
Michael Scire 6da88f8f3e docs: add banner to readme 2025-05-27 22:24:41 -07:00
385 changed files with 63448 additions and 2672 deletions

No files matched your search

+80
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"]
+4
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)
+1 -1
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)
+8
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
@@ -55,6 +62,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
+110
View File
@@ -1,4 +1,114 @@
# Changelog
## 1.12.1
+ Support was added for the new c-ares resolver in `dns.mitm`.
+ Firmware 23.0.0 introduced a new set of commands to the `sfdnsres` service. These commands provide c-ares async support for DNS resolution and are now used by most sysmodules.
+ This resulted in host redirection not being applied at all and without warning since we simply were not intercepting the new commands.
+ `dns.mitm` now fully reimplements the c-ares serialization code and intercepts the relevant commands. In tandem with the `bsdsocket` sysmodule, we now keep track of resolution queries and redirect their results.
+ Support was added for the new "BatchRead" storage in `fs.mitm`.
+ Firmware 23.0.0 introduced a new type of filesystem storage object abstracted by the interface "IStorageForBatchRead". This is a derived class from "IStorage" with the purpose of adding the new "BatchRead" command.
+ Anything that uses the filesystem API now attempts to use this type of storage instead of the old one. This is of particular relevance for `qlaunch` and for supporting custom themes which were broken as a consequence of this change.
+ `fs.mitm` was updated and extended to not only support the new storage type but also intercept a few newer commands that were previously missing.
+ The patches for the browser applets were redesigned.
+ The introduction of these patches in the previous release led to several issues and crashes, notably during media playback in the eshop and within games that use LibAppletOff.
+ After extensive analysis and testing it was concluded that the browser applets were running out of memory and still required reducing the memory we reserve for custom sysmodules.
+ New patches have been devised and introduced in this release.
+ Instead of patching size checks, we now trick the browser applets into thinking there is 1GB of free memory available to them.
+ Unused memory is still being reclaimed and discounted from the root heap, but now more realistically.
+ The browser engine's heap is now being shrunk with no noticeable downsides to media playback nor web page rendering.
+ Thanks to these changes we can now provide 40MB for custom system modules once again.
+ A number of minor issues were fixed and improvements were made, such as:
+ Automatic PRODINFO backup was fixed for recent console models that no longer use the ECC device certificate (thanks @chrisbraucker).
+ State initialization for SharedMemory and TransferMemory was fixed (thanks @fl0be).
+ Compatibility was fixed for Trails in the Sky 2nd Chapter (thanks @masagrator).
+ General system stability improvements to enhance the user's experience.
## 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.
## 1.10.1
+ Basic support was added for 21.1.0.
+ A bug was fixed that caused some games (e.g. Tomb Raider definitive edition) to fail to launch.
+ General system stability improvements to enhance the user's experience.
## 1.10.0
+ Basic support was added for 21.0.0.
+ The console should boot and atmosphère should be fully functional.
+ **Please note**: All homebrew software may need to be re-compiled with the latest libnx (>= 4.10.0), or else it may crash/experience memory corruption.
+ Nintendo broke the userland<->kernel TLS ABI in 21.0.0, by writing to previously reserved space.
+ Homebrew used this reserved space for its TLS slots, which means any homebrew software using TLS slots will experience memory corruption when running under Atmosphere 1.10.0.
+ This doesn't appear to impact everything, but a large portion of tested homebrew crashes (often on exit), and so will need re-compile for the new ABI.
+ For those technically inclined, while TLS slots are rarely used by developers, they're used to implement features like e.g. C++ exceptions under the hood, and so anything using those crashes, etc.
+ To help make this transition easier, hbmenu now shows a warning when selecting homebrew compiled with an older, incompatible ABI version.
+ I apologize for the hassle in general.
+ libnx has been updated so that its reserved space matches Nintendo's now -- this particular issue can never occur again, even if Nintendo touches more reserved space.
+ `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.
+ `pm` 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.
+ `fatal` was updated to reflect the latest official behavior.
+ Support was added for launching another game-which-has-too-many-files with romfs mods.
+ I rely on user reports for adding support/fixing these, and some of these games can be pretty obscure!
+ If you are affected by this, you will see "Data abort (0x101)" when trying to launch the game with mods.
+ Please reach out to `sciresm` on discord if this occurs to share your error report binary.
+ Although some games may be impossible to fix, I believe I can get almost everything working, so please let me try to help you (and improve atmosphère's support!) if you run into this!
+ General system stability improvements to enhance the user's experience.
## 1.9.5
+ Basic support was added for 20.5.0.
+ General system stability improvements to enhance the user's experience.
+4 -4
View File
@@ -4,9 +4,9 @@
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = git@github.com:lulle2007200/emuMMC.git
branch = internal-emummc
commit = 2d7e66d2097e5c25b584d1fc6c908de1642bdd9d
parent = 4a83cd0403a54f1a702b6f4b9609ca9ccc81902b
remote = https://github.com/m4xw/emummc
branch = develop
commit = 11a2fd2a25a526c9df92506d69da1f679b1bd997
parent = 6eb8c3e7ce4209c60bac362f1b88804318cccad2
method = merge
cmdver = 0.4.9
+1 -1
View File
@@ -2,7 +2,7 @@
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
### Supported Horizon Versions
**1.0.0 - 20.1.0**
**1.0.0 - 23.0.1**
## Features
* Arbitrary SDMMC backend selection
+40
View File
@@ -79,6 +79,16 @@
#include "offsets/2000_exfat.h"
#include "offsets/2010.h"
#include "offsets/2010_exfat.h"
#include "offsets/2100.h"
#include "offsets/2100_exfat.h"
#include "offsets/2120.h"
#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
@@ -169,6 +179,16 @@ DEFINE_OFFSET_STRUCT(_2000);
DEFINE_OFFSET_STRUCT(_2000_EXFAT);
DEFINE_OFFSET_STRUCT(_2010);
DEFINE_OFFSET_STRUCT(_2010_EXFAT);
DEFINE_OFFSET_STRUCT(_2100);
DEFINE_OFFSET_STRUCT(_2100_EXFAT);
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) {
@@ -298,6 +318,26 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_2010));
case FS_VER_20_1_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_2010_EXFAT));
case FS_VER_21_0_0:
return &(GET_OFFSET_STRUCT_NAME(_2100));
case FS_VER_21_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_2100_EXFAT));
case FS_VER_21_2_0:
return &(GET_OFFSET_STRUCT_NAME(_2120));
case FS_VER_21_2_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_2120_EXFAT));
case FS_VER_22_0_0:
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);
}
+15
View File
@@ -116,6 +116,21 @@ enum FS_VER
FS_VER_20_1_0,
FS_VER_20_1_0_EXFAT,
FS_VER_21_0_0,
FS_VER_21_0_0_EXFAT,
FS_VER_21_2_0,
FS_VER_21_2_0_EXFAT,
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,
};
+59
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_2100_H__
#define __FS_2100_H__
// Accessor vtable getters
#define FS_OFFSET_2100_SDMMC_ACCESSOR_GC 0x1AC970
#define FS_OFFSET_2100_SDMMC_ACCESSOR_SD 0x1AE980
#define FS_OFFSET_2100_SDMMC_ACCESSOR_NAND 0x1ACFA0
// Hooks
#define FS_OFFSET_2100_SDMMC_WRAPPER_READ 0x1A8850
#define FS_OFFSET_2100_SDMMC_WRAPPER_WRITE 0x1A88B0
#define FS_OFFSET_2100_RTLD 0x2E1C0
#define FS_OFFSET_2100_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2100_CLKRST_SET_MIN_V_CLK_RATE 0x1CB9B0
// Misc funcs
#define FS_OFFSET_2100_LOCK_MUTEX 0x1A17D0
#define FS_OFFSET_2100_UNLOCK_MUTEX 0x1A1830
#define FS_OFFSET_2100_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1A8810
#define FS_OFFSET_2100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1A8830
// Misc Data
#define FS_OFFSET_2100_SD_MUTEX 0xFEE408
#define FS_OFFSET_2100_NAND_MUTEX 0xFE9CF0
#define FS_OFFSET_2100_ACTIVE_PARTITION 0xFE9D30
#define FS_OFFSET_2100_SDMMC_DAS_HANDLE 0xFCBB18
// NOPs
#define FS_OFFSET_2100_SD_DAS_INIT 0x2B5C8
// Nintendo Paths
#define FS_OFFSET_2100_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2100_H__
+59
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_2100_EXFAT_EXFAT_H__
#define __FS_2100_EXFAT_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_2100_EXFAT_SDMMC_ACCESSOR_GC 0x1B7AD0
#define FS_OFFSET_2100_EXFAT_SDMMC_ACCESSOR_SD 0x1B9AE0
#define FS_OFFSET_2100_EXFAT_SDMMC_ACCESSOR_NAND 0x1B8100
// Hooks
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_READ 0x1B39B0
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_WRITE 0x1B3A10
#define FS_OFFSET_2100_EXFAT_RTLD 0x2E1C0
#define FS_OFFSET_2100_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2100_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1D6B10
// Misc funcs
#define FS_OFFSET_2100_EXFAT_LOCK_MUTEX 0x1AC930
#define FS_OFFSET_2100_EXFAT_UNLOCK_MUTEX 0x1AC990
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B3970
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B3990
// Misc Data
#define FS_OFFSET_2100_EXFAT_SD_MUTEX 0xFFF408
#define FS_OFFSET_2100_EXFAT_NAND_MUTEX 0xFFACF0
#define FS_OFFSET_2100_EXFAT_ACTIVE_PARTITION 0xFFAD30
#define FS_OFFSET_2100_EXFAT_SDMMC_DAS_HANDLE 0xFD8B18
// NOPs
#define FS_OFFSET_2100_EXFAT_SD_DAS_INIT 0x2B5C8
// Nintendo Paths
#define FS_OFFSET_2100_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2100_EXFAT_EXFAT_H__
+59
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_2120_H__
#define __FS_2120_H__
// Accessor vtable getters
#define FS_OFFSET_2120_SDMMC_ACCESSOR_GC 0x1AC970
#define FS_OFFSET_2120_SDMMC_ACCESSOR_SD 0x1AE980
#define FS_OFFSET_2120_SDMMC_ACCESSOR_NAND 0x1ACFA0
// Hooks
#define FS_OFFSET_2120_SDMMC_WRAPPER_READ 0x1A8850
#define FS_OFFSET_2120_SDMMC_WRAPPER_WRITE 0x1A88B0
#define FS_OFFSET_2120_RTLD 0x2E1C0
#define FS_OFFSET_2120_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2120_CLKRST_SET_MIN_V_CLK_RATE 0x1CB9B0
// Misc funcs
#define FS_OFFSET_2120_LOCK_MUTEX 0x1A17D0
#define FS_OFFSET_2120_UNLOCK_MUTEX 0x1A1830
#define FS_OFFSET_2120_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1A8810
#define FS_OFFSET_2120_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1A8830
// Misc Data
#define FS_OFFSET_2120_SD_MUTEX 0xFEE408
#define FS_OFFSET_2120_NAND_MUTEX 0xFE9CF0
#define FS_OFFSET_2120_ACTIVE_PARTITION 0xFE9D30
#define FS_OFFSET_2120_SDMMC_DAS_HANDLE 0xFCBB18
// NOPs
#define FS_OFFSET_2120_SD_DAS_INIT 0x2B5C8
// Nintendo Paths
#define FS_OFFSET_2120_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2120_H__
+59
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_2120_EXFAT_EXFAT_H__
#define __FS_2120_EXFAT_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_2120_EXFAT_SDMMC_ACCESSOR_GC 0x1B7AD0
#define FS_OFFSET_2120_EXFAT_SDMMC_ACCESSOR_SD 0x1B9AE0
#define FS_OFFSET_2120_EXFAT_SDMMC_ACCESSOR_NAND 0x1B8100
// Hooks
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_READ 0x1B39B0
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_WRITE 0x1B3A10
#define FS_OFFSET_2120_EXFAT_RTLD 0x2E1C0
#define FS_OFFSET_2120_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2120_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1D6B10
// Misc funcs
#define FS_OFFSET_2120_EXFAT_LOCK_MUTEX 0x1AC930
#define FS_OFFSET_2120_EXFAT_UNLOCK_MUTEX 0x1AC990
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B3970
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B3990
// Misc Data
#define FS_OFFSET_2120_EXFAT_SD_MUTEX 0xFFF408
#define FS_OFFSET_2120_EXFAT_NAND_MUTEX 0xFFACF0
#define FS_OFFSET_2120_EXFAT_ACTIVE_PARTITION 0xFFAD30
#define FS_OFFSET_2120_EXFAT_SDMMC_DAS_HANDLE 0xFD8B18
// NOPs
#define FS_OFFSET_2120_EXFAT_SD_DAS_INIT 0x2B5C8
// Nintendo Paths
#define FS_OFFSET_2120_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_2120_EXFAT_EXFAT_H__
+59
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_2200_H__
#define __FS_2200_H__
// Accessor vtable getters
#define FS_OFFSET_2200_SDMMC_ACCESSOR_GC 0x1B01C0
#define FS_OFFSET_2200_SDMMC_ACCESSOR_SD 0x1B21C0
#define FS_OFFSET_2200_SDMMC_ACCESSOR_NAND 0x1B07F0
// Hooks
#define FS_OFFSET_2200_SDMMC_WRAPPER_READ 0x1AC0F0
#define FS_OFFSET_2200_SDMMC_WRAPPER_WRITE 0x1AC150
#define FS_OFFSET_2200_RTLD 0x2DED0
#define FS_OFFSET_2200_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2200_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260
// Misc funcs
#define FS_OFFSET_2200_LOCK_MUTEX 0x1A4EF0
#define FS_OFFSET_2200_UNLOCK_MUTEX 0x1A4F40
#define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0
#define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1AC0D0
// Misc Data
#define FS_OFFSET_2200_SD_MUTEX 0xFF1408
#define FS_OFFSET_2200_NAND_MUTEX 0xFECD00
#define FS_OFFSET_2200_ACTIVE_PARTITION 0xFECD40
#define FS_OFFSET_2200_SDMMC_DAS_HANDLE 0xFCEB98
// NOPs
#define FS_OFFSET_2200_SD_DAS_INIT 0x2B438
// Nintendo Paths
#define FS_OFFSET_2200_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_2200_H__
+59
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_2200_EXFAT_H__
#define __FS_2200_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_2200_EXFAT_SDMMC_ACCESSOR_GC 0x1BB3B0
#define FS_OFFSET_2200_EXFAT_SDMMC_ACCESSOR_SD 0x1BD3B0
#define FS_OFFSET_2200_EXFAT_SDMMC_ACCESSOR_NAND 0x1BB9E0
// Hooks
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_READ 0x1B72E0
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_WRITE 0x1B7340
#define FS_OFFSET_2200_EXFAT_RTLD 0x2DED0
#define FS_OFFSET_2200_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
#define FS_OFFSET_2200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450
// Misc funcs
#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
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B72C0
// Misc Data
#define FS_OFFSET_2200_EXFAT_SD_MUTEX 0x1002408
#define FS_OFFSET_2200_EXFAT_NAND_MUTEX 0xFFDD00
#define FS_OFFSET_2200_EXFAT_ACTIVE_PARTITION 0xFFDD40
#define FS_OFFSET_2200_EXFAT_SDMMC_DAS_HANDLE 0xFDBB98
// NOPs
#define FS_OFFSET_2200_EXFAT_SD_DAS_INIT 0x2B438
// Nintendo Paths
#define FS_OFFSET_2200_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_2200_EXFAT_H__
+59
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
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
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
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__
+14 -7
View File
@@ -458,7 +458,7 @@ static void _file_based_sd_initialize(void)
if (f_emu_sd.parts == 1)
f_emu_sd.parts = 0;
return;
break;
}
if(!f_expand_cltbl(&f_emu_sd.fp[f_emu_sd.parts], EMUSD_FP_CLMT_COUNT, &f_emu_sd.clmt[f_emu_sd.parts][0], f_size(&f_emu_sd.fp[f_emu_sd.parts]))){
@@ -513,8 +513,13 @@ static void _file_based_emmc_finalize(void)
f_close(&f_emu.fp_boot0);
f_close(&f_emu.fp_boot1);
for (int i = 0; i < f_emu.parts; i++)
f_close(&f_emu.fp_gpp[i]);
{
int i = 0;
do {
f_close(&f_emu.fp_gpp[i]);
i++;
} while (i < f_emu.parts);
}
// Force unmount FAT volume.
if (emuMMC_ctx.EMMC_Type == EmummcType_File_Emmc) {
@@ -532,9 +537,11 @@ static void _file_based_sd_finalize(void)
{
if((emuMMC_ctx.SD_Type == EmummcType_File_Emmc || emuMMC_ctx.SD_Type == EmummcType_File_Sd) && file_based_sd_initialized){
_ensure_correct_partition(FS_SDMMC_SD);
for(int i = 0; i < f_emu_sd.parts; i++){
int i = 0;
do {
f_close(&f_emu_sd.fp[i]);
}
i++;
} while(i < f_emu_sd.parts);
if(emuMMC_ctx.SD_Type == EmummcType_File_Emmc) {
_mount_emmc(false);
@@ -716,7 +723,7 @@ static void _file_based_emmc_initialize(void)
if (f_emu.parts == 1)
f_emu.parts = 0;
return;
break;
}
if (!f_expand_cltbl(&f_emu.fp_gpp[f_emu.parts], EMUMMC_FP_CLMT_COUNT,
@@ -1052,7 +1059,7 @@ static uint64_t emummc_read_write_sd_inner(void *buf, unsigned int sector, unsig
goto out;
}
} else {
fp = &f_emu.fp_gpp[0];
fp = &f_emu_sd.fp[0];
}
+12 -1
View File
@@ -344,7 +344,18 @@ static bool load_emummc_sd_ctx(void) {
exo_emummc_config_t config;
__attribute__((aligned(0x1000))) exo_emummc_paths_t paths;
load_emummc_cfg(EXO_EMUMMC_MMC_SD, &config, &paths);
// Try to get SD config. Official Atmosphere exosphere does not support
// EXO_EMUMMC_MMC_SD and returns SmcResult::NotSupported. In that case,
// fall through to the default SD behavior (no SD redirection).
int x = smcGetEmummcConfig(EXO_EMUMMC_MMC_SD, &config, &paths);
if(x != 0) {
DEBUG_LOG("GetEmummcConfig SD smc not supported, using defaults\n");
emuMMC_ctx.SD_Type = EmummcType_Partition_Sd;
emuMMC_ctx.SD_StoragePartitionOffset = 0;
emuMMC_ctx.fs_ver = FS_VER_MAX;
emuMMC_ctx.magic = (u32)-1;
return false;
}
if (config.base_cfg.magic == EMUMMC_STORAGE_MAGIC) {
emuMMC_ctx.magic = config.base_cfg.magic;
@@ -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 0x8C, 0x2E, 0xC1, 0x1C, 0xA0, 0x28, 0x35, 0xFC, 0x9A, 0x9F, 0x1D, 0x9B, 0x4E, 0xDF, 0x1E, 0x03
.byte 0x2B, 0xCD, 0xE7, 0xA4, 0x93, 0x12, 0x0A, 0x72, 0x64, 0x2B, 0x9E, 0xA4, 0xC2, 0x9F, 0xED, 0x13
/* Mariko Production Master Kek Source. */
.byte 0x1A, 0x31, 0x62, 0x87, 0xA8, 0x09, 0xCA, 0xF8, 0x69, 0x15, 0x45, 0xC2, 0x6B, 0xAA, 0x5A, 0x8A
.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. */
@@ -111,6 +111,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x0C, 0x75, 0x39, 0x15, 0x53, 0xEA, 0x81, 0x11, 0xA3, 0xE0, 0xDC, 0x3D, 0x0E, 0x76, 0xC6, 0xB8 /* Master key 10 encrypted with Master key 11. */
.byte 0x90, 0x64, 0xF9, 0x08, 0x29, 0x88, 0xD4, 0xDC, 0x73, 0xA4, 0xA1, 0x13, 0x9E, 0x59, 0x85, 0xA0 /* Master key 11 encrypted with Master key 12. */
.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. */
@@ -133,6 +136,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 /* Master key 10 encrypted with Master key 11. */
.byte 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 /* Master key 11 encrypted with Master key 12. */
.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. */
@@ -152,6 +158,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x14, 0xF5, 0xA5, 0xD0, 0x73, 0x6D, 0x44, 0x80, 0x5F, 0x31, 0x5A, 0x8F, 0x1E, 0xD4, 0x0D, 0x63 /* 18.0.0 Device Master Key Source Source. */
.byte 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 /* 19.0.0 Device Master Key Source Source. */
.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. */
@@ -171,6 +180,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x3B, 0x00, 0x89, 0xD7, 0xA9, 0x9E, 0xB7, 0x70, 0x86, 0x00, 0xC3, 0x49, 0x52, 0x8C, 0xA4, 0xAF /* 18.0.0 Device Master Kek Source. */
.byte 0xAE, 0x78, 0x36, 0xB6, 0x91, 0xEB, 0xAF, 0x9C, 0x18, 0xF1, 0xC0, 0xD5, 0x8A, 0x0C, 0x7C, 0xA1 /* 19.0.0 Device Master Kek Source. */
.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. */
@@ -189,4 +201,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x21, 0xD6, 0x35, 0xF1, 0x0F, 0x7A, 0xF0, 0x5D, 0xDF, 0x79, 0x1C, 0x7A, 0xE4, 0x32, 0x82, 0x9E /* 17.0.0 Device Master Kek Source. */
.byte 0xE7, 0x85, 0x8C, 0xA2, 0xF4, 0x49, 0xCB, 0x07, 0xD1, 0x8E, 0x48, 0x1B, 0xE8, 0x1E, 0x28, 0x3B /* 18.0.0 Device Master Kek Source. */
.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 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 0xA0, 0xC8, 0x44, 0x39, 0x8A, 0x1F, 0xD8, 0x6A, 0x3D, 0x0A, 0x23, 0xFF, 0x43, 0xA6, 0x95, 0x80 /* 23.0.0 Device Master Kek Source. */
@@ -94,7 +94,7 @@ namespace ams::secmon::boot {
}
/* Check that the key generation is one that we can use. */
static_assert(pkg1::KeyGeneration_Count == 20);
static_assert(pkg1::KeyGeneration_Count == 23);
if (key_generation >= pkg1::KeyGeneration_Count) {
return false;
}
@@ -44,4 +44,11 @@ SetRegisterAllowed(APBDEV_PMC_SEL_DPD_TIM); /* 0x1C8 */
SetRegisterAllowed(APBDEV_PMC_TSC_MULT); /* 0x2B4 */
SetRegisterAllowed(APBDEV_PMC_GPU_RG_CNTRL); /* 0x2D4 */
SetRegisterAllowed(APBDEV_PMC_CNTRL2); /* 0x440 */
SetRegisterAllowed(APBDEV_PMC_AOTAG_CFG); /* 0x484 */
SetRegisterAllowed(APBDEV_PMC_TSENSOR_CONFIG0); /* 0x49C */
SetRegisterAllowed(APBDEV_PMC_TSENSOR_CONFIG1); /* 0x4A0 */
SetRegisterAllowed(APBDEV_PMC_TSENSOR_CONFIG2); /* 0x4A4 */
SetRegisterAllowed(APBDEV_PMC_TSENSOR_STATUS0); /* 0x4A8 */
SetRegisterAllowed(APBDEV_PMC_TSENSOR_STATUS1); /* 0x4AC */
SetRegisterAllowed(APBDEV_PMC_TSENSOR_PDIV); /* 0x4B4 */
SetRegisterAllowed(APBDEV_PMC_WAKE_DEBOUNCE_EN); /* 0x4D8 */
@@ -132,13 +132,13 @@ namespace ams::secmon::smc {
}
u32 GetMemoryMode() {
/* Unless development function is enabled or memory_mode_auto is set, 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 (GetSecmonConfiguration().IsMemoryModeAuto()) {
/* If memory_mode_auto is set, determine memory mode from physical memory */
memory_mode = GetMemoryMode(pkg1::MemoryMode_Auto);
} else 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());
}
return memory_mode;
@@ -148,23 +148,20 @@ 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());
}
if (GetSecmonConfiguration().IsMemoryModeAuto()) {
memory_size = pkg1::GetMemorySize(GetMemoryMode(pkg1::MemoryMode_Auto));
if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) {
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode()));
}
value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size);
/* Exosphere extensions. */
const auto &sc = GetSecmonConfiguration();
if (!sc.DisableUserModeExceptionHandlers()) {
value.Set<KernelConfiguration::EnableUserExceptionHandlers>(true);
}
@@ -176,6 +173,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;
@@ -185,7 +203,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;
@@ -252,6 +270,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) {
@@ -522,9 +543,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;
}
}
}
@@ -38,6 +38,7 @@ namespace ams::secmon::smc {
RegulatorType = 15,
DeviceUniqueKeyGeneration = 16,
Package2Hash = 17,
Unknown18 = 18,
/* Extension config items for exosphere. */
ExosphereApiVersion = 65000,
+1 -1
View File
@@ -602,7 +602,7 @@ namespace ams::nxboot {
Print("\n");
if (R_SUCCEEDED(save_result)) {
Print("Report saved to /atmosphere/fatal_errors/report_%016" PRIx64 ".bin", f_ctx->report_identifier);
Print("Report saved to /atmosphere/fatal_errors/report_%016" PRIx64 ".bin\n", f_ctx->report_identifier);
} else {
Print("Failed to save report to the SD card! (%08" PRIx32 ")\n", save_result.GetValue());
}
+18 -3
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. */
0x1A, 0x31, 0x62, 0x87, 0xA8, 0x09, 0xCA, 0xF8, 0x69, 0x15, 0x45, 0xC2, 0x6B, 0xAA, 0x5A, 0x8A
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. */
0x8C, 0x2E, 0xC1, 0x1C, 0xA0, 0x28, 0x35, 0xFC, 0x9A, 0x9F, 0x1D, 0x9B, 0x4E, 0xDF, 0x1E, 0x03
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. */
0xA1, 0x7D, 0x34, 0xDB, 0x2D, 0x9D, 0xDA, 0xE5, 0xF8, 0x15, 0x63, 0x4C, 0x8F, 0xE7, 0x6C, 0xD8
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] = {
@@ -74,6 +74,9 @@ namespace ams::nxboot {
{ 0x14, 0xF5, 0xA5, 0xD0, 0x73, 0x6D, 0x44, 0x80, 0x5F, 0x31, 0x5A, 0x8F, 0x1E, 0xD4, 0x0D, 0x63 }, /* 18.0.0 Device Master Key Source Source. */
{ 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 }, /* 19.0.0 Device Master Key Source Source. */
{ 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] = {
@@ -94,6 +97,9 @@ namespace ams::nxboot {
{ 0xE7, 0x85, 0x8C, 0xA2, 0xF4, 0x49, 0xCB, 0x07, 0xD1, 0x8E, 0x48, 0x1B, 0xE8, 0x1E, 0x28, 0x3B }, /* 18.0.0 Device Master Kek Source. */
{ 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F }, /* 19.0.0 Device Master Kek Source. */
{ 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] = {
@@ -114,6 +120,9 @@ namespace ams::nxboot {
{ 0x3B, 0x00, 0x89, 0xD7, 0xA9, 0x9E, 0xB7, 0x70, 0x86, 0x00, 0xC3, 0x49, 0x52, 0x8C, 0xA4, 0xAF }, /* 18.0.0 Device Master Kek Source. */
{ 0xAE, 0x78, 0x36, 0xB6, 0x91, 0xEB, 0xAF, 0x9C, 0x18, 0xF1, 0xC0, 0xD5, 0x8A, 0x0C, 0x7C, 0xA1 }, /* 19.0.0 Device Master Kek Source. */
{ 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] = {
@@ -137,6 +146,9 @@ namespace ams::nxboot {
{ 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 }, /* Master key 10 encrypted with Master key 11. */
{ 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 }, /* Master key 11 encrypted with Master key 12. */
{ 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] = {
@@ -160,6 +172,9 @@ namespace ams::nxboot {
{ 0x0C, 0x75, 0x39, 0x15, 0x53, 0xEA, 0x81, 0x11, 0xA3, 0xE0, 0xDC, 0x3D, 0x0E, 0x76, 0xC6, 0xB8 }, /* Master key 10 encrypted with Master key 11. */
{ 0x90, 0x64, 0xF9, 0x08, 0x29, 0x88, 0xD4, 0xDC, 0x73, 0xA4, 0xA1, 0x13, 0x9E, 0x59, 0x85, 0xA0 }, /* Master key 11 encrypted with Master key 12. */
{ 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] = {};
+3 -1
View File
@@ -118,7 +118,9 @@ namespace ams::nxboot {
}
/* Read emuMMC/emuSD config now, need to switch to emuSD, if active, to read AMS files from there */
ReadEmummcConfig();
if (R_FAILED(ReadEmummcConfig())) {
ShowFatalError("Failed to read emummc config.");
}
/* Switch to emuSD, if active */
SwapToEmuSd();
+1 -1
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 == 20);
static_assert(pkg1::KeyGeneration_Count == 23);
if (key_generation >= pkg1::KeyGeneration_Count) {
return false;
}
+15 -2
View File
@@ -154,6 +154,12 @@ namespace ams::nxboot {
return ams::TargetFirmware_19_0_0;
} else if (std::memcmp(package1 + 0x10, "20250206", 8) == 0) {
return ams::TargetFirmware_20_0_0;
} else if (std::memcmp(package1 + 0x10, "20251009", 8) == 0) {
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:
@@ -298,8 +304,9 @@ namespace ams::nxboot {
/* If we should, save the current warmboot firmware. */
UpdateWarmbootPath(expected_fuses);
if (!IsFileExist(warmboot_path)) {
fs::CreateDirectory("warmboot_mariko");
fs::CreateFile(warmboot_path, warmboot_src_size);
/* Try to create the directory/file, allowing them to fail (if already exist). */
static_cast<void>(fs::CreateDirectory("sdmc:/warmboot_mariko"));
static_cast<void>(fs::CreateFile(warmboot_path, warmboot_src_size));
Result result;
fs::FileHandle file;
@@ -430,6 +437,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') {
@@ -186,6 +186,21 @@ namespace ams::nxboot {
FsVersion_20_1_0,
FsVersion_20_1_0_Exfat,
FsVersion_21_0_0,
FsVersion_21_0_0_Exfat,
FsVersion_21_2_0,
FsVersion_21_2_0_Exfat,
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,
};
@@ -284,6 +299,21 @@ namespace ams::nxboot {
{ 0xED, 0x34, 0xB4, 0x50, 0x58, 0x4A, 0x5B, 0x43 }, /* FsVersion_20_1_0 */
{ 0xA5, 0x1A, 0xA4, 0x92, 0x6C, 0x41, 0x87, 0x59 }, /* FsVersion_20_1_0_Exfat */
{ 0xEE, 0x4B, 0x30, 0x12, 0xA6, 0x84, 0x02, 0x25 }, /* FsVersion_21_0_0 */
{ 0x6E, 0x2B, 0xD9, 0xBA, 0xA3, 0xB9, 0x10, 0xF1 }, /* FsVersion_21_0_0_Exfat */
{ 0xAF, 0x1D, 0xBD, 0xC7, 0x82, 0x98, 0x3C, 0xBD }, /* FsVersion_21_2_0 */
{ 0x56, 0x25, 0x17, 0xA1, 0x92, 0xC3, 0xC8, 0xF0 }, /* FsVersion_21_2_0_Exfat */
{ 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) {
@@ -685,6 +715,40 @@ namespace ams::nxboot {
AddPatch(fs_meta, 0x1B3945, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x187B70, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_21_0_0:
case FsVersion_21_2_0:
AddPatch(fs_meta, 0x1AC9ED, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1ACA05, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x17FBE0, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_21_0_0_Exfat:
case FsVersion_21_2_0_Exfat:
AddPatch(fs_meta, 0x1B7B4D, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x1B7B65, NogcPatch0, sizeof(NogcPatch0));
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;
}
@@ -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));
+3 -3
View File
@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = 0f72b2ceba36c4255763d79ec48575ceb41d2539
parent = 77603bf7e54cc2717ec38c0c3fc98621c78ff642
commit = cf48d23375cf36742876f4b014971b2ebabc6dc8
parent = ff43bc566adb33c51a43b9ef45b0d3898ad39040
method = merge
cmdver = 0.4.1
cmdver = 0.4.9
+1 -1
View File
@@ -26,7 +26,7 @@ ATMOSPHERE_OPTIMIZATION_FLAG := -O2
endif
export DEFINES = $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
export SETTINGS = $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -Wextra -Werror -Wno-missing-field-initializers
export SETTINGS = $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -Wextra -Werror -Wno-missing-field-initializers -Wno-error=unused-result
export CFLAGS = $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export CXXFLAGS = $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
export ASFLAGS = $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
@@ -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];
@@ -40,6 +40,9 @@ namespace ams::pkg1 {
KeyGeneration_18_0_0 = 0x11,
KeyGeneration_19_0_0 = 0x12,
KeyGeneration_20_0_0 = 0x13,
KeyGeneration_21_0_0 = 0x14,
KeyGeneration_22_0_0 = 0x15,
KeyGeneration_23_0_0 = 0x16,
KeyGeneration_Count,
@@ -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'>;
@@ -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,
};
@@ -106,6 +107,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(); }
};
@@ -177,6 +177,9 @@ namespace ams::fuse {
}
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
TargetFirmware_23_0_0,
TargetFirmware_22_0_0,
TargetFirmware_21_0_0,
TargetFirmware_20_0_0,
TargetFirmware_19_0_0,
TargetFirmware_17_0_0,
@@ -321,8 +324,7 @@ namespace ams::fuse {
DramId GetDramId() {
/* Get the value. */
return DramId::DramId_IcosaSamsung4GB;
// return static_cast<DramId>(GetDramIdValue(util::BitPack32{GetCommonOdmWord(4)}));
return static_cast<DramId>(GetDramIdValue(util::BitPack32{GetCommonOdmWord(4)}));
}
HardwareType GetHardwareType() {
+4 -1
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));
@@ -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)
@@ -83,9 +83,9 @@ namespace ams::kern::arch::arm64 {
}
NOINLINE Result BindHandler(KInterruptHandler *handler, s32 irq, s32 core_id, s32 priority, bool manual_clear, bool level);
NOINLINE Result UnbindHandler(s32 irq, s32 core);
NOINLINE void UnbindHandler(s32 irq, s32 core);
NOINLINE Result ClearInterrupt(s32 irq, s32 core_id);
NOINLINE void ClearInterrupt(s32 irq, s32 core_id);
ALWAYS_INLINE void SendInterProcessorInterrupt(s32 irq, u64 core_mask) {
m_interrupt_controller.SendInterProcessorInterrupt(irq, core_mask);
@@ -99,10 +99,10 @@ namespace ams::kern::arch::arm64 {
private:
Result BindGlobal(KInterruptHandler *handler, s32 irq, s32 core_id, s32 priority, bool manual_clear, bool level);
Result BindLocal(KInterruptHandler *handler, s32 irq, s32 priority, bool manual_clear);
Result UnbindGlobal(s32 irq);
Result UnbindLocal(s32 irq);
Result ClearGlobal(s32 irq);
Result ClearLocal(s32 irq);
void UnbindGlobal(s32 irq);
void UnbindLocal(s32 irq);
void ClearGlobal(s32 irq);
void ClearLocal(s32 irq);
private:
[[nodiscard]] static ALWAYS_INLINE u32 GetInterruptsEnabledState() {
u64 intr_state;
@@ -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);
@@ -197,9 +204,9 @@ namespace ams::kern::arch::arm64 {
cpu::SwitchProcess(s_ttbr0_entries[proc_idx + 1], proc_id);
}
NOINLINE Result 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);
Result Finalize();
NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
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) {
/* Note the update. */
@@ -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(); }
@@ -165,7 +165,7 @@ namespace ams::kern::arch::arm64 {
constexpr explicit KThreadContext(util::ConstantInitializeTag) : m_callee_saved(), m_lr(), m_sp(), m_fpcr(), m_fpsr(), m_callee_saved_fpu(), m_locked() { /* ... */ }
explicit KThreadContext() { /* ... */ }
Result Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main);
void Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main);
void SetArguments(uintptr_t arg0, uintptr_t arg1);
@@ -35,7 +35,7 @@ namespace ams::kern::arch::arm64 {
static bool CopyMemoryToUser(void *dst, const void *src, size_t size);
static bool CopyMemoryToUserAligned32Bit(void *dst, const void *src, size_t size);
static bool CopyMemoryToUserAligned64Bit(void *dst, const void *src, size_t size);
static bool CopyMemoryToUserSize32Bit(void *dst, const void *src);
static bool CopyMemoryToUserSize32Bit(void *dst, u32 value);
static s32 CopyStringToUser(void *dst, const void *src, size_t size);
static bool UpdateLockAtomic(u32 *out, u32 *address, u32 if_zero, u32 new_orr_mask);
@@ -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;
}
@@ -100,8 +100,8 @@ namespace ams::kern::arch::arm64 {
return Impl::CopyMemoryToUserAligned64Bit(dst, src, size);
}
static bool CopyMemoryToUserSize32Bit(void *dst, const void *src) {
return Impl::CopyMemoryToUserSize32Bit(dst, src);
static bool CopyMemoryToUserSize32Bit(void *dst, u32 value) {
return Impl::CopyMemoryToUserSize32Bit(dst, value);
}
static s32 CopyStringToUser(void *dst, const void *src, size_t size) {
@@ -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);
@@ -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;
@@ -47,13 +47,6 @@
/* re-enabled by toggling this define. */
//#define MESOSPHERE_ENABLE_PROCESS_CREATION_TIME
/* NOTE: This enables fast class token storage using a class member. */
/* This saves a virtual call when doing KAutoObject->DynCast<>(), */
/* at the cost of storing class tokens inside the class object. */
/* However, as of (10/16/2021) KAutoObject has an unused class member */
/* of the right side, and so this does not actually cost any space. */
#define MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST
/* NOTE: This enables usage of KDebug handles as parameter for svc::GetInfo */
/* calls which require a process parameter. This enables a debugger to obtain */
/* address space/layout information, for example. However, it changes abi, and so */
@@ -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);
@@ -121,14 +121,9 @@ namespace ams::kern {
private:
KAutoObject *m_next_closed_object;
ReferenceCount m_ref_count;
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
ClassTokenType m_class_token;
#endif
public:
constexpr ALWAYS_INLINE explicit KAutoObject(util::ConstantInitializeTag) : m_next_closed_object(nullptr), m_ref_count(0)
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
, m_class_token(0)
#endif
constexpr ALWAYS_INLINE explicit KAutoObject(util::ConstantInitializeTag) : m_next_closed_object(nullptr), m_ref_count(0), m_class_token(0)
{
MESOSPHERE_ASSERT_THIS();
}
@@ -151,19 +146,11 @@ namespace ams::kern {
}
ALWAYS_INLINE bool IsDerivedFrom(const TypeObj &rhs) const {
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.GetClassToken());
#else
return this->GetTypeObj().IsDerivedFrom(rhs);
#endif
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.GetClassToken());
}
ALWAYS_INLINE bool IsDerivedFrom(const KAutoObject &rhs) const {
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.m_class_token);
#else
return this->IsDerivedFrom(rhs.GetTypeObj());
#endif
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.m_class_token);
}
template<typename Derived>
@@ -218,12 +205,10 @@ namespace ams::kern {
KAutoObject &auto_object = *static_cast<KAutoObject *>(obj);
/* If we should, set our class token. */
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
{
constexpr auto Token = Derived::GetStaticTypeObj().GetClassToken();
auto_object.m_class_token = Token;
}
#endif
/* Initialize reference count to 1. */
auto_object.m_ref_count = 1;
@@ -93,9 +93,9 @@ namespace ams::kern {
static Result ProcessDebugEvent(ams::svc::DebugEvent event, const uintptr_t *params, size_t num_params);
public:
static Result OnDebugEvent(ams::svc::DebugEvent event, const uintptr_t *params, size_t num_params);
static Result OnExitProcess(KProcess *process);
static Result OnTerminateProcess(KProcess *process);
static Result OnExitThread(KThread *thread);
static void OnExitProcess(KProcess *process);
static void OnTerminateProcess(KProcess *process);
static void OnExitThread(KThread *thread);
static KEventInfo *CreateDebugEvent(ams::svc::DebugEvent event, u64 thread_id, const uintptr_t *params, size_t num_params);
};
@@ -50,8 +50,8 @@ namespace ams::kern {
KReadableEvent &GetReadableEvent() { return m_readable_event; }
Result Signal();
Result Clear();
void Signal();
void Clear();
ALWAYS_INLINE void OnReadableEventDestroyed() { m_readable_event_destroyed = true; }
};
@@ -105,7 +105,7 @@ namespace ams::kern {
constexpr ALWAYS_INLINE size_t GetCount() const { return m_count; }
constexpr ALWAYS_INLINE size_t GetMaxCount() const { return m_max_count; }
MESOSPHERE_NOINLINE_IF_DEBUG Result Finalize();
MESOSPHERE_NOINLINE_IF_DEBUG void Finalize();
MESOSPHERE_NOINLINE_IF_DEBUG bool Remove(ams::svc::Handle handle);
template<typename T = KAutoObject>
@@ -38,13 +38,11 @@ namespace ams::kern {
Result Reset();
Result Clear() {
void Clear() {
MESOSPHERE_ASSERT_THIS();
/* Try to perform a reset, succeeding unconditionally. */
this->Reset();
R_SUCCEED();
/* Try to perform a reset, ignoring whether it succeeds. */
static_cast<void>(this->Reset());
}
bool IsInitialized() const { return m_is_initialized; }
@@ -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:
@@ -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,10 +197,10 @@ 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;
bool m_allowed_exec_device_mapping;
KMemoryBlockSlabManager *m_memory_block_slab_manager;
KBlockInfoManager *m_block_info_manager;
KResourceLimit *m_resource_limit;
@@ -211,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_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 Result 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();
@@ -246,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);
@@ -489,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; }
@@ -520,6 +540,8 @@ namespace ams::kern {
size_t GetAliasCodeDataSize() const;
u32 GetAllocateOption() const { return m_allocate_option; }
void AllowDeviceMappingOfExecPages() { m_allowed_exec_device_mapping = true; }
public:
static ALWAYS_INLINE KVirtualAddress GetLinearMappedVirtualAddress(KPhysicalAddress addr) {
return KMemoryLayout::GetLinearVirtualAddress(addr);
@@ -102,8 +102,8 @@ namespace ams::kern {
IoRegionList m_io_region_list;
bool m_is_suspended;
bool m_is_immortal;
bool m_is_jit_debug;
bool m_is_handle_table_initialized;
bool m_is_jit_debug;
ams::svc::DebugEvent m_jit_debug_event_type;
ams::svc::DebugException m_jit_debug_exception_type;
uintptr_t m_jit_debug_params[4];
@@ -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; }
@@ -269,7 +274,7 @@ namespace ams::kern {
void RemoveIoRegion(KIoRegion *io_region);
Result CreateThreadLocalRegion(KProcessAddress *out);
Result DeleteThreadLocalRegion(KProcessAddress addr);
void DeleteThreadLocalRegion(KProcessAddress addr);
void *GetThreadLocalRegionPointer(KProcessAddress addr);
constexpr KProcessAddress GetProcessLocalRegionAddress() const { return m_plr_address; }
@@ -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. */
@@ -35,16 +35,14 @@ namespace ams::kern {
constexpr KEvent *GetParent() const { return m_parent; }
Result Signal();
void Signal();
Result Reset();
Result Clear() {
void Clear() {
MESOSPHERE_ASSERT_THIS();
/* Try to perform a reset, succeeding unconditionally. */
this->Reset();
R_SUCCEED();
/* Try to perform a reset, ignoring whether it succeeds. */
static_cast<void>(this->Reset());
}
virtual bool IsSignaled() const override;
@@ -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);
@@ -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); }
@@ -29,6 +29,7 @@ namespace ams::kern {
class KProcess;
class KConditionVariable;
class KAddressArbiter;
class KPageBuffer;
using KThreadFunction = void (*)(uintptr_t);
@@ -105,7 +106,7 @@ namespace ams::kern {
util::Atomic<u8> dpc_flags;
u8 current_svc_id;
u8 reserved_2c;
u8 exception_flags;
util::Atomic<u8> exception_flags;
bool is_pinned;
u8 reserved_2f;
u8 reserved_30[0x10];
@@ -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{}
{
/* ... */
}
@@ -417,17 +421,17 @@ namespace ams::kern {
private:
ALWAYS_INLINE void SetExceptionFlag(ExceptionFlag flag) {
MESOSPHERE_ASSERT_THIS();
this->GetStackParameters().exception_flags |= flag;
this->GetStackParameters().exception_flags.FetchOr<std::memory_order_relaxed>(flag);
}
ALWAYS_INLINE void ClearExceptionFlag(ExceptionFlag flag) {
MESOSPHERE_ASSERT_THIS();
this->GetStackParameters().exception_flags &= ~flag;
this->GetStackParameters().exception_flags.FetchAnd<std::memory_order_relaxed>(~flag);
}
ALWAYS_INLINE bool IsExceptionFlagSet(ExceptionFlag flag) const {
MESOSPHERE_ASSERT_THIS();
return this->GetStackParameters().exception_flags & flag;
return this->GetStackParameters().exception_flags.Load<std::memory_order_relaxed>() & flag;
}
public:
/* ALWAYS_INLINE void SetCallingSvc() { return this->SetExceptionFlag(ExceptionFlag_IsCallingSvc); } */
@@ -523,7 +527,7 @@ namespace ams::kern {
Result GetCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
Result SetCoreMask(int32_t ideal_core, u64 affinity_mask);
Result GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
void GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
constexpr ThreadState GetState() const { return static_cast<ThreadState>(m_thread_state & ThreadState_Mask); }
constexpr ThreadState GetRawState() const { return m_thread_state; }
@@ -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? */
@@ -717,7 +724,7 @@ namespace ams::kern {
}
void SetBasePriority(s32 priority);
Result SetPriorityToIdle();
void SetPriorityToIdle();
Result Run();
void Exit();
@@ -725,7 +732,7 @@ namespace ams::kern {
Result Terminate();
ThreadState RequestTerminate();
Result Sleep(s64 timeout);
void Sleep(s64 timeout);
ALWAYS_INLINE void *GetStackTop() const { return reinterpret_cast<StackParameters *>(m_kernel_stack_top) - 1; }
ALWAYS_INLINE void *GetKernelStackTop() const { return m_kernel_stack_top; }
@@ -77,7 +77,7 @@ namespace ams::kern {
}
public:
Result Initialize(KProcess *process);
Result Finalize();
void Finalize();
KProcessAddress Reserve();
void Release(KProcessAddress addr);
+2
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
#---------------------------------------------------------------------------------
@@ -215,11 +215,13 @@ namespace ams::kern::arch::arm64::cpu {
KThread::Register(new_thread);
/* Run the thread. */
new_thread->Run();
MESOSPHERE_R_ABORT_UNLESS(new_thread->Run());
}
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;
@@ -508,16 +510,16 @@ namespace ams::kern::arch::arm64::cpu {
g_cache_operation_handler.Initialize(core_id);
/* Bind all handlers to the relevant interrupts. */
Kernel::GetInterruptManager().BindHandler(std::addressof(g_cache_operation_handler), KInterruptName_CacheOperation, core_id, KInterruptController::PriorityLevel_High, false, false);
Kernel::GetInterruptManager().BindHandler(std::addressof(g_thread_termination_handler), KInterruptName_ThreadTerminate, core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
Kernel::GetInterruptManager().BindHandler(std::addressof(g_core_barrier_handler), KInterruptName_CoreBarrier, core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_cache_operation_handler), KInterruptName_CacheOperation, core_id, KInterruptController::PriorityLevel_High, false, false));
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_thread_termination_handler), KInterruptName_ThreadTerminate, core_id, KInterruptController::PriorityLevel_Scheduler, false, false));
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_core_barrier_handler), KInterruptName_CoreBarrier, core_id, KInterruptController::PriorityLevel_Scheduler, false, false));
/* If we should, enable user access to the performance counter registers. */
if (KTargetSystem::IsUserPmuAccessEnabled()) { SetPmUserEnrEl0(1ul); }
/* If we should, enable the kernel performance counter interrupt handler. */
#if defined(MESOSPHERE_ENABLE_PERFORMANCE_COUNTER)
Kernel::GetInterruptManager().BindHandler(std::addressof(g_performance_counter_handler[core_id]), KInterruptName_PerformanceCounter, core_id, KInterruptController::PriorityLevel_Timer, false, false);
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_performance_counter_handler[core_id]), KInterruptName_PerformanceCounter, core_id, KInterruptController::PriorityLevel_Timer, false, false));
#endif
}
@@ -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;
@@ -25,7 +25,7 @@ namespace ams::kern::arch::arm64 {
m_maximum_time = static_cast<s64>(std::min<u64>(std::numeric_limits<s64>::max(), cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor().GetCompareValue()));
/* Bind the interrupt task for this core. */
Kernel::GetInterruptManager().BindHandler(this, KInterruptName_NonSecurePhysicalTimer, GetCurrentCoreId(), KInterruptController::PriorityLevel_Timer, true, true);
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(this, KInterruptName_NonSecurePhysicalTimer, GetCurrentCoreId(), KInterruptController::PriorityLevel_Timer, true, true));
}
void KHardwareTimer::Finalize() {
@@ -126,7 +126,7 @@ namespace ams::kern::arch::arm64 {
if (entry.handler != nullptr) {
/* Set manual clear needed if relevant. */
if (entry.manually_cleared) {
m_interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
m_interrupt_controller.Disable(irq);
entry.needs_clear = true;
}
@@ -242,40 +242,40 @@ namespace ams::kern::arch::arm64 {
}
}
Result KInterruptManager::UnbindHandler(s32 irq, s32 core_id) {
void KInterruptManager::UnbindHandler(s32 irq, s32 core_id) {
MESOSPHERE_UNUSED(core_id);
R_UNLESS(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq), svc::ResultOutOfRange());
MESOSPHERE_ASSERT(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq));
if (KInterruptController::IsGlobal(irq)) {
KScopedInterruptDisable di;
KScopedSpinLock lk(this->GetGlobalInterruptLock());
R_RETURN(this->UnbindGlobal(irq));
} else {
return this->UnbindGlobal(irq);
} else if (KInterruptController::IsLocal(irq)) {
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
KScopedInterruptDisable di;
R_RETURN(this->UnbindLocal(irq));
return this->UnbindLocal(irq);
}
}
Result KInterruptManager::ClearInterrupt(s32 irq, s32 core_id) {
void KInterruptManager::ClearInterrupt(s32 irq, s32 core_id) {
MESOSPHERE_UNUSED(core_id);
R_UNLESS(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq), svc::ResultOutOfRange());
MESOSPHERE_ASSERT(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq));
if (KInterruptController::IsGlobal(irq)) {
KScopedInterruptDisable di;
KScopedSpinLock lk(this->GetGlobalInterruptLock());
R_RETURN(this->ClearGlobal(irq));
} else {
return this->ClearGlobal(irq);
} else if (KInterruptController::IsLocal(irq)) {
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
KScopedInterruptDisable di;
R_RETURN(this->ClearLocal(irq));
return this->ClearLocal(irq);
}
}
@@ -332,7 +332,7 @@ namespace ams::kern::arch::arm64 {
R_SUCCEED();
}
Result KInterruptManager::UnbindGlobal(s32 irq) {
void KInterruptManager::UnbindGlobal(s32 irq) {
for (size_t core_id = 0; core_id < cpu::NumCores; core_id++) {
m_interrupt_controller.ClearTarget(irq, static_cast<s32>(core_id));
}
@@ -340,50 +340,35 @@ namespace ams::kern::arch::arm64 {
m_interrupt_controller.Disable(irq);
GetGlobalInterruptEntry(irq).handler = nullptr;
R_SUCCEED();
}
Result KInterruptManager::UnbindLocal(s32 irq) {
auto &entry = this->GetLocalInterruptEntry(irq);
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
void KInterruptManager::UnbindLocal(s32 irq) {
m_interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
m_interrupt_controller.Disable(irq);
entry.handler = nullptr;
R_SUCCEED();
this->GetLocalInterruptEntry(irq).handler = nullptr;
}
Result KInterruptManager::ClearGlobal(s32 irq) {
/* We can't clear an entry with no handler. */
void KInterruptManager::ClearGlobal(s32 irq) {
/* Get the entry. */
auto &entry = GetGlobalInterruptEntry(irq);
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
/* If auto-cleared, we can succeed immediately. */
R_SUCCEED_IF(!entry.manually_cleared);
R_SUCCEED_IF(!entry.needs_clear);
/* Clear and enable. */
entry.needs_clear = false;
m_interrupt_controller.Enable(irq);
R_SUCCEED();
/* If not auto-cleared, clear and enable. */
if (entry.manually_cleared && entry.needs_clear) {
entry.needs_clear = false;
m_interrupt_controller.Enable(irq);
}
}
Result KInterruptManager::ClearLocal(s32 irq) {
/* We can't clear an entry with no handler. */
void KInterruptManager::ClearLocal(s32 irq) {
/* Get the entry. */
auto &entry = this->GetLocalInterruptEntry(irq);
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
/* If auto-cleared, we can succeed immediately. */
R_SUCCEED_IF(!entry.manually_cleared);
R_SUCCEED_IF(!entry.needs_clear);
/* Clear and set priority. */
entry.needs_clear = false;
m_interrupt_controller.SetPriorityLevel(irq, entry.priority);
R_SUCCEED();
/* If not auto-cleared, clear and enable. */
if (entry.manually_cleared && entry.needs_clear) {
entry.needs_clear = false;
m_interrupt_controller.Enable(irq);
}
}
}
@@ -119,18 +119,16 @@ namespace ams::kern::arch::arm64 {
MESOSPHERE_UNUSED(core_id);
}
Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
void KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
/* Initialize basic fields. */
m_asid = 0;
m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer();
/* Initialize the base page table. */
MESOSPHERE_R_ABORT_UNLESS(KPageTableBase::InitializeForKernel(true, table, start, end));
R_SUCCEED();
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));
@@ -146,14 +144,14 @@ 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();
R_SUCCEED();
}
Result KPageTable::Finalize() {
void KPageTable::Finalize() {
/* Only process tables should be finalized. */
MESOSPHERE_ASSERT(!this->IsKernel());
@@ -271,8 +269,6 @@ namespace ams::kern::arch::arm64 {
/* Perform inherited finalization. */
KPageTableBase::Finalize();
}
R_SUCCEED();
}
Result KPageTable::OperateImpl(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll) {
@@ -733,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);
@@ -942,7 +941,7 @@ namespace ams::kern::arch::arm64 {
/* If we should flush entries, do so. */
if ((apply_option & ApplyOption_FlushDataCache) != 0) {
if (IsHeapPhysicalAddress(next_entry.phys_addr)) {
cpu::FlushDataCache(GetVoidPointer(GetHeapVirtualAddress(next_entry.phys_addr)), next_entry.block_size);
MESOSPHERE_R_ABORT_UNLESS(cpu::FlushDataCache(GetVoidPointer(GetHeapVirtualAddress(next_entry.phys_addr)), next_entry.block_size));
}
}
@@ -37,7 +37,7 @@ namespace ams::kern::arch::arm64 {
KScopedInterruptEnable ei;
const uintptr_t params[2] = { GetCurrentThread().GetId(), GetInteger(GetCurrentThread().GetThreadLocalRegionAddress()) };
KDebug::OnDebugEvent(ams::svc::DebugEvent_CreateThread, params, util::size(params));
static_cast<void>(KDebug::OnDebugEvent(ams::svc::DebugEvent_CreateThread, params, util::size(params)));
}
/* Handle any pending dpc. */
@@ -116,7 +116,7 @@ namespace ams::kern::arch::arm64 {
}
Result KThreadContext::Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main) {
void KThreadContext::Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main) {
MESOSPHERE_ASSERT(k_sp != Null<KVirtualAddress>);
/* Ensure that the stack pointers are aligned. */
@@ -157,8 +157,6 @@ namespace ams::kern::arch::arm64 {
/* Lock the context, if we're a main thread. */
m_locked = is_main;
R_SUCCEED();
}
void KThreadContext::SetArguments(uintptr_t arg0, uintptr_t arg1) {
@@ -306,15 +306,14 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl28CopyMemoryToUserAligned64BitEPvPK
mov x0, #1
ret
/* ams::kern::arch::arm64::UserspaceAccess::Impl::CopyMemoryToUserSize32Bit(void *dst, const void *src) */
.section .text._ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv, "ax", %progbits
.global _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv
.type _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv, %function
/* ams::kern::arch::arm64::UserspaceAccess::Impl::CopyMemoryToUserSize32Bit(void *dst, u32 value) */
.section .text._ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj, "ax", %progbits
.global _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj
.type _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj, %function
.balign 0x10
_ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv:
/* Just load and store a u32. */
ldr w2, [x1]
sttr w2, [x0]
_ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj:
/* Just store a u32. */
sttr w1, [x0]
/* We're done. */
mov x0, #1
@@ -683,7 +682,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl18WriteIoMemory32BitEPvPKvm:
mov x30, x10
/* Write the word to io. */
sttr w9, [x5]
sttr w9, [x4]
dsb sy
2: /* Continue. */
@@ -728,7 +727,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl18WriteIoMemory16BitEPvPKvm:
mov x30, x10
/* Write the word to io. */
sttrh w9, [x5]
sttrh w9, [x4]
dsb sy
2: /* Continue. */
@@ -773,7 +772,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl17WriteIoMemory8BitEPvPKvm:
mov x30, x10
/* Write the word to io. */
sttrb w9, [x5]
sttrb w9, [x4]
dsb sy
2: /* Continue. */
@@ -660,8 +660,7 @@ namespace ams::kern::board::nintendo::nx {
ptm.Open(table_virt_addr, 1);
/* Save the page. Note that it is a pre-condition that the page is cleared, when allocated from the system page table manager. */
/* NOTE: Nintendo does not check the result of StoreDataCache. */
cpu::StoreDataCache(GetVoidPointer(table_virt_addr), PageDirectorySize);
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(table_virt_addr), PageDirectorySize));
g_reserved_table_phys_addr = table_phys_addr;
/* Reserve an asid to correspond to no device. */
@@ -710,7 +709,7 @@ namespace ams::kern::board::nintendo::nx {
/* Install interrupt handler. */
#if defined(MESOSPHERE_ENABLE_MEMORY_CONTROLLER_INTERRUPT)
{
Kernel::GetInterruptManager().BindHandler(std::addressof(g_mc_interrupt_task), KInterruptName_MemoryController, GetCurrentCoreId(), KInterruptController::PriorityLevel_High, true, true);
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_mc_interrupt_task), KInterruptName_MemoryController, GetCurrentCoreId(), KInterruptController::PriorityLevel_High, true, true));
}
#endif
}
@@ -806,7 +805,7 @@ namespace ams::kern::board::nintendo::nx {
MESOSPHERE_ASSERT(IsValidPhysicalAddress(GetPageTablePhysicalAddress(table_vaddr)));
ptm.Open(table_vaddr, 1);
cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageDirectorySize);
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageDirectorySize));
m_tables[i] = table_vaddr;
}
@@ -1042,7 +1041,7 @@ namespace ams::kern::board::nintendo::nx {
if (l2_index == 0 && util::IsAligned(GetInteger(phys_addr), DeviceLargePageSize) && remaining >= DeviceLargePageSize) {
/* Set the large page. */
l1[l1_index].SetLargePage(read, write, true, phys_addr);
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
/* Synchronize. */
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
@@ -1062,11 +1061,11 @@ namespace ams::kern::board::nintendo::nx {
const KVirtualAddress table_vaddr = ptm.Allocate();
R_UNLESS(table_vaddr != Null<KVirtualAddress>, svc::ResultOutOfMemory());
MESOSPHERE_ASSERT(IsValidPhysicalAddress(GetPageTablePhysicalAddress(table_vaddr)));
cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageTableSize);
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageTableSize));
/* Set the l1 table. */
l1[l1_index].SetTable(true, true, true, GetPageTablePhysicalAddress(table_vaddr));
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
/* Synchronize. */
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
@@ -1093,7 +1092,7 @@ namespace ams::kern::board::nintendo::nx {
/* Add a reference to the l2 page (from the l2 entry page). */
ptm.Open(KVirtualAddress(l2), 1);
}
cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry));
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry)));
/* Invalidate the page table cache. */
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
@@ -1199,7 +1198,7 @@ namespace ams::kern::board::nintendo::nx {
++num_closed;
}
}
cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry));
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry)));
/* Invalidate the page table cache. */
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
@@ -1243,7 +1242,7 @@ namespace ams::kern::board::nintendo::nx {
if (ptm.Close(KVirtualAddress(l2), num_closed)) {
/* Invalidate the l1 entry. */
l1[l1_index].Invalidate();
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
/* Synchronize. */
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
@@ -1266,7 +1265,7 @@ namespace ams::kern::board::nintendo::nx {
/* Invalidate the entry. */
l1[l1_index].Invalidate();
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
/* Synchronize. */
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
@@ -441,7 +441,7 @@ namespace ams::kern::board::nintendo::nx {
KThread::Register(new_thread);
/* Run the thread. */
new_thread->Run();
MESOSPHERE_R_ABORT_UNLESS(new_thread->Run());
}
}
@@ -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);
@@ -361,10 +355,24 @@ namespace ams::kern::board::nintendo::nx {
}();
/* Return (possibly) adjusted size. */
/* NOTE: On 20.0.0+ the browser requires much more memory in the applet pool in order to function. */
/* 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. */
const size_t ExtraSystemMemoryForAtmosphere = kern::GetTargetFirmware() >= ams::TargetFirmware_20_0_0 ? 14_MB : 40_MB;
return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
/* NOTE: On 23.0.0+ we are patching memory allocation for each browser applet since there are only 3 of them now. */
/* Reclaiming unused memory and lying to the browser about memory limits allows us to go back to 40 MB of extra system memory. */
/* TODO: Deduplicate post 23.0.0 and pre 20.0.0. For now, this structure helps with readability and is still subject to change. */
if (kern::GetTargetFirmware() >= ams::TargetFirmware_23_0_0) {
constexpr size_t ExtraSystemMemoryForAtmosphere_23_0_0 = 40_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) {
constexpr size_t ExtraSystemMemoryForAtmosphere_20_0_0 = 14_MB;
return base_pool_size - ExtraSystemMemoryForAtmosphere_20_0_0 - KTraceBufferSize;
} else {
constexpr size_t ExtraSystemMemoryForAtmosphere = 40_MB;
return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
}
}
size_t KSystemControl::Init::GetMinimumNonSecureSystemPoolSize() {
@@ -409,7 +417,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;
@@ -469,9 +480,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. */
@@ -516,32 +527,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() {
@@ -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));
}
@@ -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 {
@@ -140,14 +140,12 @@ namespace ams::kern {
/* Add the previously reserved pages. */
if (src_pool == dst_pool && binary_pages != 0) {
/* NOTE: Nintendo does not check the result of this operation. */
pg.AddBlock(KMemoryLayout::GetLinearPhysicalAddress(data), binary_pages);
MESOSPHERE_R_ABORT_UNLESS(pg.AddBlock(KMemoryLayout::GetLinearPhysicalAddress(data), binary_pages));
}
/* Add the previously unreserved pages. */
for (const auto &block : unreserve_pg) {
/* NOTE: Nintendo does not check the result of this operation. */
pg.AddBlock(block.GetAddress(), block.GetNumPages());
MESOSPHERE_R_ABORT_UNLESS(pg.AddBlock(block.GetAddress(), block.GetNumPages()));
}
}
MESOSPHERE_ABORT_UNLESS(pg.GetNumPages() == static_cast<size_t>(params.code_num_pages));
@@ -287,7 +285,7 @@ namespace ams::kern {
MESOSPHERE_INIT_ABORT_UNLESS(expected_size != 0);
/* Ensure that the size we need to reserve is as we expect it to be. */
const size_t total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize);
const u32 total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize);
MESOSPHERE_ABORT_UNLESS(total_size == expected_size);
MESOSPHERE_ABORT_UNLESS(total_size <= InitialProcessBinarySizeMax);
@@ -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:
@@ -37,7 +37,7 @@ namespace ams::kern {
/* Clear and store cache. */
void * const block_address = GetVoidPointer(KMemoryLayout::GetLinearVirtualAddress(block.GetAddress()));
std::memset(block_address, 0xFF, block.GetSize());
cpu::StoreDataCache(block_address, block.GetSize());
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(block_address, block.GetSize()));
}
/* Set remaining tracking members. */
@@ -23,8 +23,8 @@ namespace ams::kern {
return UserspaceAccess::CopyMemoryFromUserSize32Bit(out, GetVoidPointer(address));
}
ALWAYS_INLINE bool WriteToUser(KProcessAddress address, const u32 *p) {
return UserspaceAccess::CopyMemoryToUserSize32Bit(GetVoidPointer(address), p);
ALWAYS_INLINE bool WriteToUser(KProcessAddress address, u32 val) {
return UserspaceAccess::CopyMemoryToUserSize32Bit(GetVoidPointer(address), val);
}
ALWAYS_INLINE bool UpdateLockAtomic(u32 *out, KProcessAddress address, u32 if_zero, u32 new_orr_mask) {
@@ -94,7 +94,7 @@ namespace ams::kern {
/* Write the value to userspace. */
Result result;
if (AMS_LIKELY(WriteToUser(addr, std::addressof(next_value)))) {
if (AMS_LIKELY(WriteToUser(addr, next_value))) {
result = ResultSuccess();
} else {
result = svc::ResultInvalidCurrentMemory();
@@ -210,8 +210,8 @@ namespace ams::kern {
/* If we have no waiters, clear the has waiter flag. */
if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
const u32 has_waiter_flag = 0;
WriteToUser(cv_key, std::addressof(has_waiter_flag));
constexpr u32 HasNoWaiterFlag = 0;
WriteToUser(cv_key, HasNoWaiterFlag);
}
}
}
@@ -252,13 +252,13 @@ namespace ams::kern {
/* Write to the cv key. */
{
const u32 has_waiter_flag = 1;
WriteToUser(key, std::addressof(has_waiter_flag));
constexpr u32 HasWaiterFlag = 1;
WriteToUser(key, HasWaiterFlag);
cpu::DataMemoryBarrierInnerShareable();
}
/* Write the value to userspace. */
if (!WriteToUser(addr, std::addressof(next_value))) {
if (!WriteToUser(addr, next_value)) {
slp.CancelSleep();
R_THROW(svc::ResultInvalidCurrentMemory());
}
@@ -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;
@@ -416,7 +416,8 @@ namespace ams::kern {
KProcess * const target = this->GetProcessUnsafe();
/* Terminate the process. */
target->Terminate();
/* NOTE: This result is seemingly-intentionally not checked by Nintendo. */
static_cast<void>(target->Terminate(-1ll));
R_SUCCEED();
}
@@ -755,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:
@@ -772,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];
@@ -804,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;
}
@@ -875,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));
@@ -1133,7 +1142,7 @@ namespace ams::kern {
R_SUCCEED();
}
Result KDebugBase::OnExitProcess(KProcess *process) {
void KDebugBase::OnExitProcess(KProcess *process) {
MESOSPHERE_ASSERT(process != nullptr);
/* Check if we're attached to a debugger. */
@@ -1148,11 +1157,9 @@ namespace ams::kern {
debug->NotifyAvailable();
}
}
R_SUCCEED();
}
Result KDebugBase::OnTerminateProcess(KProcess *process) {
void KDebugBase::OnTerminateProcess(KProcess *process) {
MESOSPHERE_ASSERT(process != nullptr);
/* Check if we're attached to a debugger. */
@@ -1167,21 +1174,17 @@ namespace ams::kern {
debug->NotifyAvailable();
}
}
R_SUCCEED();
}
Result KDebugBase::OnExitThread(KThread *thread) {
void KDebugBase::OnExitThread(KThread *thread) {
MESOSPHERE_ASSERT(thread != nullptr);
/* Check if we're attached to a debugger. */
if (KProcess *process = thread->GetOwnerProcess(); process != nullptr && process->IsAttachedToDebugger()) {
/* If we are, submit the event. */
const uintptr_t params[2] = { thread->GetId(), static_cast<uintptr_t>(thread->IsTerminationRequested() ? ams::svc::ThreadExitReason_TerminateThread : ams::svc::ThreadExitReason_ExitThread) };
R_TRY(OnDebugEvent(ams::svc::DebugEvent_ExitThread, params, util::size(params)));
static_cast<void>(OnDebugEvent(ams::svc::DebugEvent_ExitThread, params, util::size(params)));
}
R_SUCCEED();
}
}
@@ -167,7 +167,7 @@ namespace ams::kern {
KThread::Register(new_thread);
/* Run the thread. */
new_thread->Run();
MESOSPHERE_R_ABORT_UNLESS(new_thread->Run());
}
void KDpcManager::HandleDpc() {
@@ -38,20 +38,20 @@ namespace ams::kern {
MESOSPHERE_ASSERT_THIS();
}
Result KEvent::Signal() {
void KEvent::Signal() {
KScopedSchedulerLock sl;
R_SUCCEED_IF(m_readable_event_destroyed);
R_RETURN(m_readable_event.Signal());
if (!m_readable_event_destroyed) {
m_readable_event.Signal();
}
}
Result KEvent::Clear() {
void KEvent::Clear() {
KScopedSchedulerLock sl;
R_SUCCEED_IF(m_readable_event_destroyed);
R_RETURN(m_readable_event.Clear());
if (!m_readable_event_destroyed) {
m_readable_event.Clear();
}
}
void KEvent::PostDestroy(uintptr_t arg) {
@@ -17,7 +17,7 @@
namespace ams::kern {
Result KHandleTable::Finalize() {
void KHandleTable::Finalize() {
MESOSPHERE_ASSERT_THIS();
/* Get the table and clear our record of it. */
@@ -35,8 +35,6 @@ namespace ams::kern {
obj->Close();
}
}
R_SUCCEED();
}
bool KHandleTable::Remove(ams::svc::Handle handle) {
@@ -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));
@@ -88,14 +88,14 @@ namespace ams::kern {
}
}
Result 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;
@@ -130,10 +130,10 @@ namespace ams::kern {
m_impl.InitializeForKernel(table, start, end);
/* Initialize our memory block manager. */
R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
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,13 @@ 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;
m_is_kernel = false;
@@ -236,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) {
@@ -346,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]);
}
}
}
@@ -560,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:
@@ -595,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:
@@ -621,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:
@@ -644,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();
}
}
@@ -1792,7 +1711,7 @@ namespace ams::kern {
/* Ensure cache coherency, if we're setting pages as executable. */
if (is_x) {
for (const auto &block : pg) {
cpu::StoreDataCache(GetVoidPointer(GetHeapVirtualAddress(block.GetAddress())), block.GetSize());
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(GetHeapVirtualAddress(block.GetAddress())), block.GetSize()));
}
cpu::InvalidateEntireInstructionCache();
}
@@ -1996,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;
@@ -2665,8 +2584,7 @@ namespace ams::kern {
/* Invalidate the block. */
if (cur_size > 0) {
/* NOTE: Nintendo does not check the result of invalidation. */
cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
MESOSPHERE_R_ABORT_UNLESS(cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size));
}
/* Advance. */
@@ -2689,8 +2607,7 @@ namespace ams::kern {
/* Invalidate the last block. */
if (cur_size > 0) {
/* NOTE: Nintendo does not check the result of invalidation. */
cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
MESOSPHERE_R_ABORT_UNLESS(cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size));
}
R_SUCCEED();
@@ -2768,7 +2685,7 @@ namespace ams::kern {
if (cur_size >= sizeof(u32)) {
const size_t copy_size = util::AlignDown(cur_size, sizeof(u32));
const void * copy_src = GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr));
cpu::FlushDataCache(copy_src, copy_size);
MESOSPHERE_R_ABORT_UNLESS(cpu::FlushDataCache(copy_src, copy_size));
R_UNLESS(UserspaceAccess::CopyMemoryToUserAligned32Bit(buffer, copy_src, copy_size), svc::ResultInvalidPointer());
buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + copy_size);
cur_addr += copy_size;
@@ -2778,7 +2695,7 @@ namespace ams::kern {
/* Copy remaining data. */
if (cur_size > 0) {
const void * copy_src = GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr));
cpu::FlushDataCache(copy_src, cur_size);
MESOSPHERE_R_ABORT_UNLESS(cpu::FlushDataCache(copy_src, cur_size));
R_UNLESS(UserspaceAccess::CopyMemoryToUser(buffer, copy_src, cur_size), svc::ResultInvalidPointer());
}
@@ -2853,7 +2770,7 @@ namespace ams::kern {
if (cur_size >= sizeof(u32)) {
const size_t copy_size = util::AlignDown(cur_size, sizeof(u32));
R_UNLESS(UserspaceAccess::CopyMemoryFromUserAligned32Bit(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), buffer, copy_size), svc::ResultInvalidCurrentMemory());
cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), copy_size);
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), copy_size));
buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + copy_size);
cur_addr += copy_size;
@@ -2863,7 +2780,7 @@ namespace ams::kern {
/* Copy remaining data. */
if (cur_size > 0) {
R_UNLESS(UserspaceAccess::CopyMemoryFromUser(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), buffer, cur_size), svc::ResultInvalidCurrentMemory());
cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size));
}
R_SUCCEED();
@@ -3079,7 +2996,9 @@ namespace ams::kern {
const u32 test_state = (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap) | (check_heap ? KMemoryState_FlagReferenceCounted : KMemoryState_None);
size_t num_allocator_blocks;
KMemoryState old_state;
R_TRY(this->CheckMemoryState(std::addressof(old_state), nullptr, nullptr, std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared));
const KMemoryPermission perm_mask = static_cast<KMemoryPermission>(perm | (m_allowed_exec_device_mapping ? KMemoryPermission_None : KMemoryPermission_UserExecute));
R_TRY(this->CheckMemoryState(std::addressof(old_state), nullptr, nullptr, std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm_mask, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared));
/* Create an update allocator. */
Result allocator_result;
@@ -3286,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. */
{
@@ -3435,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. */
{
@@ -185,6 +185,11 @@ namespace ams::kern {
/* Validate that the intended kernel version isn't too high for us to support. */
R_UNLESS(m_capabilities.GetIntendedKernelVersion() <= ams::svc::SupportedKernelVersion, svc::ResultInvalidCombination());
/* Enable mapping device pages as executable on legacy processes. */
if (m_capabilities.GetIntendedKernelMajorVersion() < 26) {
m_page_table.GetBasePageTable().AllowDeviceMappingOfExecPages();
}
/* Create and clear the process local region. */
R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address)));
m_plr_heap_address = this->GetThreadLocalRegionPointer(m_plr_address);
@@ -205,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)
@@ -221,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));
@@ -259,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. */
@@ -274,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;
@@ -288,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(); };
@@ -327,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;
@@ -353,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;
@@ -367,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(); };
@@ -387,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));
}
@@ -404,7 +419,7 @@ namespace ams::kern {
void KProcess::DoWorkerTaskImpl() {
/* Terminate child threads. */
TerminateChildren(this, nullptr);
MESOSPHERE_R_ABORT_UNLESS(TerminateChildren(this, nullptr));
/* Finalize the handle table, if we're not immortal. */
if (!m_is_immortal && m_is_handle_table_initialized) {
@@ -420,7 +435,7 @@ namespace ams::kern {
Result KProcess::StartTermination() {
/* Finalize the handle table when we're done, if the process isn't immortal. */
ON_SCOPE_EXIT {
ON_RESULT_SUCCESS {
if (!m_is_immortal) {
this->FinalizeHandleTable();
}
@@ -450,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. */
@@ -465,13 +480,14 @@ 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;
}
}
/* If we need to start termination, do so. */
if (needs_terminate) {
this->StartTermination();
static_cast<void>(this->StartTermination());
/* Note for debug that we're exiting the process. */
MESOSPHERE_LOG("KProcess::Exit() pid=%ld name=%-12s\n", m_process_id, m_name);
@@ -485,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 */
@@ -501,29 +517,33 @@ 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;
}
}
/* If we need to terminate, do so. */
if (needs_terminate) {
/* Start termination. */
if (R_SUCCEEDED(this->StartTermination())) {
/* Note for debug that we're terminating the process. */
MESOSPHERE_LOG("KProcess::Terminate() OK pid=%ld name=%-12s\n", m_process_id, m_name);
/* Call the debug callback. */
KDebug::OnTerminateProcess(this);
/* Finish termination. */
this->FinishTermination();
} else {
/* If we fail to terminate, register as a worker task. */
ON_RESULT_FAILURE {
/* Note for debug that we're terminating the process. */
MESOSPHERE_LOG("KProcess::Terminate() FAIL pid=%ld name=%-12s\n", m_process_id, m_name);
/* Register the process as a work task. */
KWorkerTaskManager::AddTask(KWorkerTaskManager::WorkerType_ExitProcess, this);
}
};
/* Start termination. */
R_TRY(this->StartTermination());
/* Note for debug that we're terminating the process. */
MESOSPHERE_LOG("KProcess::Terminate() OK pid=%ld name=%-12s\n", m_process_id, m_name);
/* Call the debug callback. */
KDebug::OnTerminateProcess(this);
/* Finish termination. */
this->FinishTermination();
}
R_SUCCEED();
@@ -666,7 +686,7 @@ namespace ams::kern {
R_SUCCEED();
}
Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
void KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
KThreadLocalPage *page_to_free = nullptr;
/* Release the region. */
@@ -678,7 +698,7 @@ namespace ams::kern {
if (it == m_partially_used_tlp_tree.end()) {
/* If we don't find it, it has to be in the fully used list. */
it = m_fully_used_tlp_tree.find_key(util::AlignDown(GetInteger(addr), PageSize));
R_UNLESS(it != m_fully_used_tlp_tree.end(), svc::ResultInvalidAddress());
MESOSPHERE_ABORT_UNLESS(it != m_fully_used_tlp_tree.end());
/* Release the region. */
it->Release(addr);
@@ -710,8 +730,6 @@ namespace ams::kern {
KThreadLocalPage::Free(page_to_free);
}
R_SUCCEED();
}
void *KProcess::GetThreadLocalRegionPointer(KProcessAddress addr) {
@@ -767,7 +785,7 @@ namespace ams::kern {
MESOSPHERE_ASSERT(m_num_running_threads.Load() > 0);
if (const auto prev = m_num_running_threads--; prev == 1) {
this->Terminate();
static_cast<void>(this->Terminate(-1ll));
}
}
@@ -964,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();
@@ -975,6 +996,9 @@ namespace ams::kern {
/* Set the thread arguments. */
main_thread->GetContext().SetArguments(0, thread_handle);
/* Pass the thread handle to the thread local region. */
static_cast<ams::svc::ThreadLocalRegion *>(main_thread->GetThreadLocalRegionHeapAddress())->thread_handle = thread_handle;
/* Update our state. */
this->ChangeState((state == State_Created) ? State_Running : State_RunningAttached);
ON_RESULT_FAILURE_2 { this->ChangeState(state); };
@@ -1180,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;
}
@@ -46,7 +46,7 @@ namespace ams::kern {
}
}
Result KReadableEvent::Signal() {
void KReadableEvent::Signal() {
MESOSPHERE_ASSERT_THIS();
KScopedSchedulerLock lk;
@@ -55,8 +55,6 @@ namespace ams::kern {
m_is_signaled = true;
this->NotifyAvailable();
}
R_SUCCEED();
}
Result KReadableEvent::Reset() {
@@ -65,7 +65,7 @@ namespace ams::kern {
}
/* Bind interrupt handler. */
Kernel::GetInterruptManager().BindHandler(GetSchedulerInterruptHandler(), KInterruptName_Scheduler, m_core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(GetSchedulerInterruptHandler(), KInterruptName_Scheduler, m_core_id, KInterruptController::PriorityLevel_Scheduler, false, false));
/* Set the current thread. */
m_current_thread = GetCurrentThreadPointer();
@@ -270,7 +270,13 @@ namespace ams::kern {
m_current_thread = next_thread;
/* Set the new Thread Local region. */
cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress()));
const auto tls_address = GetInteger(next_thread->GetThreadLocalRegionAddress());
cpu::SwitchThreadLocalRegion(tls_address);
/* Update the thread's cpu time differential in TLS, if relevant. */
if (tls_address != 0) {
static_cast<ams::svc::ThreadLocalRegion *>(next_thread->GetThreadLocalRegionHeapAddress())->thread_cpu_time = next_thread->GetCpuTime() - cur_tick;
}
}
void KScheduler::ClearPreviousThread(KThread *thread) {
@@ -476,8 +476,8 @@ namespace ams::kern {
/* Ensure that we clean up on failure. */
ON_RESULT_FAILURE {
dst_page_table.CleanupForIpcServer(dst_address, size, dst_state);
src_page_table.CleanupForIpcClient(src_address, size, dst_state);
static_cast<void>(dst_page_table.CleanupForIpcServer(dst_address, size, dst_state));
static_cast<void>(src_page_table.CleanupForIpcClient(src_address, size, dst_state));
};
/* Push the appropriate mapping. */
@@ -582,7 +582,7 @@ namespace ams::kern {
/* Set up a guard to make sure that we end up in a clean state on error. */
ON_RESULT_FAILURE {
/* Cleanup mappings. */
CleanupMap(request, std::addressof(dst_process), std::addressof(src_page_table));
static_cast<void>(CleanupMap(request, std::addressof(dst_process), std::addressof(src_page_table)));
/* Cleanup special data. */
if (src_header.GetHasSpecialHeader()) {
@@ -835,11 +835,11 @@ namespace ams::kern {
CleanupSpecialData(dst_process, dst_msg_ptr, dst_buffer_size);
}
} else {
CleanupServerHandles(src_user ? src_message_buffer : 0, src_buffer_size, src_message_paddr);
static_cast<void>(CleanupServerHandles(src_user ? src_message_buffer : 0, src_buffer_size, src_message_paddr));
}
/* Cleanup mappings. */
CleanupMap(request, std::addressof(src_process), std::addressof(dst_page_table));
static_cast<void>(CleanupMap(request, std::addressof(src_process), std::addressof(dst_page_table)));
};
/* Ensure that the headers fit. */
@@ -1052,7 +1052,7 @@ namespace ams::kern {
/* Unlock the client buffer. */
/* NOTE: Nintendo does not check the result of this. */
client_pt.UnlockForIpcUserBuffer(client_message, client_buffer_size);
static_cast<void>(client_pt.UnlockForIpcUserBuffer(client_message, client_buffer_size));
/* Signal the event. */
event->Signal();
@@ -1156,7 +1156,7 @@ namespace ams::kern {
/* Unlock the client buffer. */
/* NOTE: Nintendo does not check the result of this. */
client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size);
static_cast<void>(client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size));
/* Signal the event. */
event->Signal();
@@ -1284,7 +1284,7 @@ namespace ams::kern {
/* Unlock the client buffer. */
/* NOTE: Nintendo does not check the result of this. */
client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size);
static_cast<void>(client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size));
/* Signal the event. */
event->Signal();
@@ -1383,7 +1383,7 @@ namespace ams::kern {
/* Unlock the buffer. */
/* NOTE: Nintendo does not check the result of this. */
client_pt.UnlockForIpcUserBuffer(request->GetAddress(), request->GetSize());
static_cast<void>(client_pt.UnlockForIpcUserBuffer(request->GetAddress(), request->GetSize()));
/* Signal the event. */
event->Signal();
@@ -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() {
@@ -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() {
@@ -42,7 +42,7 @@ namespace ams::kern {
R_UNLESS(m_resource_size > rc_size, svc::ResultOutOfMemory());
/* Initialize slab heaps. */
m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, PageSize);
R_TRY(m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, PageSize));
m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, GetPointer<KPageTableManager::RefCount>(m_resource_address));
m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
@@ -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,9 +417,15 @@ 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>) {
MESOSPHERE_R_ABORT_UNLESS(m_parent->DeleteThreadLocalRegion(m_tls_address));
m_parent->DeleteThreadLocalRegion(m_tls_address);
}
/* Release any waiters. */
@@ -697,7 +730,7 @@ namespace ams::kern {
R_SUCCEED();
}
Result KThread::GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask) {
void KThread::GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask) {
MESOSPHERE_ASSERT_THIS();
{
KScopedSchedulerLock sl;
@@ -712,8 +745,6 @@ namespace ams::kern {
*out_affinity_mask = m_original_physical_affinity_mask.GetAffinityMask();
}
}
R_SUCCEED();
}
Result KThread::SetCoreMask(int32_t core_id, u64 v_affinity_mask) {
@@ -852,7 +883,7 @@ namespace ams::kern {
}
}
Result KThread::SetPriorityToIdle() {
void KThread::SetPriorityToIdle() {
MESOSPHERE_ASSERT_THIS();
KScopedSchedulerLock sl;
@@ -862,8 +893,6 @@ namespace ams::kern {
m_priority = IdleThreadPriority;
m_base_priority = IdleThreadPriority;
KScheduler::OnThreadPriorityChanged(this, old_priority);
R_SUCCEED();
}
void KThread::RequestSuspend(SuspendType type) {
@@ -1407,7 +1436,7 @@ namespace ams::kern {
return this->GetState();
}
Result KThread::Sleep(s64 timeout) {
void KThread::Sleep(s64 timeout) {
MESOSPHERE_ASSERT_THIS();
MESOSPHERE_ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread());
MESOSPHERE_ASSERT(this == GetCurrentThreadPointer());
@@ -1422,15 +1451,13 @@ namespace ams::kern {
/* Check if the thread should terminate. */
if (this->IsTerminationRequested()) {
slp.CancelSleep();
R_THROW(svc::ResultTerminationRequested());
return;
}
/* Wait for the sleep to end. */
wait_queue.SetHardwareTimer(timer);
this->BeginWait(std::addressof(wait_queue));
}
R_SUCCEED();
}
void KThread::BeginWait(KThreadQueue *queue) {
@@ -32,7 +32,7 @@ namespace ams::kern {
R_RETURN(m_owner->GetPageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, page_buf->GetPhysicalAddress(), KMemoryState_ThreadLocal, KMemoryPermission_UserReadWrite));
}
Result KThreadLocalPage::Finalize() {
void KThreadLocalPage::Finalize() {
MESOSPHERE_ASSERT_THIS();
/* Get the physical address of the page. */
@@ -40,11 +40,10 @@ namespace ams::kern {
MESOSPHERE_ABORT_UNLESS(m_owner->GetPageTable().GetPhysicalAddress(std::addressof(phys_addr), this->GetAddress()));
/* Unmap the page. */
R_TRY(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState_ThreadLocal));
MESOSPHERE_R_ABORT_UNLESS(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState_ThreadLocal));
/* Free the page. */
KPageBuffer::FreeChecked<PageSize>(KPageBuffer::FromPhysicalAddress(phys_addr));
R_SUCCEED();
}
KProcessAddress KThreadLocalPage::Reserve() {
@@ -67,7 +67,7 @@ namespace ams::kern {
KThread::Register(thread);
/* Run the thread. */
thread->Run();
MESOSPHERE_R_ABORT_UNLESS(thread->Run());
}
void KWorkerTaskManager::AddTask(WorkerType type, KWorkerTask *task) {
@@ -52,8 +52,8 @@ namespace ams::kern {
void *idle_thread_stack = GetVoidPointer(KMemoryLayout::GetIdleStackTopAddress(core_id));
KAutoObject::Create<KThread>(main_thread);
KAutoObject::Create<KThread>(idle_thread);
main_thread->Initialize(nullptr, 0, main_thread_stack, 0, KThread::MainThreadPriority, core_id, nullptr, KThread::ThreadType_Main);
idle_thread->Initialize(nullptr, 0, idle_thread_stack, 0, KThread::IdleThreadPriority, core_id, nullptr, KThread::ThreadType_Main);
MESOSPHERE_R_ABORT_UNLESS(main_thread->Initialize(nullptr, 0, main_thread_stack, 0, KThread::MainThreadPriority, core_id, nullptr, KThread::ThreadType_Main));
MESOSPHERE_R_ABORT_UNLESS(idle_thread->Initialize(nullptr, 0, idle_thread_stack, 0, KThread::IdleThreadPriority, core_id, nullptr, KThread::ThreadType_Main));
/* Set the current thread to be the main thread, and we have no processes running yet. */
SetCurrentThread(main_thread);
@@ -79,7 +79,7 @@ namespace ams::kern {
KDynamicPageManager * const sys_dynamic_page_manager = KTargetSystem::IsDynamicResourceLimitsEnabled() ? std::addressof(g_resource_manager_page_manager) : nullptr;
/* Initialize the resource managers' shared page manager. */
g_resource_manager_page_manager.Initialize(address, size, std::max<size_t>(PageSize, KPageBufferSlabHeap::BufferSize));
MESOSPHERE_R_ABORT_UNLESS(g_resource_manager_page_manager.Initialize(address, size, std::max<size_t>(PageSize, KPageBufferSlabHeap::BufferSize)));
/* Initialize the KPageBuffer slab heap. */
KPageBuffer::InitializeSlabHeap(g_resource_manager_page_manager);
@@ -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());
@@ -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));
@@ -131,7 +131,7 @@ namespace ams::kern::svc {
} else {
class StoreCacheOperation : public CacheOperation {
public:
virtual void Operate(void *address, size_t size) const override { cpu::StoreDataCache(address, size); }
virtual void Operate(void *address, size_t size) const override { MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(address, size)); }
} operation;
R_RETURN(DoProcessCacheOperation(operation, page_table, address, size));
@@ -158,7 +158,7 @@ namespace ams::kern::svc {
} else {
class FlushCacheOperation : public CacheOperation {
public:
virtual void Operate(void *address, size_t size) const override { cpu::FlushDataCache(address, size); }
virtual void Operate(void *address, size_t size) const override { MESOSPHERE_R_ABORT_UNLESS(cpu::FlushDataCache(address, size)); }
} operation;
R_RETURN(DoProcessCacheOperation(operation, page_table, address, size));
Loaded 100 of 385 files, more files were not shown because too many files have changed in this diff. Show more