Compare commits

..

266 Commits

Author SHA1 Message Date
Michael Scire
4fe9a89ab8 docs: commit saddest changelog of all time, this is your brain on going to vacation 2023-08-21 17:30:06 -07:00
Michael Scire
de73f6c5bb git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "c3dc418a2"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "c3dc418a2"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-08-21 17:27:16 -07:00
Michael Scire
e488b6ee47 ams: add enum recognition for 16.1.0 2023-08-21 17:26:27 -07:00
Michael Scire
99810dc091 fssystem: fix typo error in BucketTree::Visitor::MoveNext 2023-08-15 14:47:09 -07:00
Liam
e54957285f libstrat: comment fixes for fssystem 2023-08-12 11:33:29 -07:00
Michael Scire
fca213460b libstrat: fix more minor style issues pointed out by Pharynx 2023-08-10 11:48:28 -07:00
Michael Scire
4e6bd19fcd fssystem: fix stupid issue in NodeBuffer move-ctor
Code compiles with this constructor deleted, so it wasn't used, but even so...
2023-08-03 16:58:55 -07:00
Michael Scire
8b88351cb4 mitm: fix errant include on non-hos 2023-06-06 19:32:06 -07:00
Michael Scire
63ea152349 fatal: take good idea from shrek 2023-05-19 11:47:38 -07:00
Michael Scire
3cb54e2b4b git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "f4a966eb4"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "f4a966eb4"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-05-14 03:17:20 -07:00
Michael Scire
e9de11a746 ams: bump version to 1.5.4 2023-05-14 03:16:27 -07:00
Michael Scire
b979b5aa36 docs: 1.5.4 changelog, zelda why the fuck 2023-05-14 03:16:15 -07:00
SciresM
f2ee44da74 romfs/ams.mitm/pm: refactor to dynamically steal heap for certain games. (#2122)
* fs.mitm: skeleton the use of special allocation in romfs build

* pm: add api for ams.mitm to steal application memory

* pm/mitm: okay, that api won't work, try a different one

* romfs: revert memory usage increases; we'll handle torture games case-by-case.

* pm/romfs: first (broken?) pass at dynamic heap.

I cannot wait to figure out all the ways this is wrong.

* Release the dynamic heap a little more eagerly

* romfs: animal crossing is also not a nice game

* romfs: fix issues in close-during-build

* romfs: zelda is a blight upon this earth
2023-05-14 03:06:52 -07:00
Michael Scire
85c23b5781 fusee: actually identify new FS 2023-05-08 18:38:13 -07:00
Michael Scire
8e042f2262 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "30205111e"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "30205111e"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-05-08 18:25:25 -07:00
Michael Scire
81e9154a52 emummc: add enums for 16.0.3 2023-05-08 18:24:49 -07:00
Michael Scire
e9b9dbc2aa docs: add changelog for 1.5.3 2023-05-08 18:19:31 -07:00
Michael Scire
7e6c849ca4 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "cd0fc2c1d"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "cd0fc2c1d"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-05-08 18:06:50 -07:00
Michael Scire
8ec7c096d0 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "d2fcc73eb"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "d2fcc73eb"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-05-08 18:05:36 -07:00
Michael Scire
6e5b901a9b emummc: support 16.0.3 2023-05-08 18:03:35 -07:00
Michael Scire
b800953d66 ams: recognize 16.0.3('s FS) 2023-05-08 17:51:13 -07:00
Michael Scire
f0240db75a fs.mitm: mitm glue for font replacement, before I forget 2023-05-08 17:40:10 -07:00
Michael Scire
1f5ec68a5c ams: fix compilation with gcc 13 2023-05-07 03:36:46 -07:00
Michael Scire
ed9e60acb9 kern: track heap in KPageTableBase::MemoryRange 2023-04-30 16:50:53 -07:00
Liam
a7300b0fa4 haze: fix file size transmission issue 2023-04-18 22:15:48 -07:00
Liam
8e2eca2004 haze: abstract firmware version and serial number fetch 2023-04-18 22:15:48 -07:00
Michael Scire
9f83b3c838 ams: I really need to automate keeping this in sync 2023-04-17 20:57:57 -07:00
Michael Scire
434c8cefc4 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "ecc8b1811"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "ecc8b1811"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-04-17 20:40:41 -07:00
Michael Scire
d8aed7de6d ams: add 16.0.2 enum 2023-04-17 20:40:02 -07:00
Liam
a346014dc7 haze: get serial number and firmware version from set:sys 2023-04-17 22:22:28 -04:00
Michael Scire
4b3c801e9f dist: add haze to output zip 2023-04-17 14:35:25 -07:00
Michael Scire
90db1223f6 docs: avoid unintended insinuations 2023-04-17 14:24:27 -07:00
Michael Scire
fa64a6ff4d docs: pretend to be literate 2023-04-17 14:20:16 -07:00
Michael Scire
0c6a06a0cf git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "7340e2eab"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "7340e2eab"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-04-17 14:19:59 -07:00
Michael Scire
5efb4a2a98 docs: bump version, 16.0.1 exists too 2023-04-17 14:19:18 -07:00
liamwhite
3b662122f9 troposphere: add haze MTP server (#2095)
* troposphere: add haze MTP server

* haze: adjust banner, new lines between class sections, single-statement if

* haze: remove additional newlines between sections

* haze: avoid use of reference out parameter

* haze: console_main_loop: style

* haze: event_reactor, file_system_proxy, ptp: style

* haze: ptp_data_builder, ptp_object_database, ptp_object_heap, results, usb_session: style

* haze: event_reactor, ptp_data_parser, async_usb_server, ptp_object_database, ptp_object_heap: style

* haze: ptp_responder: style

* haze: usb_session: style

* haze: use svc defs from vapours

* haze: misc comments

* haze: fix pointer overflow check

* haze: fix copy paste error

* haze: use alignment, invalidate cached use values in console

* haze: fix stray hex constant

* haze: misc style

* haze: fixes for windows

* haze: add GetObjectPropsSupported, GetObjectPropDesc, GetObjectPropValue

* haze: add SetObjectPropValue

* haze: improve object database API

* haze: improve WriteVariableLengthData readability

* haze: fix directory renames on windows

* haze: ptp_object_database: fix collation

* haze: event_reactor: fix size validation

* haze: ptp_responder: improve documentation

* haze: ptp_responder: avoid unnecessary fs interaction in GetObjectPropValue

* haze: ptp_responder: fix object deletion on windows

* haze: tear down sessions on suspension

* haze: prefer more specific data types

* haze: misc

* haze: fix usb 3.0 support

* haze: improve host-to-device file transfer performance

* haze: report device serial

* haze: move static_assert to requires, fix alignment
2023-04-17 14:08:05 -07:00
Michael Scire
e9b28ab4b1 kern: adjust wording to be more technically correct 2023-03-27 10:54:58 -07:00
Michael Scire
1afb184c14 docs: pretend I know how to type common words 2023-03-14 01:52:06 -07:00
Michael Scire
5e070600a9 docs: add faq.md
"Alexa, what does June 15th mean?"
2023-03-14 01:48:19 -07:00
Michael Scire
8274081e39 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "b1607dc8a"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "b1607dc8a"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-03-13 17:17:50 -07:00
Michael Scire
f1ad26ce84 ams: bump version 2023-03-13 17:16:51 -07:00
Michael Scire
e4c314146e docs: update changelog 2023-03-13 17:16:33 -07:00
Michael Scire
52f00731d9 settings: add os guard 2023-03-12 22:34:23 -07:00
Michael Scire
476d658a79 ams: allow convertible-to-result in abort print macros 2023-03-11 15:14:33 -07:00
Michael Scire
7263022bac docs: mention bluetooth db feature 2023-03-10 10:24:19 -07:00
Michael Scire
e0e7aa1e2f set.mitm: misc style fixes for bluetooth db 2023-03-10 10:19:58 -07:00
ndeadly
bd9d8fff46 Add system setting to mirror bluetooth pairing database to sd card (#1787)
* ams_mitm: add ability to mirror bluetooth device pairing database to sd card via a system setting

* ams_mitm: address requested stylistic changes

* ams_mitm: make use of R_SUCCEED macro

* ams_mitm: use settings::BluetoothDevicesSettings instead of libnx type

* ams_mitm: fix logic error when truncating pairing database on read

* Update .ini comment

* ams_mitm: missing R_TRY around call to fs::FlushFile

* stratosphere: remove union from BluetoothDevicesSettings type

---------

Co-authored-by: ndeadly <24677491+ndeadly@users.noreply.github.com>
2023-03-10 10:06:38 -07:00
Michael Scire
61e3f0b391 windows: disable -fdata-sections
This causes all data to be emitted as .data$*. This breaks fzero-initialized-in-bss,
because linker puts stuff in .data even when it's all-zero and should end up in .bss.
2023-03-09 23:46:54 -07:00
Michael Scire
cd9b173318 windows: re-enable lto for os/fs libraries 2023-03-09 23:46:31 -07:00
Michael Scire
a8df400825 kern: fix stray addressof operator 2023-03-08 09:46:38 -07:00
Michael Scire
68040e2922 windows: add brave new mingw compat hook for gcc 12.2.0+ 2023-03-07 22:07:03 -07:00
Michael Scire
8da4d14e15 kern: minor cleanup (thanks @liamwhite) 2023-03-06 21:18:00 -07:00
Michael Scire
e2ebf9c0ff fatal: correct comment about pools 2023-03-01 03:21:51 -07:00
Michael Scire
5fb6f52b9e fatal: dynamically allocate memory as required (preferring system > nonsecure > unsafe) 2023-03-01 03:20:49 -07:00
Michael Scire
982389dceb os: add UnsafeMemory apis 2023-03-01 03:20:49 -07:00
Adubbz
f636596ee2 daybreak: scale title font size
(cherry picked from commit 035b37c615183bd387210a54d269346e3a9b379a)
2023-02-25 10:53:16 +11:00
Michael Scire
0a2440522f fatal: use a hack to be kinder wrt pl:u session limit 2023-02-23 22:06:49 -07:00
Michael Scire
3292ea5970 kern: fix stray comment copy/paste error 2023-02-23 22:00:00 -07:00
Michael Scire
33d42f4831 erpt: update server code for 16.0.0 logic changes 2023-02-23 21:51:51 -07:00
Michael Scire
46094cfb3e kern: increase non-dynamic heap sizes to 8 GB to match 2023-02-23 19:05:52 -07:00
Michael Scire
618691a500 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "af0d00890"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "af0d00890"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-02-23 09:01:41 -07:00
Michael Scire
356d89244f docs: add 1.5.0 pre-release changelog 2023-02-22 18:36:01 -07:00
Michael Scire
1ce3611695 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "bba1f1fb6"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "bba1f1fb6"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-02-22 18:26:15 -07:00
Michael Scire
1ab8b23444 emummc: try fixing commit id 2023-02-22 18:25:41 -07:00
Michael Scire
06b4738d54 emummc: re-update for 16.0.0 2023-02-22 18:24:51 -07:00
Michael Scire
b92c614347 git subrepo clone --force --branch=develop https://github.com/m4xw/emummc
subrepo:
  subdir:   "emummc"
  merged:   "4714b2df9"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "4714b2df9"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-02-22 18:23:27 -07:00
Michael Scire
99175c1149 loader: update usb3 patches for 16.0.0 2023-02-22 17:19:51 -08:00
Michael Scire
8876eedfb0 ncm: alignment was changed for PlaceHolderId/ContentId in 16.0.0 2023-02-22 17:19:51 -08:00
Michael Scire
bbcee8c77c ncm: fix inversion in activation skipping 2023-02-22 17:19:51 -08:00
Michael Scire
f7915c2c05 ncm: Add IntegratedContent*Impl 2023-02-22 17:19:51 -08:00
Michael Scire
668cabd4a2 ncm: first pass at ContentManagerImpl refactor (missing the IntegratedImpls, won't link) 2023-02-22 17:19:51 -08:00
Michael Scire
d64ab354ad kern: 16.x web applet crashes on exit with 48 MB stolen (rip) 2023-02-22 17:19:51 -08:00
Michael Scire
59b518783d ncm: fix copy/paste error in switch case 2023-02-22 17:19:51 -08:00
Michael Scire
6462101b6f strat: fix sysmodule building, bump version so I don't forget later 2023-02-22 17:19:51 -08:00
Michael Scire
0ea5dbcfbb libstrat: make build with new ncm/fs api changes (sysmodules probably fail to build) 2023-02-22 17:19:51 -08:00
Michael Scire
bb6446aada erpt: update for new ids 2023-02-22 17:19:51 -08:00
Michael Scire
e46e7e0eb1 boot2: update for 16.0.0 2023-02-22 17:19:51 -08:00
Michael Scire
cb89c66bd8 emummc: update for 16.0.0 2023-02-22 17:19:51 -08:00
Michael Scire
e85a512cf4 fusee/exo: implement the usual changes for new firmware support 2023-02-22 17:19:51 -08:00
Michael Scire
7d9fea01c3 kern: bump supported version to 16.x 2023-02-22 17:19:51 -08:00
Michael Scire
406320f6ec kern: better divide non-secure size, don't waste fatal memory unless necessary 2023-02-22 17:19:51 -08:00
Michael Scire
aad2be0a01 kern: delete creation time field from KProcess 2023-02-22 17:19:51 -08:00
Michael Scire
25383db524 kern: add InfoType_IoRegionHint 2023-02-22 17:19:51 -08:00
Michael Scire
48f4c526f3 kern: refactor priority inheritance to represent locks as C++ objects 2023-02-22 17:19:51 -08:00
Michael Scire
1279d236f3 kern: remove unnecessary interrupt disables from arbiter/condvar 2023-02-22 17:19:51 -08:00
Michael Scire
008eb974d4 kern: KConditionVariable::SignalToAddress now emits dmb before userspace write 2023-02-22 17:19:51 -08:00
Michael Scire
035cebef9d kern: refactor init (kill identity map, merge cpu on logic) 2023-02-22 17:19:51 -08:00
Michael Scire
8db22967bf kern: use variable-count parameter arrays for DebugEvents 2023-02-22 17:19:51 -08:00
Michael Scire
db510f96c3 kern: update KSystemControl::InitializePhase1, dynamically scale 39-bit address space regions 2023-02-22 17:19:51 -08:00
Michael Scire
6e2dd791b2 kern: update for new ChangePermissions page table operation 2023-02-22 17:19:51 -08:00
Michael Scire
bff61c68ab kern: adjust pool allocations 2023-02-22 17:19:51 -08:00
Michael Scire
ca7734ffaf kern: simplify KSchedulerLock::Lock 2023-02-22 17:19:51 -08:00
Michael Scire
ed22f802ee kern: allow QueryIoMapping to find Static mappings 2023-02-22 17:19:51 -08:00
Michael Scire
8ffc177b44 kern: update UnmapIoRegion for new Mapping_Memory handling 2023-02-22 17:19:51 -08:00
Michael Scire
c058376b3b kern: use tree for IoPool regions instead of list 2023-02-22 17:19:51 -08:00
Michael Scire
d5ebf13094 kern: optimize userspace access asm to use cheaper instruction in io memory loops 2023-02-22 17:19:51 -08:00
Michael Scire
695c125721 kern: use different psr masks for 64 and 32-bit El0 threads 2023-02-22 17:19:51 -08:00
Michael Scire
e7e3e7b374 kern: increase stack parameter size by 0x10 2023-02-22 17:19:51 -08:00
Michael Scire
3a5f406c5f kern: update scheduler for new switch count tracking logic 2023-02-21 03:12:17 -07:00
Michael Scire
8176f085f1 gpio: really not sure how this works before, lol 2023-01-30 23:13:45 -07:00
Michael Scire
7a69f2f062 kern/pm: only steal 8 MB from applet.
WebApplet crashes on exit with 16 more MB stolen, apparently.
2023-01-24 19:54:28 -07:00
Michael Scire
32b590e7ab git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "b7711b8fb"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "b7711b8fb"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-01-24 14:39:54 -07:00
Michael Scire
590f22933d docs/ams: bump version to 1.4.1 2023-01-24 14:39:06 -07:00
Michael Scire
0dd071b279 romfs: thank you fire emblem, very cool (closes #2021) 2023-01-24 14:07:50 -07:00
Michael Scire
f1132fbf5a romfs: push clobber fix missed by git add 2023-01-24 14:03:54 -07:00
Michael Scire
9cd57b6c61 romfs: reduce peak allocation sizes by enabling intermediate context frees 2023-01-24 14:02:05 -07:00
0x8ff
bf66e40a7b Update ReSwitched Team URL
reswitched.team is a dead domain no longer owned by the ReSwitched Team
2023-01-20 19:01:33 -08:00
Michael Scire
77cc53227a sdmmc: fix wrong mode select for GcAsic(Fpga)Speed 2023-01-19 21:47:19 -07:00
Michael Scire
59a295db79 sdmmc: fix missing call to GetSdStatus at non-uhsi mode 2023-01-19 21:44:44 -07:00
Michael Scire
e4b9930bf3 kern: fix unnecessarily strong load in aligned spinlock
Copy-paste error I didn't notice for two years, whoops
2022-12-25 01:56:31 -07:00
Michael Scire
04c9004e05 erpt: fix multiple issues with automatic report cleanup (thanks @yellows8)
* Setting retrieval was performed before the call that used the setting.
* Call to detect number of files passed incomplete path and was guaranteed to fail.
* Call to delete reports passed incomplete path and was guaranteed to do nothing.
2022-12-13 01:08:13 -07:00
Michael Scire
1f8798ace7 kern: fix GetProcessId wrong result on invalid parameter 2022-12-04 13:40:44 -07:00
Michael Scire
ff7a80e592 dmnt: allow string termination to end a toggle (closes #1980) 2022-10-28 14:14:38 -07:00
Michael Scire
e3ace4be15 exo: fix MemoryArrange enum typo 2022-10-19 15:18:08 -07:00
Michael Scire
36a33617a4 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "b2232894f"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "b2232894f"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-10-18 11:11:09 -07:00
Michael Scire
8ce4f19615 ncm: update enums, refactor comparison operators 2022-10-18 11:10:17 -07:00
Michael Scire
05fee5d53c fusee: fix 15.x exFAT nogc patch 2022-10-16 15:45:47 -07:00
Michael Scire
f88606fbc1 gdbstub: fix reading module name for homebrew 2022-10-15 15:13:05 -07:00
Michael Scire
e580c3970c git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "363fba0cf"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "363fba0cf"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-10-12 09:16:51 -07:00
Michael Scire
2603136e8b ams: add changelog for 1.4.0 2022-10-12 09:15:16 -07:00
Michael Scire
3d3f8629af loader: update usb3 enable patches for 15.0.0 2022-10-12 09:15:16 -07:00
Michael Scire
d178ea368a lr: new AOC commands use MapAlias for paths... 2022-10-12 09:15:16 -07:00
Michael Scire
b444385762 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "4714b2df9"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "4714b2df9"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-10-12 09:15:16 -07:00
Michael Scire
0c3f1bed33 emummc: update for 15.0.0 2022-10-12 09:15:16 -07:00
Michael Scire
bf4fdf6188 kern: update for new exception flag semantics 2022-10-12 09:15:16 -07:00
Michael Scire
13238fc4fd kern: use slab allocated KSessionRequest dynamic mappings 2022-10-12 09:15:16 -07:00
Michael Scire
e7a1e0fee2 kern: implement Svc(Un)MapInsecureMemory 2022-10-12 09:15:16 -07:00
Michael Scire
5a918f3bc9 kern: move SecureAppletMemory/KPageBuffer heap into the ResourceRegion 2022-10-12 09:15:16 -07:00
Michael Scire
ea82889e6c kern: increase stack region size when thread resource limit is increased 2022-10-12 09:15:16 -07:00
Michael Scire
7f2cbba543 kern: Implement new PageTable operations/PhysicalMemory reference semantics 2022-10-12 09:15:16 -07:00
Michael Scire
5ee7d8a5ed kern: update for new device map semantics 2022-10-12 09:15:16 -07:00
Michael Scire
947fdcf6f6 kern: merge/simplify KInterruptEventTask into KInterruptEvent 2022-10-12 09:15:16 -07:00
Michael Scire
2e73f33eb0 kern: implement K(Secure)SystemResource 2022-10-12 09:15:16 -07:00
Michael Scire
752704a798 kern: update handle table init 2022-10-12 09:15:16 -07:00
Michael Scire
d00406e089 os: update os namespace for 15.0.0, loader/ro: update to use csrng, spl: bump max sessions 2022-10-12 09:15:16 -07:00
Michael Scire
dddb5bfdea boot2: launch new eth sysmodule after bsdsockets 2022-10-12 09:15:16 -07:00
Michael Scire
ed0572bd53 erpt: update IDs for 15.0.0 2022-10-12 09:15:16 -07:00
Michael Scire
b3bbc99cfb ams.mitm: fix up ContentInfo construction 2022-10-12 09:15:16 -07:00
Michael Scire
0ebbbc839f fusee/exo: fix up dram id names/mappings 2022-10-12 09:15:16 -07:00
hexkyz
275c0234cb exo: add new dram ids 2022-10-12 09:15:16 -07:00
Michael Scire
427130a122 ncm: update for new add on content/attr changes 2022-10-12 09:15:16 -07:00
hexkyz
ef07964ea0 fusee: update sdram handling for 15.0.0 2022-10-12 09:15:16 -07:00
Michael Scire
e1aff401ba lr: add support for location resolver disable commands 2022-10-12 09:15:16 -07:00
Michael Scire
05de5538d6 ncm: GetContentAccessibilities, GetContentInfo* 2022-10-12 09:15:16 -07:00
Michael Scire
9929517a83 fusee/exo: enum support for 15.0.0 2022-10-12 09:15:16 -07:00
Michael Scire
545765d167 ams/fuse: update version numbers, update DramId read logic 2022-10-12 09:15:16 -07:00
Michael Scire
8d9e3f2a31 boot: fix ChargerDriver inititalization correctness (thanks @CTCaer) 2022-09-16 15:34:38 -07:00
Michael Scire
28f0940c58 diag: fix process name cache 2022-08-11 14:19:26 -07:00
Michael Scire
d954e85826 fs/emummc: fix DirectoryRedirectionFileSystem not stripping prefix 2022-08-06 08:48:51 -07:00
Michael Scire
7e6b369605 ns.mitm/fs.mitm: allow program specific web override for non-hbl, if present 2022-07-25 16:24:57 -07:00
Liam
e702eab21c KScheduler: fix documentation mistakes 2022-06-29 17:28:26 -07:00
Liam
592b9c66d1 gdbstub: report architecture tag for ARM targets 2022-06-29 17:28:03 -07:00
Michael Scire
8e17feff94 os: pthread_yield is deprecated, don't use it on linux 2022-06-27 15:36:04 -07:00
Michael Scire
6514e365ad gdbstub: fix threads with invalid characters for packets (closes #1904) 2022-06-16 00:11:44 -07:00
Michael Scire
efa4a346af os: silence warning building with gcc 12 on windows 2022-06-12 01:38:04 -07:00
Michael Scire
d75f9bbedf fs: add extension GetEntryList to AesCtrCounterExtendedStorage 2022-06-11 16:54:02 -07:00
Michael Scire
ea7f51a279 os: fix whoops in SetMemoryPermission on windows 2022-06-11 00:58:14 -07:00
Michael Scire
a65b6df8d2 os: implement MemoryHeapManager, SetMemoryAttribute 2022-06-10 22:36:03 -07:00
Michael Scire
4e112de223 dmnt.gen2: fix gt, optimize 2022-06-08 00:49:47 -07:00
Michael Scire
20d200471d kern: optimize postfix-compare to prefix-compare, result logic is identical but breaks earlier in some paths 2022-06-07 23:49:31 -07:00
Michael Scire
5f2d713fe4 kern: mea culpa (some time since 7.x) 2022-06-07 23:40:32 -07:00
Michael Scire
114d2598da dmnt.gen2: sanitize brackets in thread names to be valid xml 2022-06-07 22:03:37 -07:00
Michael Scire
36bdb83cfc util: prevent optimizer from removing endian-swapped writes 2022-06-05 22:57:18 -07:00
Michael Scire
a975689c59 ams: address some warnings when building with gcc-12 2022-06-05 22:57:08 -07:00
Michael Scire
a809e23320 lr: update capacity constants to reflect 12.0.0 changes 2022-05-26 18:44:12 -07:00
Michael Scire
4db485083b strat: update for code changes found in boot (closes #1797) 2022-05-05 17:45:55 -07:00
Michael Scire
e96972c939 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "b91294d3b"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "b91294d3b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-04-29 16:15:06 -07:00
Michael Scire
3545c0aac2 ams: fs accuracy fixes, bump to 1.3.2 2022-04-29 16:14:01 -07:00
Michael Scire
d85875b910 os: fix various regressions since 1.3.1 2022-04-29 15:46:55 -07:00
Michael Scire
b1367942a2 os: fix minor bug (and simplify) MapProcessCodeMemory 2022-04-18 01:43:49 -07:00
Michael Scire
c2c0a2e169 ro/os: use os primitives for MapProcessCodeMemory 2022-04-18 01:39:22 -07:00
Michael Scire
f5052b4bca loader: update for changes in 14.0.0 2022-04-17 20:11:05 -07:00
Michael Scire
70d67bb115 loader: use os apis for interacting with process memory 2022-04-17 18:51:36 -07:00
Michael Scire
9056e0b05f strat: fix linux clang build 2022-04-17 14:01:03 -07:00
Michael Scire
895b6d0470 optional: add c++23 monadic interface 2022-04-17 12:17:25 -07:00
Michael Scire
dfba595cdc fs: fix null check in AesXtsStorageExternal 2022-04-16 12:28:40 -07:00
Michael Scire
175a34da43 os: silence a maybe-uninit warning 2022-04-16 12:28:21 -07:00
Michael Scire
02b126c2be os: refactor multi wait apis to better match Nintendo's latest implementation 2022-04-12 16:47:36 -07:00
Michael Scire
b45671fd35 fs: QueryEntry uses NonSecure buffers 2022-04-08 11:23:39 -07:00
Michael Scire
106599895d fs: fix memory leak when path is reallocated (closes #1842) 2022-04-08 11:02:17 -07:00
Michael Scire
80154b0a54 os: broadcast, not signal, on release more than 1 sema 2022-04-07 12:17:13 -07:00
Michael Scire
62eb4d6989 docs: add changelog for 1.3.1 2022-04-04 17:48:18 -07:00
Michael Scire
b52e44e798 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "590cdaf02"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "590cdaf02"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-04-04 17:47:56 -07:00
Michael Scire
72baa4ff18 ams: add enum recognition for 14.1.0 2022-04-04 17:44:56 -07:00
Michael Scire
442656899f util: update some bit utility logic 2022-04-03 10:51:46 -07:00
Michael Scire
d7f89a0c31 fs: update signature for VerifySign1 2022-04-01 21:06:26 -07:00
Michael Scire
2e6223d9d0 fssystem: add unique lock apis 2022-03-28 14:29:22 -07:00
Michael Scire
28f11a86fd fs: update romfs types 2022-03-28 13:57:06 -07:00
Michael Scire
a8b52dc123 fs: remove dead code 2022-03-28 08:37:08 -07:00
Michael Scire
9b47ddf01f fs: update LocalFileSystem 2022-03-28 01:33:40 -07:00
Michael Scire
0fbf007bcf fs: fixup all OperateRange implementations 2022-03-28 00:54:10 -07:00
Michael Scire
4ad8dad416 os: add DetachIoRegionHandle 2022-03-28 00:00:36 -07:00
Michael Scire
8e258bde9d util: LockFreeAtomicType (for time) 2022-03-27 20:15:10 -07:00
Michael Scire
c0d5140ef0 strat: add windows socket api, linux/macos TODO 2022-03-27 14:36:31 -07:00
Michael Scire
1bef1b58d4 fs: also update comment, for locking 2022-03-26 15:29:38 -07:00
Michael Scire
07cd682460 fs: fix inverted optional-lock condition 2022-03-26 15:28:40 -07:00
Michael Scire
e5c3d264ec fs: implement new 14.0.0 spl-ctr dispatch semantics 2022-03-26 15:21:12 -07:00
Michael Scire
bbf22b4c60 ams: globally prefer R_RETURN to return for ams::Result 2022-03-26 14:48:33 -07:00
Michael Scire
dd78ede99f ams: use R_SUCCEED, R_THROW globally 2022-03-26 00:14:36 -07:00
Michael Scire
e5b1739f65 fatal: yield our lbl session unless needed 2022-03-25 23:47:20 -07:00
Michael Scire
a4a2cc2218 fs: update IStorage::Check functions for 14.0.0 2022-03-25 23:29:36 -07:00
Michael Scire
5ffbed1bee fs: update a few loose missed results 2022-03-25 10:02:55 -07:00
Michael Scire
ec44eaa263 fs: update nca drivers (and dependents/callees) for 14.0.0 changes 2022-03-25 09:48:24 -07:00
Michael Scire
20e53fcd82 fs: update HashGeneratorFactorySelector to reflect 14.0.0 2022-03-24 21:57:37 -07:00
SciresM
64c6ef2de7 fs: reduce path size 0x28 -> 0x18
This implements two optimizations on fs::Path, which N added in 12.0.0.

The current structure looks like: 

```cpp
struct Path {
    const char *m_str; // Points to the read-only path string
    char *m_write_buffer_buffer; // Part of std::unique_ptr<char[], ams::fs::impl::Deleter>
    ams::fs::impl::Deleter m_write_buffer_deleter; // Parse of std::unique_ptr<char[], ams::fs::impl::Deleter>, stores the size of the buffer.
    size_t m_write_buffer_length; // Copy of the write buffer's size accessible to the Path() structure.
    bool m_is_normalized; // Whether the path buffer is normalized
};
```

This is pretty wasteful. The write buffer size is stored twice, wasting 8 bytes, because one copy of the size isn't accessible to the path.

In addition, due to alignment, the bool wastes 7 padding bytes.

This commit:

* Encodes normalized in the low bit of the write buffer length, saving 8 bytes.
* Use a custom WriteBuffer class rather than generic unique_ptr, to avoid needing to store the WriteBuffer twice.


These each save 8 bytes, for a final size of 0x18 rather than 0x28.
2022-03-24 20:22:47 -07:00
Michael Scire
817ad8f98d util: pointer traits only if <memory>/stratosphere 2022-03-24 18:24:19 -07:00
Michael Scire
dfa475a769 util: add pointer utils, use to constrain fs pointers 2022-03-24 16:21:03 -07:00
Michael Scire
141ae5c7ab fs: fix removed include 2022-03-24 13:31:49 -07:00
Michael Scire
4646581e93 fs: for my sanity, begin tracking version where code was last checked for accuracy 2022-03-24 08:43:40 -07:00
Michael Scire
b69fa13576 fatal: fix usage of removed bpc api in 14.0.0 2022-03-23 19:11:37 -07:00
Michael Scire
0da15a30fd git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "726a7efdd"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "726a7efdd"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-03-23 13:45:59 -07:00
Michael Scire
44d553d12e loader: add usb-3 patch for 14.0.0 2022-03-23 13:45:28 -07:00
Michael Scire
6f54ab5716 fs: fix out of bounds access when parsing directory paths 2022-03-23 13:38:34 -07:00
Michael Scire
596a0f2551 ams.mitm: wrong stack was increased 2022-03-23 11:51:16 -07:00
Michael Scire
ff828dc0bc ams.mitm: increase sysupdater stack size (as needed by new ncm code) 2022-03-23 11:37:30 -07:00
Michael Scire
027f3b4911 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "af48924e5"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "af48924e5"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-03-23 11:25:46 -07:00
Michael Scire
3fff114b14 crypto: fix aes-128 dec on arm64/cortex-a57 2022-03-23 11:24:43 -07:00
Michael Scire
f23f490cb4 strat: fix clang build 2022-03-23 10:39:20 -07:00
Michael Scire
c503629ac8 ams.mitm: fix reboot to payload 2022-03-23 10:17:00 -07:00
Michael Scire
6b436739be git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "56a2e8a20"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "56a2e8a20"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-03-23 09:22:50 -07:00
Michael Scire
4f763b2aa4 emummc: integrate updates for 14.0.0 2022-03-23 09:22:22 -07:00
Michael Scire
12d83106fd git subrepo clone --branch=develop https://github.com/m4xw/emummc emummc
subrepo:
  subdir:   "emummc"
  merged:   "a9d569594"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "a9d569594"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-03-23 09:20:54 -07:00
Michael Scire
e3cb5e74b9 emummc: temp delete 2022-03-23 09:20:31 -07:00
Michael Scire
b1a4a0db67 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "d97cdde1a"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "d97cdde1a"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-03-23 09:17:52 -07:00
Michael Scire
847fee4901 docs: fix changelog, some 2022-03-23 09:13:47 -07:00
Michael Scire
f2b48d466f docs: add basic changelog for 1.3.0 2022-03-23 09:10:50 -07:00
Michael Scire
6e97dff27f exo: fix typo causing mishandling of carveouts 2022-03-23 09:10:50 -07:00
Michael Scire
be399772c0 emummc: add 14.0.0 patches 2022-03-23 09:10:50 -07:00
Michael Scire
45da60f902 kern: turns out changing base address gives pretty elfs but breaks relocs 2022-03-23 09:10:50 -07:00
Michael Scire
01fd324d4f os/dd: add missing semicolon to new cache logic 2022-03-23 09:10:50 -07:00
Michael Scire
f95bdb87a0 exo: right, Mariko* is a wiki-ism 2022-03-23 09:10:50 -07:00
Michael Scire
91d3d242f5 exo: update for new dram ids 2022-03-23 09:10:50 -07:00
Michael Scire
383fc2cc99 kern: codegen tweaks, now that we're no longer -Os 2022-03-23 09:10:50 -07:00
Michael Scire
1ca2f61527 kern: good night sweet prince 2022-03-23 09:10:50 -07:00
Michael Scire
cdc619a8a6 kern: on second thought, gcc built ins are for chumps 2022-03-23 09:10:50 -07:00
Michael Scire
ff07ba4201 kern: implement revised IPI/SGI semantics 2022-03-23 09:10:50 -07:00
Michael Scire
9d89835ff8 kern: update for new hw maintenance semantics 2022-03-23 09:10:50 -07:00
Michael Scire
6e17317d5d kern: implement new thread context/fpu semantics 2022-03-23 09:10:50 -07:00
hexkyz
79afa3b64c fusee: add unused mtc table 2022-03-23 09:10:50 -07:00
hexkyz
f3968f5f7c fusee: add new sdram params 2022-03-23 09:10:50 -07:00
hexkyz
a8e23adffe fusee: add new mtc tables 2022-03-23 09:10:50 -07:00
Michael Scire
401047f603 kern: implement additional randomness in KPageHeap allocations 2022-03-23 09:10:50 -07:00
Michael Scire
24739f245e kern: enforce end of dram == end of partitions (move our probably outdated KTraceBuffer to new location) 2022-03-23 09:10:50 -07:00
Michael Scire
8cb3cfd835 kern: add new KCapability checks before creating process 2022-03-23 09:10:50 -07:00
Michael Scire
14e768cd10 kern: add InfoType_IsSvcPermitted 2022-03-23 09:10:50 -07:00
Michael Scire
ef1b67b87b kern: enforce maximum secure region size 2022-03-23 09:10:50 -07:00
Michael Scire
8ef6c49d30 kern: print kernel backtrace on panic 2022-03-23 09:10:50 -07:00
Michael Scire
a89c5dd5d7 ncm: hot take, uninitialized data bad 2022-03-23 09:10:50 -07:00
Michael Scire
dfcb5005d2 fs/sprof/build: fix minor issues 2022-03-23 09:10:50 -07:00
Michael Scire
f3e3649bd5 pm: grant access to GetResourceLimitPeakValue 2022-03-23 09:10:50 -07:00
Michael Scire
07f91f0a83 boot2: launch omm before am 2022-03-23 09:10:50 -07:00
Michael Scire
81005fa3f8 pgl: style nitpick 2022-03-23 09:10:50 -07:00
Michael Scire
60d78bbf75 pgl: hook up logic for enabling extra system threads 2022-03-23 09:10:50 -07:00
Michael Scire
247852db3a pm: hook up the new libnx apis 2022-03-23 09:10:50 -07:00
Michael Scire
51c145f6c9 fusee: update static_assert on key generation 2022-03-23 09:10:50 -07:00
Michael Scire
74fddf667a pm: loosen restriction on resource limit boost 2022-03-23 09:10:50 -07:00
Michael Scire
027242e909 erpt: update id map 2022-03-23 09:10:50 -07:00
Michael Scire
86f98e49c7 sf: add another sanity assert 2022-03-23 09:10:50 -07:00
Michael Scire
3579797309 sf: add new debug-interface-id in cmif out header 2022-03-23 09:10:50 -07:00
Michael Scire
77b3bfcd16 sprofile: fix/simplify import count calculation 2022-03-23 09:10:50 -07:00
Michael Scire
fa98bf9434 libstrat: misc fixes for unused arg warnings 2022-03-23 09:10:50 -07:00
Michael Scire
e975784179 fatal: update for new 14.0.0 command 2022-03-23 09:10:50 -07:00
Michael Scire
dc643daaa7 kern: update version (note: actual 14-kernel diff/impl todo) 2022-03-23 09:10:50 -07:00
Michael Scire
e05df99342 pm/kern: update for 14.0.0 2022-03-23 09:10:50 -07:00
Michael Scire
0cfc93d423 sprofile: update for 14.0.0 (orphaned profiles now deleted on import) 2022-03-23 09:10:50 -07:00
Michael Scire
588d761615 exo/fusee: first pass at updating enums for 14.0.0 2022-03-23 09:10:50 -07:00
1006 changed files with 23433 additions and 9302 deletions

View File

@@ -38,7 +38,7 @@ In no particular order, we credit the following for their invaluable contributio
* __switchbrew__ for the [libnx](https://github.com/switchbrew/libnx) project and the extensive [documentation, research and tool development](http://switchbrew.org) pertaining to the Nintendo Switch. * __switchbrew__ for the [libnx](https://github.com/switchbrew/libnx) project and the extensive [documentation, research and tool development](http://switchbrew.org) pertaining to the Nintendo Switch.
* __devkitPro__ for the [devkitA64](https://devkitpro.org/) toolchain and libnx support. * __devkitPro__ for the [devkitA64](https://devkitpro.org/) toolchain and libnx support.
* __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.team/) pertaining to the Nintendo Switch. * __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.github.io/) pertaining to the Nintendo Switch.
* __ChaN__ for the [FatFs](http://elm-chan.org/fsw/ff/00index_e.html) module. * __ChaN__ for the [FatFs](http://elm-chan.org/fsw/ff/00index_e.html) module.
* __Marcus Geelnard__ for the [bcl-1.2.0](https://sourceforge.net/projects/bcl/files/bcl/bcl-1.2.0) library. * __Marcus Geelnard__ for the [bcl-1.2.0](https://sourceforge.net/projects/bcl/files/bcl/bcl-1.2.0) library.
* __naehrwert__ and __st4rk__ for the original [hekate](https://github.com/nwert/hekate) project and its hwinit code base. * __naehrwert__ and __st4rk__ for the original [hekate](https://github.com/nwert/hekate) project and its hwinit code base.

View File

@@ -51,6 +51,8 @@ dist: dist-no-debug
cp $(CURRENT_DIRECTORY)/stratosphere/spl/$(ATMOSPHERE_OUT_DIR)/spl.elf $(DIST_DIR)/spl.elf cp $(CURRENT_DIRECTORY)/stratosphere/spl/$(ATMOSPHERE_OUT_DIR)/spl.elf $(DIST_DIR)/spl.elf
cp $(CURRENT_DIRECTORY)/stratosphere/TioServer/$(ATMOSPHERE_OUT_DIR)/TioServer.elf $(DIST_DIR)/TioServer.elf cp $(CURRENT_DIRECTORY)/stratosphere/TioServer/$(ATMOSPHERE_OUT_DIR)/TioServer.elf $(DIST_DIR)/TioServer.elf
cp $(CURRENT_DIRECTORY)/troposphere/daybreak/daybreak.elf $(DIST_DIR)/daybreak.elf cp $(CURRENT_DIRECTORY)/troposphere/daybreak/daybreak.elf $(DIST_DIR)/daybreak.elf
cp $(CURRENT_DIRECTORY)/troposphere/haze/haze.elf $(DIST_DIR)/haze.elf
cp $(CURRENT_DIRECTORY)/troposphere/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 -r ../atmosphere-$(ATMOSPHERE_VERSION)-debug.zip ./*; cd ../;
rm -rf $(DIST_DIR) rm -rf $(DIST_DIR)
@@ -106,6 +108,7 @@ dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
rm -r $(DIST_DIR)/stratosphere_romfs rm -r $(DIST_DIR)/stratosphere_romfs
cp troposphere/reboot_to_payload/reboot_to_payload.nro $(DIST_DIR)/switch/reboot_to_payload.nro cp troposphere/reboot_to_payload/reboot_to_payload.nro $(DIST_DIR)/switch/reboot_to_payload.nro
cp troposphere/daybreak/daybreak.nro $(DIST_DIR)/switch/daybreak.nro cp troposphere/daybreak/daybreak.nro $(DIST_DIR)/switch/daybreak.nro
cp troposphere/haze/haze.nro $(DIST_DIR)/switch/haze.nro
cd $(DIST_DIR); zip -r ../atmosphere-$(ATMOSPHERE_VERSION).zip ./*; cd ../; cd $(DIST_DIR); zip -r ../atmosphere-$(ATMOSPHERE_VERSION).zip ./*; cd ../;
rm -rf $(DIST_DIR) rm -rf $(DIST_DIR)
cp fusee/$(ATMOSPHERE_BOOT_OUT_DIR)/fusee.bin $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)/fusee.bin cp fusee/$(ATMOSPHERE_BOOT_OUT_DIR)/fusee.bin $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)/fusee.bin

View File

@@ -67,6 +67,10 @@
; Note that this setting is ignored (and treated as 1) when htc is enabled. ; Note that this setting is ignored (and treated as 1) when htc is enabled.
; 0 = Disabled, 1 = Enabled ; 0 = Disabled, 1 = Enabled
; enable_log_manager = u8!0x0 ; enable_log_manager = u8!0x0
; Controls whether the bluetooth pairing database is redirected to the SD card (shared across sysmmc/all emummcs)
; NOTE: On <13.0.0, the database size was 10 instead of 20; booting pre-13.0.0 will truncate the database.
; 0 = Disabled, 1 = Enabled
; enable_external_bluetooth_db = u8!0x0
[hbloader] [hbloader]
; Controls the size of the homebrew heap when running as applet. ; Controls the size of the homebrew heap when running as applet.
; If set to zero, all available applet memory is used as heap. ; If set to zero, all available applet memory is used as heap.

View File

@@ -1,4 +1,101 @@
# Changelog # Changelog
## 1.5.5
+ Support was added for 16.1.0.
+ General system stability improvements to enhance the user's experience.
## 1.5.4
+ Experimental new functionality was implemented to prevent crashing when building romfs for certain games with obscene file counts.
+ This includes both Fire Emblem: Engage (~190000 files), and The Legend of Zelda: Tears of the Kingdom (~300000) files.
+ The solution involved adding functionality to ams.mitm/pm to dynamically steal memory from the application (and system) pool as needed when the games have romfs mods.
+ No memory is taken, and there is no cost to this functionality when playing without mods (or with overrides disabled).
+ The Legend of Zelda: Tears of the Kingdom is currently the absolute worst case game, requiring ~48 MB of memory to build a romfs image to play with mods.
+ Right now, the memory is sourced as follows: 32 MB (base ams.mitm heap), 10 MB (stolen from application pool), 8 MB (dynamically stolen from system pool).
+ This is 50 MB, which allows a little overhead in the worst case (prevents crashing due to exhausting the heap for other allocations in ams.mitm).
+ Zelda is remarkably sensitive to memory being stolen from the application pool, tolerating no more than 16 MB on 1.0.0 and 12 MB on 1.1.0. I have chosen to steal 10 MB, to be safe, for now.
+ This may break on a future game update, but I will fix it if and when that happens. There is no perfect solution; the game simply requires too much memory to support mods flawlessly, and I am forced to compromise.
+ As usual, if you encounter a game that exhausts ams.mitm's memory (crashing it) when loading layeredfs mods, please contact `SciresM#0524`.
"I am jinxing myself by saying this, but it's really hard to imagine any game being worse than The Legend of Zelda: Tears of the Kingdom, but if it happens again I will drop everything to fix it as usual".
+ General system stability improvements to enhance the user's experience.
## 1.5.3
+ Support was added for 16.0.3.
+ Atmosphère was updated to use GCC 13/newlib (latest devkitA64/devkitARM releases).
+ **Please note**: This introduces a known issue, which is currently being worked on.
+ As you may recall from the 1.4.1 changelog, Fire Emblem: Engage requires enormous amounts of memory to support using layeredfs mods with the game.
+ Latest GCC/newlib slightly increases malloc overhead size, which makes the previous memory increase insufficient.
+ A general-case solution to this is in the works, which should hopefully fix the problem in a way that doesn't jinx me for the future.
+ A number of minor issues were fixed and improvements were made, including:
+ An issue was fixed that caused system font replacement to not work on 16.0.0+.
+ An minor accuracy issue was addressed in mesosphere's management of certain memory ranges; this issue would have had zero visible impact to the end-user.
+ General system stability improvements to enhance the user's experience.
## 1.5.2
+ A homebrew application (`haze`) was added for performing USB file transfer (with thanks to @liamwhite for both design and implementation).
+ `haze` is included with atmosphère, and provides access to the SD card via the PTP/MTP protocol.
+ **Please note**: haze will show inside the homebrew menu under the name "USB File Transfer".
+ **Please note**: Atmosphère cannot be updated at runtime, and trying to install an atmosphère update via haze will fail as usual.
+ General system stability improvements to enhance the user's experience.
## 1.5.1
+ `fatal` was updated to reduce memory footprint.
+ Starting in 16.0.0, official `fatal` has no framebuffer or rendering logic, and instead calls other system service commands to draw the screen.
+ However, these commands aren't usable by atmosphère (too small rendering window, bad color support).
+ To reduce the relative memory footprint differential between atmosphère and official code, the framebuffer (2 MB) is now dynamically allocated when needed.
+ This will try to allocate from multiple pools (preferring System > System_NonSecure > Application).
+ This technically requires that 2 MB be available in at least one of these pools for the fatal screen to render (otherwise, a reboot-to-black-and-white-fatal will occur), but this should be a non-issue in almost all cases.
+ A feature was added to optionally mirror the bluetooth pairing database to the SD card (thanks @ndeadly).
+ This allows device pairings to be automatically kept in-sync across sysmmc/all emummcs.
+ This is opt-in, and can be controlled by setting `atmosphere!enable_external_bluetooth_db = u8!0x1`.
+ When enabled, the pairing database will be synchronized to `/atmosphere/bluetooth_devices.db`.
+ General system stability improvements to enhance the user's experience.
## 1.5.0
+ Support was added for 16.0.0
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `ncm` was updated to reflect the latest official behavior.
+ Many FS apis were updated under the hood to reflect the latest official behavior.
+ **Please Note**: 16.0.0 made breaking changes to a number of system APIs, including in FS/NCM/Shared Font commands that some homebrew programs may use.
+ These programs may encounter strange errors, and may need to be recompiled with a libnx updated to support 16.0.0's changes to function properly.
+ A number of minor issues were fixed and improvements were made, including:
+ An issue was fixed that could cause GPIO outputs to be misconfigured under certain circumstances.
+ General system stability improvements to enhance the user's experience.
## 1.4.1
+ A number of minor issues were fixed and improvements were made, including:
+ `dmnt` cheat toggle files are no longer ignored when they are missing a trailing newline.
+ The mechanism for automatically cleaning up `erpt_reports` added in 1.3.0 was fixed.
+ This was actually just very fundamentally broken and has never worked, but it is verified working now.
+ Minor fixes were made in `mesosphère` to match official kernel behavior (spin lock assembly was corrected, wrong result on failure in in GetProcessId was corrected).
+ A missing call to GetSdStatus when initializing SD cards at non uhs-i mode was added in the sdmmc driver.
+ `ams.mitm`'s memory usage was increased by 16 MB, to prevent crashing when building romfs for games with obscene file counts.
+ To quote the changelog for 1.2.3: "Animal Crossing's 2.0.0 update contains >99000 files [...] It's really hard to imagine any game being worse than Animal Crossing".
+ As it turns out, Fire Emblem: Engage has ~186000 files, and is approximately twice as bad as animal crossing.
+ The additional memory here is taken from the applet pool; no issues are expected to arise from this, but please report anything you may run into.
+ As usual, if you encounter a game that exhausts ams.mitm's memory (crashing it) when loading layeredfs mods, please contact `SciresM#0524`.
+ I am jinxing myself by saying this, but it's really hard to imagine any game being worse than Fire Emblem: Engage, but if it happens again I will drop everything to fix it as usual.
+ General system stability improvements to enhance the user's experience.
## 1.4.0
+ Support was added for 15.0.0.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `ncm` was updated to reflect the latest official behavior.
+ A number of minor issues were fixed and improvements were made, including:
+ The capacity limit on registered add-on contents was fixed in NCM to reflect the increase that occurred in 12.0.0.
+ An off-by-one was fixed in mesosphere when computing the new value for an address arbiter signaled with ModifyByWaitingCountIfEqual.
+ dmnt.gen2's gdbstub now sanitizes thread names to prevent invalid characters from breaking gdb.
+ dmnt.gen2's gdbstub now reports the architecture tag correctly when attached to 32-bit processes.
+ Support for program-specific html manual content overrides was added for non-hbl takeover context.
+ A bug was fixed in how emummc constructed the alternate Nintendo directory path.
+ Previously, this was using `/*/Nintendo/Nintendo` instead of `/*/Nintendo`.
+ Code was added to automatically move the old folders to the new ones when booting into emummc.
+ A bug was fixed in boot that caused an incorrectly low input voltage limit to be set.
+ General system stability improvements to enhance the user's experience.
## 1.3.2
+ Support was improved for 14.0.0+.
+ `loader` was updated to reflect the latest official behaviors.
+ `ro` was updated to reflect the latest official behaviors.
+ A number of minor issues were fixed and improvements were made, including:
+ A memory leak was fixed in filesystem path management; this could cause a crash when launching games ~100 times, or when deleting/re-downloading games.
+ A bug was fixed that could cause threads to not see a newly signaled semaphore.
+ A number of minor inaccuracies were fixed in the updated FileSystem APIs.
+ General system stability improvements to enhance the user's experience.
## 1.3.1
+ Support was added for 14.1.0.
+ A number of minor under the hood improvements to accuracy were made to better reflect latest official system module behavior, particularly around FS apis.
+ General system stability improvements to enhance the user's experience.
## 1.3.0 ## 1.3.0
+ Support was added for 14.0.0. + Support was added for 14.0.0.
+ `mesosphère` was updated to reflect the latest official kernel behavior. + `mesosphère` was updated to reflect the latest official kernel behavior.
@@ -15,9 +112,10 @@
+ If you are a developer interested in adding support for another target, please reach out to `SciresM#0524` on discord. + If you are a developer interested in adding support for another target, please reach out to `SciresM#0524` on discord.
+ This is intended to finally allow sanely testing Atmosphère's code, by allowing most of it to run on a PC (with access to a debugger) instead of on game console hardware. + This is intended to finally allow sanely testing Atmosphère's code, by allowing most of it to run on a PC (with access to a debugger) instead of on game console hardware.
+ In addition, this will allow making PC tools which reuse code written for Atmosphère directly.. + In addition, this will allow making PC tools which reuse code written for Atmosphère directly..
+ **Please Note**: This has no relation to interacting with official software on PC whatsoever. This does not and is not intended to enable anything with official software, it only really allows for making tests and self-contained atmosphère-based tools. + **Please Note**: This has no relation to interacting with official software on PC whatsoever. This really allows for making tests and self-contained atmosphère-based command-line tools; the Atmosphère project continues to have zero interest in attempting to run official software of any kind.
+ In the course of adding this support (and working on tooling using it), a number of major revisions were added to stratosphere: + In the course of adding this support (and working on tooling using it), a number of fairly major revisions were made to stratosphere (particularly surrounding filesystem code).
+ + **Please Note**: A number of changes made for this (and ones necessary in the process of adding support for 14.0.0) are api-breaking.
+ If you're a developer and any of this caused your code to break, please feel free to contact `SciresM#0524` for help updating your program.
+ General system stability improvements to enhance the user's experience. + General system stability improvements to enhance the user's experience.
## 1.2.6 ## 1.2.6
+ Support was added for 13.2.1. + Support was added for 13.2.1.

18
docs/faq.md Normal file
View File

@@ -0,0 +1,18 @@
# Frequently Asked Questions
This document serves as a place to store answers for common questions received about Atmosphère.
## What does "June 15th" mean?
When Atmosphère began development in February 2018, "June 15" was given as the estimate/target date for a first release, to coincide with the planned disclosure of a vulnerability.
This deadline was missed, hard.
People made rather a lot of fun of me (SciresM) for this.
Several months later, when the first Atmosphère release occurred, I captioned it "Happy June 15th!" and pretended like I hadn't missed the first deadline.
This amused me a lot, and so the practice has been kept up for every single release since.
Depending on who you ask, you may be told that this is a dumb joke and it is not funny.
This is incorrect. It is definitely a dumb joke, but it is also hilarious.

View File

@@ -27,3 +27,6 @@ A list of planned features for Atmosphère can be found [here](roadmap.md).
## Release History ## Release History
A changelog of previous versions of Atmosphère can be found [here](changelog.md). A changelog of previous versions of Atmosphère can be found [here](changelog.md).
## Frequently Asked Questions
Answers to one or more frequently asked questions may be found [here](faq.md).

6
emummc/.gitrepo vendored
View File

@@ -4,9 +4,9 @@
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme ; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
; ;
[subrepo] [subrepo]
remote = https://github.com/m4xw/emuMMC remote = https://github.com/m4xw/emummc
branch = develop branch = develop
commit = a9d56959460fc794ce2cb6405402c25a3e89c47f commit = 30205111ee375bef96f0f76cb6a3130a2f0fc85c
parent = ff719641396c635b735873fb2b020c910f768a04 parent = 81e9154a52a976f85317bddd0131426599d26a62
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.1

2
emummc/README.md vendored
View File

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

View File

@@ -61,6 +61,12 @@
#include "offsets/1310_exfat.h" #include "offsets/1310_exfat.h"
#include "offsets/1400.h" #include "offsets/1400.h"
#include "offsets/1400_exfat.h" #include "offsets/1400_exfat.h"
#include "offsets/1500.h"
#include "offsets/1500_exfat.h"
#include "offsets/1600.h"
#include "offsets/1600_exfat.h"
#include "offsets/1603.h"
#include "offsets/1603_exfat.h"
#include "../utils/fatal.h" #include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers #define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -133,6 +139,12 @@ DEFINE_OFFSET_STRUCT(_1310);
DEFINE_OFFSET_STRUCT(_1310_EXFAT); DEFINE_OFFSET_STRUCT(_1310_EXFAT);
DEFINE_OFFSET_STRUCT(_1400); DEFINE_OFFSET_STRUCT(_1400);
DEFINE_OFFSET_STRUCT(_1400_EXFAT); DEFINE_OFFSET_STRUCT(_1400_EXFAT);
DEFINE_OFFSET_STRUCT(_1500);
DEFINE_OFFSET_STRUCT(_1500_EXFAT);
DEFINE_OFFSET_STRUCT(_1600);
DEFINE_OFFSET_STRUCT(_1600_EXFAT);
DEFINE_OFFSET_STRUCT(_1603);
DEFINE_OFFSET_STRUCT(_1603_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) { const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) { switch (version) {
@@ -226,6 +238,18 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_1400)); return &(GET_OFFSET_STRUCT_NAME(_1400));
case FS_VER_14_0_0_EXFAT: case FS_VER_14_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1400_EXFAT)); return &(GET_OFFSET_STRUCT_NAME(_1400_EXFAT));
case FS_VER_15_0_0:
return &(GET_OFFSET_STRUCT_NAME(_1500));
case FS_VER_15_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1500_EXFAT));
case FS_VER_16_0_0:
return &(GET_OFFSET_STRUCT_NAME(_1600));
case FS_VER_16_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1600_EXFAT));
case FS_VER_16_0_3:
return &(GET_OFFSET_STRUCT_NAME(_1603));
case FS_VER_16_0_3_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1603_EXFAT));
default: default:
fatal_abort(Fatal_UnknownVersion); fatal_abort(Fatal_UnknownVersion);
} }

View File

@@ -89,6 +89,15 @@ enum FS_VER
FS_VER_14_0_0, FS_VER_14_0_0,
FS_VER_14_0_0_EXFAT, FS_VER_14_0_0_EXFAT,
FS_VER_15_0_0,
FS_VER_15_0_0_EXFAT,
FS_VER_16_0_0,
FS_VER_16_0_0_EXFAT,
FS_VER_16_0_3,
FS_VER_16_0_3_EXFAT,
FS_VER_MAX, FS_VER_MAX,
}; };

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

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1500_H__
#define __FS_1500_H__
// Accessor vtable getters
#define FS_OFFSET_1500_SDMMC_ACCESSOR_GC 0x183E20
#define FS_OFFSET_1500_SDMMC_ACCESSOR_SD 0x185AA0
#define FS_OFFSET_1500_SDMMC_ACCESSOR_NAND 0x1842E0
// Hooks
#define FS_OFFSET_1500_SDMMC_WRAPPER_READ 0x17FCF0
#define FS_OFFSET_1500_SDMMC_WRAPPER_WRITE 0x17FD50
#define FS_OFFSET_1500_RTLD 0x26518
#define FS_OFFSET_1500_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1500_CLKRST_SET_MIN_V_CLK_RATE 0x1A0870
// Misc funcs
#define FS_OFFSET_1500_LOCK_MUTEX 0x1791A0
#define FS_OFFSET_1500_UNLOCK_MUTEX 0x1791F0
#define FS_OFFSET_1500_SDMMC_WRAPPER_CONTROLLER_OPEN 0x17FCB0
#define FS_OFFSET_1500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x17FCD0
// Misc Data
#define FS_OFFSET_1500_SD_MUTEX 0xFF33F0
#define FS_OFFSET_1500_NAND_MUTEX 0xFEE2E8
#define FS_OFFSET_1500_ACTIVE_PARTITION 0xFEE328
#define FS_OFFSET_1500_SDMMC_DAS_HANDLE 0xFD38D8
// NOPs
#define FS_OFFSET_1500_SD_DAS_INIT 0x25454
// Nintendo Paths
#define FS_OFFSET_1500_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063050, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0006FDE8, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000768D4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x00089364, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1500_H__

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

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1500_EXFAT_H__
#define __FS_1500_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1500_EXFAT_SDMMC_ACCESSOR_GC 0x18EDB0
#define FS_OFFSET_1500_EXFAT_SDMMC_ACCESSOR_SD 0x190A30
#define FS_OFFSET_1500_EXFAT_SDMMC_ACCESSOR_NAND 0x18F270
// Hooks
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_READ 0x18AC80
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_WRITE 0x18ACE0
#define FS_OFFSET_1500_EXFAT_RTLD 0x26518
#define FS_OFFSET_1500_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1500_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1AB800
// Misc funcs
#define FS_OFFSET_1500_EXFAT_LOCK_MUTEX 0x184130
#define FS_OFFSET_1500_EXFAT_UNLOCK_MUTEX 0x184180
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x18AC40
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x18AC60
// Misc Data
#define FS_OFFSET_1500_EXFAT_SD_MUTEX 0x10053F0
#define FS_OFFSET_1500_EXFAT_NAND_MUTEX 0x10002E8
#define FS_OFFSET_1500_EXFAT_ACTIVE_PARTITION 0x1000328
#define FS_OFFSET_1500_EXFAT_SDMMC_DAS_HANDLE 0xFE08D8
// NOPs
#define FS_OFFSET_1500_EXFAT_SD_DAS_INIT 0x25454
// Nintendo Paths
#define FS_OFFSET_1500_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063050, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0006FDE8, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000768D4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x00089364, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1500_EXFAT_H__

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

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1600_H__
#define __FS_1600_H__
// Accessor vtable getters
#define FS_OFFSET_1600_SDMMC_ACCESSOR_GC 0x1862A0
#define FS_OFFSET_1600_SDMMC_ACCESSOR_SD 0x187F20
#define FS_OFFSET_1600_SDMMC_ACCESSOR_NAND 0x186760
// Hooks
#define FS_OFFSET_1600_SDMMC_WRAPPER_READ 0x1821F0
#define FS_OFFSET_1600_SDMMC_WRAPPER_WRITE 0x182250
#define FS_OFFSET_1600_RTLD 0x269B0
#define FS_OFFSET_1600_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1600_CLKRST_SET_MIN_V_CLK_RATE 0x1A2D30
// Misc funcs
#define FS_OFFSET_1600_LOCK_MUTEX 0x17B730
#define FS_OFFSET_1600_UNLOCK_MUTEX 0x17B780
#define FS_OFFSET_1600_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1821B0
#define FS_OFFSET_1600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1821D0
// Misc Data
#define FS_OFFSET_1600_SD_MUTEX 0xFFB3F0
#define FS_OFFSET_1600_NAND_MUTEX 0xFF6B58
#define FS_OFFSET_1600_ACTIVE_PARTITION 0xFF6B98
#define FS_OFFSET_1600_SDMMC_DAS_HANDLE 0xFDC8B0
// NOPs
#define FS_OFFSET_1600_SD_DAS_INIT 0x258D4
// Nintendo Paths
#define FS_OFFSET_1600_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063B48, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070D6C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007790C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A754, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1600_H__

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

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1600_EXFAT_H__
#define __FS_1600_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1600_EXFAT_SDMMC_ACCESSOR_GC 0x190F80
#define FS_OFFSET_1600_EXFAT_SDMMC_ACCESSOR_SD 0x192C00
#define FS_OFFSET_1600_EXFAT_SDMMC_ACCESSOR_NAND 0x191440
// Hooks
#define FS_OFFSET_1600_EXFAT_SDMMC_WRAPPER_READ 0x18CED0
#define FS_OFFSET_1600_EXFAT_SDMMC_WRAPPER_WRITE 0x18CF30
#define FS_OFFSET_1600_EXFAT_RTLD 0x269B0
#define FS_OFFSET_1600_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1600_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1ADA10
// Misc funcs
#define FS_OFFSET_1600_EXFAT_LOCK_MUTEX 0x186410
#define FS_OFFSET_1600_EXFAT_UNLOCK_MUTEX 0x186460
#define FS_OFFSET_1600_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x18CE90
#define FS_OFFSET_1600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x18CEB0
// Misc Data
#define FS_OFFSET_1600_EXFAT_SD_MUTEX 0x100D3F0
#define FS_OFFSET_1600_EXFAT_NAND_MUTEX 0x1008B58
#define FS_OFFSET_1600_EXFAT_ACTIVE_PARTITION 0x1008B98
#define FS_OFFSET_1600_EXFAT_SDMMC_DAS_HANDLE 0xFE98B0
// NOPs
#define FS_OFFSET_1600_EXFAT_SD_DAS_INIT 0x258D4
// Nintendo Paths
#define FS_OFFSET_1600_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063B48, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070D6C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007790C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A754, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1600_EXFAT_H__

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

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1603_H__
#define __FS_1603_H__
// Accessor vtable getters
#define FS_OFFSET_1603_SDMMC_ACCESSOR_GC 0x1862F0
#define FS_OFFSET_1603_SDMMC_ACCESSOR_SD 0x187F70
#define FS_OFFSET_1603_SDMMC_ACCESSOR_NAND 0x1867B0
// Hooks
#define FS_OFFSET_1603_SDMMC_WRAPPER_READ 0x182240
#define FS_OFFSET_1603_SDMMC_WRAPPER_WRITE 0x1822A0
#define FS_OFFSET_1603_RTLD 0x269B0
#define FS_OFFSET_1603_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1603_CLKRST_SET_MIN_V_CLK_RATE 0x1A2D80
// Misc funcs
#define FS_OFFSET_1603_LOCK_MUTEX 0x17B780
#define FS_OFFSET_1603_UNLOCK_MUTEX 0x17B7D0
#define FS_OFFSET_1603_SDMMC_WRAPPER_CONTROLLER_OPEN 0x182200
#define FS_OFFSET_1603_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x182220
// Misc Data
#define FS_OFFSET_1603_SD_MUTEX 0xFFB3F0
#define FS_OFFSET_1603_NAND_MUTEX 0xFF6B58
#define FS_OFFSET_1603_ACTIVE_PARTITION 0xFF6B98
#define FS_OFFSET_1603_SDMMC_DAS_HANDLE 0xFDC8B0
// NOPs
#define FS_OFFSET_1603_SD_DAS_INIT 0x258D4
// Nintendo Paths
#define FS_OFFSET_1603_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063B98, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070DBC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007795C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A7A4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1603_H__

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

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1603_EXFAT_H__
#define __FS_1603_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1603_EXFAT_SDMMC_ACCESSOR_GC 0x190FD0
#define FS_OFFSET_1603_EXFAT_SDMMC_ACCESSOR_SD 0x192C50
#define FS_OFFSET_1603_EXFAT_SDMMC_ACCESSOR_NAND 0x191490
// Hooks
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_READ 0x18CF20
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_WRITE 0x18CF80
#define FS_OFFSET_1603_EXFAT_RTLD 0x269B0
#define FS_OFFSET_1603_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1603_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1ADA60
// Misc funcs
#define FS_OFFSET_1603_EXFAT_LOCK_MUTEX 0x186460
#define FS_OFFSET_1603_EXFAT_UNLOCK_MUTEX 0x1864B0
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x18CEE0
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x18CF00
// Misc Data
#define FS_OFFSET_1603_EXFAT_SD_MUTEX 0x100D3F0
#define FS_OFFSET_1603_EXFAT_NAND_MUTEX 0x1008B58
#define FS_OFFSET_1603_EXFAT_ACTIVE_PARTITION 0x1008B98
#define FS_OFFSET_1603_EXFAT_SDMMC_DAS_HANDLE 0xFE98B0
// NOPs
#define FS_OFFSET_1603_EXFAT_SD_DAS_INIT 0x258D4
// Nintendo Paths
#define FS_OFFSET_1603_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063B98, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070DBC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007795C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A7A4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1603_EXFAT_H__

View File

@@ -27,6 +27,10 @@ CODE_BEGIN armDCacheFlush
bic x8, x0, x10 bic x8, x0, x10
mov x10, x1 mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armDCacheFlush_L0: armDCacheFlush_L0:
dc civac, x8 dc civac, x8
add x8, x8, x9 add x8, x8, x9
@@ -34,6 +38,9 @@ armDCacheFlush_L0:
bcc armDCacheFlush_L0 bcc armDCacheFlush_L0
dsb sy dsb sy
strb wzr, [x0, #0x104]
ret ret
CODE_END CODE_END
@@ -48,6 +55,10 @@ CODE_BEGIN armDCacheClean
bic x8, x0, x10 bic x8, x0, x10
mov x10, x1 mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armDCacheClean_L0: armDCacheClean_L0:
dc cvac, x8 dc cvac, x8
add x8, x8, x9 add x8, x8, x9
@@ -55,6 +66,9 @@ armDCacheClean_L0:
bcc armDCacheClean_L0 bcc armDCacheClean_L0
dsb sy dsb sy
strb wzr, [x0, #0x104]
ret ret
CODE_END CODE_END
@@ -68,6 +82,10 @@ CODE_BEGIN armICacheInvalidate
bic x8, x0, x10 bic x8, x0, x10
mov x10, x1 mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armICacheInvalidate_L0: armICacheInvalidate_L0:
ic ivau, x8 ic ivau, x8
add x8, x8, x9 add x8, x8, x9
@@ -75,6 +93,9 @@ armICacheInvalidate_L0:
bcc armICacheInvalidate_L0 bcc armICacheInvalidate_L0
dsb sy dsb sy
strb wzr, [x0, #0x104]
ret ret
CODE_END CODE_END
@@ -89,6 +110,10 @@ CODE_BEGIN armDCacheZero
bic x8, x0, x10 bic x8, x0, x10
mov x10, x1 mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armDCacheZero_L0: armDCacheZero_L0:
dc zva, x8 dc zva, x8
add x8, x8, x9 add x8, x8, x9
@@ -96,5 +121,8 @@ armDCacheZero_L0:
bcc armDCacheZero_L0 bcc armDCacheZero_L0
dsb sy dsb sy
strb wzr, [x0, #0x104]
ret ret
CODE_END CODE_END

View File

@@ -62,7 +62,7 @@ namespace ams::secmon::fatal {
/* Write the context to the file. */ /* Write the context to the file. */
R_TRY(fs::WriteFile(file, 0, ctx, sizeof(*ctx), fs::WriteOption::Flush)); R_TRY(fs::WriteFile(file, 0, ctx, sizeof(*ctx), fs::WriteOption::Flush));
return ResultSuccess(); R_SUCCEED();
} }
} }

View File

@@ -48,11 +48,11 @@ namespace ams::secmon::fatal {
//sdmmc::Deactivate(Port); //sdmmc::Deactivate(Port);
R_TRY(sdmmc::Activate(Port)); R_TRY(sdmmc::Activate(Port));
return ResultSuccess(); R_SUCCEED();
} }
Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) { Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) {
return sdmmc::CheckSdCardConnection(out_sm, out_bw, Port); R_RETURN(sdmmc::CheckSdCardConnection(out_sm, out_bw, Port));
} }
Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count) { Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count) {
@@ -78,7 +78,7 @@ namespace ams::secmon::fatal {
sector_count -= cur_sectors; sector_count -= cur_sectors;
} }
return ResultSuccess(); R_SUCCEED();
} }
Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size) { Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size) {
@@ -104,7 +104,7 @@ namespace ams::secmon::fatal {
sector_count -= cur_sectors; sector_count -= cur_sectors;
} }
return ResultSuccess(); R_SUCCEED();
} }
} }

View File

@@ -34,45 +34,45 @@ namespace ams::fs {
Result TranslateFatFsError(FRESULT res) { Result TranslateFatFsError(FRESULT res) {
switch (res) { switch (res) {
case FR_OK: case FR_OK:
return ResultSuccess(); R_SUCCEED();
case FR_DISK_ERR: case FR_DISK_ERR:
return fs::ResultMmcAccessFailed(); R_THROW(fs::ResultMmcAccessFailed());
case FR_INT_ERR: case FR_INT_ERR:
return fs::ResultPreconditionViolation(); R_THROW(fs::ResultPreconditionViolation());
case FR_NOT_READY: case FR_NOT_READY:
return fs::ResultMmcAccessFailed(); R_THROW(fs::ResultMmcAccessFailed());
case FR_NO_FILE: case FR_NO_FILE:
return fs::ResultPathNotFound(); R_THROW(fs::ResultPathNotFound());
case FR_NO_PATH: case FR_NO_PATH:
return fs::ResultPathNotFound(); R_THROW(fs::ResultPathNotFound());
case FR_INVALID_NAME: case FR_INVALID_NAME:
return fs::ResultInvalidPath(); R_THROW(fs::ResultInvalidPath());
case FR_DENIED: case FR_DENIED:
return fs::ResultPermissionDenied(); R_THROW(fs::ResultPermissionDenied());
case FR_EXIST: case FR_EXIST:
return fs::ResultPathAlreadyExists(); R_THROW(fs::ResultPathAlreadyExists());
case FR_INVALID_OBJECT: case FR_INVALID_OBJECT:
return fs::ResultInvalidArgument(); R_THROW(fs::ResultInvalidArgument());
case FR_WRITE_PROTECTED: case FR_WRITE_PROTECTED:
return fs::ResultWriteNotPermitted(); R_THROW(fs::ResultWriteNotPermitted());
case FR_INVALID_DRIVE: case FR_INVALID_DRIVE:
return fs::ResultInvalidMountName(); R_THROW(fs::ResultInvalidMountName());
case FR_NOT_ENABLED: case FR_NOT_ENABLED:
return fs::ResultInvalidMountName(); /* BAD/TODO */ R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
case FR_NO_FILESYSTEM: case FR_NO_FILESYSTEM:
return fs::ResultInvalidMountName(); /* BAD/TODO */ R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
case FR_TIMEOUT: case FR_TIMEOUT:
return fs::ResultTargetLocked(); /* BAD/TODO */ R_THROW(fs::ResultTargetLocked()); /* BAD/TODO */
case FR_LOCKED: case FR_LOCKED:
return fs::ResultTargetLocked(); R_THROW(fs::ResultTargetLocked());
case FR_NOT_ENOUGH_CORE: case FR_NOT_ENOUGH_CORE:
return fs::ResultPreconditionViolation(); /* BAD/TODO */ R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
case FR_TOO_MANY_OPEN_FILES: case FR_TOO_MANY_OPEN_FILES:
return fs::ResultPreconditionViolation(); /* BAD/TODO */ R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
case FR_INVALID_PARAMETER: case FR_INVALID_PARAMETER:
return fs::ResultInvalidArgument(); R_THROW(fs::ResultInvalidArgument());
default: default:
return fs::ResultInternal(); R_THROW(fs::ResultInternal());
} }
} }
@@ -125,11 +125,11 @@ namespace ams::fs {
/* Expand the file. */ /* Expand the file. */
R_TRY(TranslateFatFsError(f_expand(std::addressof(fp), size, 1))); R_TRY(TranslateFatFsError(f_expand(std::addressof(fp), size, 1)));
return ResultSuccess(); R_SUCCEED();
} }
Result CreateDirectory(const char *path) { Result CreateDirectory(const char *path) {
return TranslateFatFsError(f_mkdir(path)); R_RETURN(TranslateFatFsError(f_mkdir(path)));
} }
Result OpenFile(FileHandle *out_file, const char *path, int mode) { Result OpenFile(FileHandle *out_file, const char *path, int mode) {
@@ -144,10 +144,10 @@ namespace ams::fs {
out_file->_handle = fp; out_file->_handle = fp;
g_files_opened[i] = true; g_files_opened[i] = true;
g_open_modes[i] = mode; g_open_modes[i] = mode;
return ResultSuccess(); R_SUCCEED();
} }
} }
return fs::ResultOpenCountLimit(); R_THROW(fs::ResultOpenCountLimit());
} }
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) { Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
@@ -164,11 +164,11 @@ namespace ams::fs {
/* Check that we read the correct amount. */ /* Check that we read the correct amount. */
R_UNLESS(br == size, fs::ResultOutOfRange()); R_UNLESS(br == size, fs::ResultOutOfRange());
return ResultSuccess(); R_SUCCEED();
} }
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size) { Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size) {
return ReadFile(handle, offset, buffer, size, fs::ReadOption::None); R_RETURN(ReadFile(handle, offset, buffer, size, fs::ReadOption::None));
} }
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) { Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
@@ -185,21 +185,21 @@ namespace ams::fs {
/* Set the output size. */ /* Set the output size. */
*out = br; *out = br;
return ResultSuccess(); R_SUCCEED();
} }
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) { Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) {
return ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None); R_RETURN(ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None));
} }
Result GetFileSize(s64 *out, FileHandle handle) { Result GetFileSize(s64 *out, FileHandle handle) {
FIL *fp = GetInternalFile(handle); FIL *fp = GetInternalFile(handle);
*out = f_size(fp); *out = f_size(fp);
return ResultSuccess(); R_SUCCEED();
} }
Result FlushFile(FileHandle handle) { Result FlushFile(FileHandle handle) {
return TranslateFatFsError(f_sync(GetInternalFile(handle))); R_RETURN(TranslateFatFsError(f_sync(GetInternalFile(handle))));
} }
Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) { Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) {
@@ -218,7 +218,7 @@ namespace ams::fs {
R_TRY(FlushFile(handle)); R_TRY(FlushFile(handle));
} }
return ResultSuccess(); R_SUCCEED();
} }
Result SetFileSize(FileHandle handle, s64 size) { Result SetFileSize(FileHandle handle, s64 size) {
@@ -242,7 +242,7 @@ namespace ams::fs {
/* Check that our expansion succeeded. */ /* Check that our expansion succeeded. */
AMS_ASSERT(f_size(fp) == static_cast<FSIZE_t>(size)); AMS_ASSERT(f_size(fp) == static_cast<FSIZE_t>(size));
return ResultSuccess(); R_SUCCEED();
} }
int GetFileOpenMode(FileHandle handle) { int GetFileOpenMode(FileHandle handle) {

View File

@@ -85,10 +85,10 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
/* We can get away with only including latest because exosphere supports newer-than-expected master key in engine. */ /* 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. */ /* TODO: Update on next change of keys. */
/* Mariko Development Master Kek Source. */ /* Mariko Development Master Kek Source. */
.byte 0xEC, 0x5E, 0xB5, 0x11, 0xD5, 0x43, 0x1E, 0x6A, 0x4E, 0x54, 0x6F, 0xD4, 0xD3, 0x22, 0xCE, 0x87 .byte 0x3A, 0x9C, 0xF0, 0x39, 0x70, 0x23, 0xF6, 0xAF, 0x71, 0x44, 0x60, 0xF4, 0x6D, 0xED, 0xA1, 0xD6
/* Mariko Production Master Kek Source. */ /* Mariko Production Master Kek Source. */
.byte 0xD2, 0x68, 0xC6, 0x53, 0x9D, 0x94, 0xF9, 0xA8, 0xA5, 0xA8, 0xA7, 0xC8, 0x8F, 0x53, 0x4B, 0x7A .byte 0xA5, 0xEC, 0x16, 0x39, 0x1A, 0x30, 0x16, 0x08, 0x2E, 0xCF, 0x09, 0x6F, 0x5E, 0x7C, 0xEE, 0xA9
/* Development Master Key Vectors. */ /* 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. */ .byte 0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE /* Zeroes encrypted with Master Key 00. */
@@ -105,6 +105,8 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x21, 0x88, 0x6B, 0x10, 0x9E, 0x83, 0xD6, 0x52, 0xAB, 0x08, 0xDB, 0x6D, 0x39, 0xFF, 0x1C, 0x9C /* Master key 0A encrypted with Master key 0B. */ .byte 0x21, 0x88, 0x6B, 0x10, 0x9E, 0x83, 0xD6, 0x52, 0xAB, 0x08, 0xDB, 0x6D, 0x39, 0xFF, 0x1C, 0x9C /* Master key 0A encrypted with Master key 0B. */
.byte 0x8A, 0xCE, 0xC4, 0x7F, 0xBE, 0x08, 0x61, 0x88, 0xD3, 0x73, 0x64, 0x51, 0xE2, 0xB6, 0x53, 0x15 /* Master key 0B encrypted with Master key 0C. */ .byte 0x8A, 0xCE, 0xC4, 0x7F, 0xBE, 0x08, 0x61, 0x88, 0xD3, 0x73, 0x64, 0x51, 0xE2, 0xB6, 0x53, 0x15 /* Master key 0B encrypted with Master key 0C. */
.byte 0x08, 0xE0, 0xF4, 0xBE, 0xAA, 0x6E, 0x5A, 0xC3, 0xA6, 0xBC, 0xFE, 0xB9, 0xE2, 0xA3, 0x24, 0x12 /* Master key 0C encrypted with Master key 0D. */ .byte 0x08, 0xE0, 0xF4, 0xBE, 0xAA, 0x6E, 0x5A, 0xC3, 0xA6, 0xBC, 0xFE, 0xB9, 0xE2, 0xA3, 0x24, 0x12 /* Master key 0C encrypted with Master key 0D. */
.byte 0xD6, 0x80, 0x98, 0xC0, 0xFA, 0xC7, 0x13, 0xCB, 0x93, 0xD2, 0x0B, 0x82, 0x4C, 0xA1, 0x7B, 0x8D /* Master key 0D encrypted with Master key 0E. */
.byte 0x78, 0x66, 0x19, 0xBD, 0x86, 0xE7, 0xC1, 0x09, 0x9B, 0x6F, 0x92, 0xB2, 0x58, 0x7D, 0xCF, 0x26 /* Master key 0E encrypted with Master key 0F. */
/* Production Master Key Vectors. */ /* 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. */ .byte 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D /* Zeroes encrypted with Master Key 00. */
@@ -121,6 +123,8 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xC1, 0x8D, 0x16, 0xBB, 0x2A, 0xE4, 0x1D, 0xD4, 0xC2, 0xC1, 0xB6, 0x40, 0x94, 0x35, 0x63, 0x98 /* Master key 0A encrypted with Master key 0B. */ .byte 0xC1, 0x8D, 0x16, 0xBB, 0x2A, 0xE4, 0x1D, 0xD4, 0xC2, 0xC1, 0xB6, 0x40, 0x94, 0x35, 0x63, 0x98 /* Master key 0A encrypted with Master key 0B. */
.byte 0xA3, 0x24, 0x65, 0x75, 0xEA, 0xCC, 0x6E, 0x8D, 0xFB, 0x5A, 0x16, 0x50, 0x74, 0xD2, 0x15, 0x06 /* Master key 0B encrypted with Master key 0C. */ .byte 0xA3, 0x24, 0x65, 0x75, 0xEA, 0xCC, 0x6E, 0x8D, 0xFB, 0x5A, 0x16, 0x50, 0x74, 0xD2, 0x15, 0x06 /* Master key 0B encrypted with Master key 0C. */
.byte 0x83, 0x67, 0xAF, 0x01, 0xCF, 0x93, 0xA1, 0xAB, 0x80, 0x45, 0xF7, 0x3F, 0x72, 0xFD, 0x3B, 0x38 /* Master key 0C encrypted with Master key 0D. */ .byte 0x83, 0x67, 0xAF, 0x01, 0xCF, 0x93, 0xA1, 0xAB, 0x80, 0x45, 0xF7, 0x3F, 0x72, 0xFD, 0x3B, 0x38 /* Master key 0C encrypted with Master key 0D. */
.byte 0xB1, 0x81, 0xA6, 0x0D, 0x72, 0xC7, 0xEE, 0x15, 0x21, 0xF3, 0xC0, 0xB5, 0x6B, 0x61, 0x6D, 0xE7 /* Master key 0D encrypted with Master key 0E. */
.byte 0xAF, 0x11, 0x4C, 0x67, 0x17, 0x7A, 0x52, 0x43, 0xF7, 0x70, 0x2F, 0xC7, 0xEF, 0x81, 0x72, 0x16 /* Master key 0E encrypted with Master key 0F. */
/* Device Master Key Source Sources. */ /* 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. */ .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. */
@@ -134,6 +138,8 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6 /* 12.1.0 Device Master Key Source Source. */ .byte 0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6 /* 12.1.0 Device Master Key Source Source. */
.byte 0xE4, 0xF3, 0x45, 0x6F, 0x18, 0xA1, 0x89, 0xF8, 0xDA, 0x4C, 0x64, 0x75, 0x68, 0xE6, 0xBD, 0x4F /* 13.0.0 Device Master Key Source Source. */ .byte 0xE4, 0xF3, 0x45, 0x6F, 0x18, 0xA1, 0x89, 0xF8, 0xDA, 0x4C, 0x64, 0x75, 0x68, 0xE6, 0xBD, 0x4F /* 13.0.0 Device Master Key Source Source. */
.byte 0x5B, 0x94, 0x63, 0xF7, 0xAD, 0x96, 0x1B, 0xA6, 0x23, 0x30, 0x06, 0x4D, 0x01, 0xE4, 0xCE, 0x1D /* 14.0.0 Device Master Key Source Source. */ .byte 0x5B, 0x94, 0x63, 0xF7, 0xAD, 0x96, 0x1B, 0xA6, 0x23, 0x30, 0x06, 0x4D, 0x01, 0xE4, 0xCE, 0x1D /* 14.0.0 Device Master Key Source Source. */
.byte 0x5E, 0xC9, 0xC5, 0x0A, 0xD0, 0x5F, 0x8B, 0x7B, 0xA7, 0x39, 0xEA, 0xBC, 0x60, 0x0F, 0x74, 0xE6 /* 15.0.0 Device Master Key Source Source. */
.byte 0xEA, 0x90, 0x6E, 0xA8, 0xAE, 0x92, 0x99, 0x64, 0x36, 0xC1, 0xF3, 0x1C, 0xC6, 0x32, 0x83, 0x8C /* 16.0.0 Device Master Key Source Source. */
/* Development Device Master Kek Sources. */ /* 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. */ .byte 0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34 /* 4.0.0 Device Master Kek Source. */
@@ -147,6 +153,8 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xC4, 0xBB, 0xF3, 0x9F, 0xA3, 0xAA, 0x00, 0x99, 0x7C, 0x97, 0xAD, 0x91, 0x8F, 0xE8, 0x45, 0xCB /* 12.1.0 Device Master Kek Source. */ .byte 0xC4, 0xBB, 0xF3, 0x9F, 0xA3, 0xAA, 0x00, 0x99, 0x7C, 0x97, 0xAD, 0x91, 0x8F, 0xE8, 0x45, 0xCB /* 12.1.0 Device Master Kek Source. */
.byte 0x20, 0x20, 0xAA, 0xFB, 0x89, 0xC2, 0xF0, 0x70, 0xB5, 0xE0, 0xA3, 0x11, 0x8A, 0x29, 0x8D, 0x0F /* 13.0.0 Device Master Kek Source. */ .byte 0x20, 0x20, 0xAA, 0xFB, 0x89, 0xC2, 0xF0, 0x70, 0xB5, 0xE0, 0xA3, 0x11, 0x8A, 0x29, 0x8D, 0x0F /* 13.0.0 Device Master Kek Source. */
.byte 0xCE, 0x14, 0x74, 0x66, 0x98, 0xA8, 0x6D, 0x7D, 0xBD, 0x54, 0x91, 0x68, 0x5F, 0x1D, 0x0E, 0xEA /* 14.0.0 Device Master Kek Source. */ .byte 0xCE, 0x14, 0x74, 0x66, 0x98, 0xA8, 0x6D, 0x7D, 0xBD, 0x54, 0x91, 0x68, 0x5F, 0x1D, 0x0E, 0xEA /* 14.0.0 Device Master Kek Source. */
.byte 0xAE, 0x05, 0x48, 0x65, 0xAB, 0x17, 0x9D, 0x3D, 0x51, 0xB7, 0x56, 0xBD, 0x9B, 0x0B, 0x5B, 0x6E /* 15.0.0 Device Master Kek Source. */
.byte 0xFF, 0xF6, 0x4B, 0x0F, 0xFF, 0x0D, 0xC0, 0x4F, 0x56, 0x8A, 0x40, 0x74, 0x67, 0xC5, 0xFE, 0x9F /* 16.0.0 Device Master Kek Source. */
/* Production Device Master Kek Sources. */ /* 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. */ .byte 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D /* 4.0.0 Device Master Kek Source. */
@@ -160,3 +168,5 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xC2, 0x65, 0x34, 0x6E, 0xC7, 0xC6, 0x5D, 0x97, 0x3E, 0x34, 0x5C, 0x6B, 0xB3, 0x7E, 0xC6, 0xE3 /* 12.1.0 Device Master Kek Source. */ .byte 0xC2, 0x65, 0x34, 0x6E, 0xC7, 0xC6, 0x5D, 0x97, 0x3E, 0x34, 0x5C, 0x6B, 0xB3, 0x7E, 0xC6, 0xE3 /* 12.1.0 Device Master Kek Source. */
.byte 0x77, 0x52, 0x92, 0xF0, 0xAA, 0xE3, 0xFB, 0xE0, 0x60, 0x16, 0xB3, 0x78, 0x68, 0x53, 0xF7, 0xA8 /* 13.0.0 Device Master Kek Source. */ .byte 0x77, 0x52, 0x92, 0xF0, 0xAA, 0xE3, 0xFB, 0xE0, 0x60, 0x16, 0xB3, 0x78, 0x68, 0x53, 0xF7, 0xA8 /* 13.0.0 Device Master Kek Source. */
.byte 0x67, 0xD5, 0xD6, 0x0C, 0x08, 0xF5, 0xA3, 0x11, 0xBD, 0x6D, 0x5A, 0xEB, 0x96, 0x24, 0xB0, 0xD2 /* 14.0.0 Device Master Kek Source. */ .byte 0x67, 0xD5, 0xD6, 0x0C, 0x08, 0xF5, 0xA3, 0x11, 0xBD, 0x6D, 0x5A, 0xEB, 0x96, 0x24, 0xB0, 0xD2 /* 14.0.0 Device Master Kek Source. */
.byte 0x7C, 0x30, 0xED, 0x8B, 0x39, 0x25, 0x2C, 0x08, 0x8F, 0x48, 0xDC, 0x28, 0xE6, 0x1A, 0x6B, 0x49 /* 15.0.0 Device Master Kek Source. */
.byte 0xF0, 0xF3, 0xFF, 0x52, 0x75, 0x2F, 0xBA, 0x4D, 0x09, 0x72, 0x30, 0x89, 0xA9, 0xDF, 0xFE, 0x1F /* 16.0.0 Device Master Kek Source. */

View File

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

View File

@@ -52,7 +52,7 @@ namespace ams::secmon::smc {
[fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB, [fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB,
[fuse::DramId_HoagHynix1y4GB] = pkg1::MemorySize_4GB, [fuse::DramId_HoagHynix1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaHynix1y4GB] = pkg1::MemorySize_4GB, [fuse::DramId_AulaHynix1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaX1X2Samsung4GB] = pkg1::MemorySize_4GB, [fuse::DramId_Deprecated7] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSansung4GB] = pkg1::MemorySize_4GB, [fuse::DramId_IowaSansung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung8GB] = pkg1::MemorySize_8GB, [fuse::DramId_IowaSamsung8GB] = pkg1::MemorySize_8GB,
[fuse::DramId_IowaHynix4GB] = pkg1::MemorySize_4GB, [fuse::DramId_IowaHynix4GB] = pkg1::MemorySize_4GB,
@@ -61,7 +61,7 @@ namespace ams::secmon::smc {
[fuse::DramId_HoagSamsung8GB] = pkg1::MemorySize_8GB, [fuse::DramId_HoagSamsung8GB] = pkg1::MemorySize_8GB,
[fuse::DramId_HoagHynix4GB] = pkg1::MemorySize_4GB, [fuse::DramId_HoagHynix4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_HoagMicron4GB] = pkg1::MemorySize_4GB, [fuse::DramId_HoagMicron4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung4GBY] = pkg1::MemorySize_4GB, [fuse::DramId_Deprecated16] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung1y4GBX] = pkg1::MemorySize_4GB, [fuse::DramId_IowaSamsung1y4GBX] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung1y8GBX] = pkg1::MemorySize_8GB, [fuse::DramId_IowaSamsung1y8GBX] = pkg1::MemorySize_8GB,
[fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB, [fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB,
@@ -74,6 +74,12 @@ namespace ams::secmon::smc {
[fuse::DramId_HoagMicron1y4GB] = pkg1::MemorySize_4GB, [fuse::DramId_HoagMicron1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaMicron1y4GB] = pkg1::MemorySize_4GB, [fuse::DramId_AulaMicron1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaSamsung1y8GBX] = pkg1::MemorySize_8GB, [fuse::DramId_AulaSamsung1y8GBX] = pkg1::MemorySize_8GB,
[fuse::DramId_IowaX1X2Samsung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_HoagX1X2Samsung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaX1X2Samsung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung4GBY] = pkg1::MemorySize_4GB,
[fuse::DramId_HoagSamsung4GBY] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaSamsung4GBY] = pkg1::MemorySize_4GB,
}; };
constexpr const pkg1::MemoryMode MemoryModes[] = { constexpr const pkg1::MemoryMode MemoryModes[] = {

View File

@@ -39,45 +39,45 @@ namespace ams::fs {
Result TranslateFatFsError(FRESULT res) { Result TranslateFatFsError(FRESULT res) {
switch (res) { switch (res) {
case FR_OK: case FR_OK:
return ResultSuccess(); R_SUCCEED();
case FR_DISK_ERR: case FR_DISK_ERR:
return fs::ResultMmcAccessFailed(); R_THROW(fs::ResultMmcAccessFailed());
case FR_INT_ERR: case FR_INT_ERR:
return fs::ResultPreconditionViolation(); R_THROW(fs::ResultPreconditionViolation());
case FR_NOT_READY: case FR_NOT_READY:
return fs::ResultMmcAccessFailed(); R_THROW(fs::ResultMmcAccessFailed());
case FR_NO_FILE: case FR_NO_FILE:
return fs::ResultPathNotFound(); R_THROW(fs::ResultPathNotFound());
case FR_NO_PATH: case FR_NO_PATH:
return fs::ResultPathNotFound(); R_THROW(fs::ResultPathNotFound());
case FR_INVALID_NAME: case FR_INVALID_NAME:
return fs::ResultInvalidPath(); R_THROW(fs::ResultInvalidPath());
case FR_DENIED: case FR_DENIED:
return fs::ResultPermissionDenied(); R_THROW(fs::ResultPermissionDenied());
case FR_EXIST: case FR_EXIST:
return fs::ResultPathAlreadyExists(); R_THROW(fs::ResultPathAlreadyExists());
case FR_INVALID_OBJECT: case FR_INVALID_OBJECT:
return fs::ResultInvalidArgument(); R_THROW(fs::ResultInvalidArgument());
case FR_WRITE_PROTECTED: case FR_WRITE_PROTECTED:
return fs::ResultWriteNotPermitted(); R_THROW(fs::ResultWriteNotPermitted());
case FR_INVALID_DRIVE: case FR_INVALID_DRIVE:
return fs::ResultInvalidMountName(); R_THROW(fs::ResultInvalidMountName());
case FR_NOT_ENABLED: case FR_NOT_ENABLED:
return fs::ResultInvalidMountName(); /* BAD/TODO */ R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
case FR_NO_FILESYSTEM: case FR_NO_FILESYSTEM:
return fs::ResultInvalidMountName(); /* BAD/TODO */ R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
case FR_TIMEOUT: case FR_TIMEOUT:
return fs::ResultTargetLocked(); /* BAD/TODO */ R_THROW(fs::ResultTargetLocked()); /* BAD/TODO */
case FR_LOCKED: case FR_LOCKED:
return fs::ResultTargetLocked(); R_THROW(fs::ResultTargetLocked());
case FR_NOT_ENOUGH_CORE: case FR_NOT_ENOUGH_CORE:
return fs::ResultPreconditionViolation(); /* BAD/TODO */ R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
case FR_TOO_MANY_OPEN_FILES: case FR_TOO_MANY_OPEN_FILES:
return fs::ResultPreconditionViolation(); /* BAD/TODO */ R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
case FR_INVALID_PARAMETER: case FR_INVALID_PARAMETER:
return fs::ResultInvalidArgument(); R_THROW(fs::ResultInvalidArgument());
default: default:
return fs::ResultInternal(); R_THROW(fs::ResultInternal());
} }
} }
@@ -138,7 +138,7 @@ namespace ams::fs {
*out_entry_type = (info.fattrib & AM_DIR) ? DirectoryEntryType_Directory : DirectoryEntryType_File; *out_entry_type = (info.fattrib & AM_DIR) ? DirectoryEntryType_Directory : DirectoryEntryType_File;
*out_archive = (info.fattrib & AM_ARC); *out_archive = (info.fattrib & AM_ARC);
return ResultSuccess(); R_SUCCEED();
} }
Result CreateFile(const char *path, s64 size) { Result CreateFile(const char *path, s64 size) {
@@ -152,11 +152,11 @@ namespace ams::fs {
/* Expand the file. */ /* Expand the file. */
R_TRY(TranslateFatFsError(f_expand(std::addressof(fp), size, 1))); R_TRY(TranslateFatFsError(f_expand(std::addressof(fp), size, 1)));
return ResultSuccess(); R_SUCCEED();
} }
Result CreateDirectory(const char *path) { Result CreateDirectory(const char *path) {
return TranslateFatFsError(f_mkdir(path)); R_RETURN(TranslateFatFsError(f_mkdir(path)));
} }
Result OpenFile(FileHandle *out_file, const char *path, int mode) { Result OpenFile(FileHandle *out_file, const char *path, int mode) {
@@ -171,10 +171,10 @@ namespace ams::fs {
out_file->_handle = fp; out_file->_handle = fp;
g_files_opened[i] = true; g_files_opened[i] = true;
g_open_modes[i] = mode; g_open_modes[i] = mode;
return ResultSuccess(); R_SUCCEED();
} }
} }
return fs::ResultOpenCountLimit(); R_THROW(fs::ResultOpenCountLimit());
} }
Result OpenDirectory(DirectoryHandle *out_dir, const char *path) { Result OpenDirectory(DirectoryHandle *out_dir, const char *path) {
@@ -188,10 +188,10 @@ namespace ams::fs {
/* Set the output. */ /* Set the output. */
out_dir->_handle = dp; out_dir->_handle = dp;
g_dirs_opened[i] = true; g_dirs_opened[i] = true;
return ResultSuccess(); R_SUCCEED();
} }
} }
return fs::ResultOpenCountLimit(); R_THROW(fs::ResultOpenCountLimit());
} }
Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries) { Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries) {
@@ -209,7 +209,7 @@ namespace ams::fs {
} }
*out_count = count; *out_count = count;
return ResultSuccess(); R_SUCCEED();
} }
void CloseDirectory(DirectoryHandle handle) { void CloseDirectory(DirectoryHandle handle) {
@@ -232,11 +232,11 @@ namespace ams::fs {
/* Check that we read the correct amount. */ /* Check that we read the correct amount. */
R_UNLESS(br == size, fs::ResultOutOfRange()); R_UNLESS(br == size, fs::ResultOutOfRange());
return ResultSuccess(); R_SUCCEED();
} }
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size) { Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size) {
return ReadFile(handle, offset, buffer, size, fs::ReadOption::None); R_RETURN(ReadFile(handle, offset, buffer, size, fs::ReadOption::None));
} }
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) { Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
@@ -253,21 +253,21 @@ namespace ams::fs {
/* Set the output size. */ /* Set the output size. */
*out = br; *out = br;
return ResultSuccess(); R_SUCCEED();
} }
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) { Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) {
return ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None); R_RETURN(ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None));
} }
Result GetFileSize(s64 *out, FileHandle handle) { Result GetFileSize(s64 *out, FileHandle handle) {
FIL *fp = GetInternalFile(handle); FIL *fp = GetInternalFile(handle);
*out = f_size(fp); *out = f_size(fp);
return ResultSuccess(); R_SUCCEED();
} }
Result FlushFile(FileHandle handle) { Result FlushFile(FileHandle handle) {
return TranslateFatFsError(f_sync(GetInternalFile(handle))); R_RETURN(TranslateFatFsError(f_sync(GetInternalFile(handle))));
} }
Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) { Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) {
@@ -286,7 +286,7 @@ namespace ams::fs {
R_TRY(FlushFile(handle)); R_TRY(FlushFile(handle));
} }
return ResultSuccess(); R_SUCCEED();
} }
Result SetFileSize(FileHandle handle, s64 size) { Result SetFileSize(FileHandle handle, s64 size) {
@@ -310,7 +310,7 @@ namespace ams::fs {
/* Check that our expansion succeeded. */ /* Check that our expansion succeeded. */
AMS_ASSERT(f_size(fp) == static_cast<FSIZE_t>(size)); AMS_ASSERT(f_size(fp) == static_cast<FSIZE_t>(size));
return ResultSuccess(); R_SUCCEED();
} }
int GetFileOpenMode(FileHandle handle) { int GetFileOpenMode(FileHandle handle) {

View File

@@ -20,7 +20,7 @@ namespace ams::fs {
Result FileHandleStorage::UpdateSize() { Result FileHandleStorage::UpdateSize() {
R_SUCCEED_IF(m_size != InvalidSize); R_SUCCEED_IF(m_size != InvalidSize);
return GetFileSize(std::addressof(m_size), m_handle); R_RETURN(GetFileSize(std::addressof(m_size), m_handle));
} }
Result FileHandleStorage::Read(s64 offset, void *buffer, size_t size) { Result FileHandleStorage::Read(s64 offset, void *buffer, size_t size) {
@@ -34,9 +34,9 @@ namespace ams::fs {
R_TRY(this->UpdateSize()); R_TRY(this->UpdateSize());
/* Ensure our access is valid. */ /* Ensure our access is valid. */
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange()); R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
return ReadFile(m_handle, offset, buffer, size, fs::ReadOption()); R_RETURN(ReadFile(m_handle, offset, buffer, size, fs::ReadOption()));
} }
Result FileHandleStorage::Write(s64 offset, const void *buffer, size_t size) { Result FileHandleStorage::Write(s64 offset, const void *buffer, size_t size) {
@@ -50,24 +50,24 @@ namespace ams::fs {
R_TRY(this->UpdateSize()); R_TRY(this->UpdateSize());
/* Ensure our access is valid. */ /* Ensure our access is valid. */
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange()); R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
return WriteFile(m_handle, offset, buffer, size, fs::WriteOption()); R_RETURN(WriteFile(m_handle, offset, buffer, size, fs::WriteOption()));
} }
Result FileHandleStorage::Flush() { Result FileHandleStorage::Flush() {
return FlushFile(m_handle); R_RETURN(FlushFile(m_handle));
} }
Result FileHandleStorage::GetSize(s64 *out_size) { Result FileHandleStorage::GetSize(s64 *out_size) {
R_TRY(this->UpdateSize()); R_TRY(this->UpdateSize());
*out_size = m_size; *out_size = m_size;
return ResultSuccess(); R_SUCCEED();
} }
Result FileHandleStorage::SetSize(s64 size) { Result FileHandleStorage::SetSize(s64 size) {
m_size = InvalidSize; m_size = InvalidSize;
return SetFileSize(m_handle, size); R_RETURN(SetFileSize(m_handle, size));
} }
} }

View File

@@ -31,25 +31,38 @@ namespace ams::fs {
virtual Result GetSize(s64 *out) = 0; virtual Result GetSize(s64 *out) = 0;
public: public:
static inline bool CheckAccessRange(s64 offset, s64 size, s64 total_size) { static inline Result CheckAccessRange(s64 offset, s64 size, s64 total_size) {
return offset >= 0 && R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
size >= 0 && R_UNLESS(size >= 0, fs::ResultInvalidSize());
size <= total_size && R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
offset <= (total_size - size); R_UNLESS(offset + size <= total_size, fs::ResultOutOfRange());
R_SUCCEED();
} }
static inline bool CheckAccessRange(s64 offset, size_t size, s64 total_size) { static ALWAYS_INLINE Result CheckAccessRange(s64 offset, size_t size, s64 total_size) {
return CheckAccessRange(offset, static_cast<s64>(size), total_size); R_RETURN(CheckAccessRange(offset, static_cast<s64>(size), total_size));
} }
static inline bool CheckOffsetAndSize(s64 offset, s64 size) { static inline Result CheckOffsetAndSize(s64 offset, s64 size) {
return offset >= 0 && R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
size >= 0 && R_UNLESS(size >= 0, fs::ResultInvalidSize());
offset <= (offset + size); R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
R_SUCCEED();
} }
static inline bool CheckOffsetAndSize(s64 offset, size_t size) { static ALWAYS_INLINE Result CheckOffsetAndSize(s64 offset, size_t size) {
return CheckOffsetAndSize(offset, static_cast<s64>(size)); R_RETURN(CheckOffsetAndSize(offset, static_cast<s64>(size)));
}
static inline Result CheckOffsetAndSizeWithResult(s64 offset, s64 size, Result fail_result) {
R_TRY_CATCH(CheckOffsetAndSize(offset, size)) {
R_CONVERT_ALL(fail_result);
} R_END_TRY_CATCH;
R_SUCCEED();
}
static ALWAYS_INLINE Result CheckOffsetAndSizeWithResult(s64 offset, size_t size, Result fail_result) {
R_RETURN(CheckOffsetAndSizeWithResult(offset, static_cast<s64>(size), fail_result));
} }
}; };
@@ -60,23 +73,23 @@ namespace ams::fs {
ReadOnlyStorageAdapter(IStorage &s) : m_storage(s) { /* ... */ } ReadOnlyStorageAdapter(IStorage &s) : m_storage(s) { /* ... */ }
virtual Result Read(s64 offset, void *buffer, size_t size) override { virtual Result Read(s64 offset, void *buffer, size_t size) override {
return m_storage.Read(offset, buffer, size); R_RETURN(m_storage.Read(offset, buffer, size));
} }
virtual Result Flush() override { virtual Result Flush() override {
return m_storage.Flush(); R_RETURN(m_storage.Flush());
} }
virtual Result GetSize(s64 *out) override { virtual Result GetSize(s64 *out) override {
return m_storage.GetSize(out); R_RETURN(m_storage.GetSize(out));
} }
virtual Result Write(s64 offset, const void *buffer, size_t size) override { virtual Result Write(s64 offset, const void *buffer, size_t size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
virtual Result SetSize(s64 size) override { virtual Result SetSize(s64 size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
}; };
@@ -93,9 +106,9 @@ namespace ams::fs {
R_SUCCEED_IF(size == 0); R_SUCCEED_IF(size == 0);
/* Validate arguments and read. */ /* Validate arguments and read. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange()); R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
return m_storage.Read(m_offset + offset, buffer, size); R_RETURN(m_storage.Read(m_offset + offset, buffer, size));
} }
virtual Result Write(s64 offset, const void *buffer, size_t size) override{ virtual Result Write(s64 offset, const void *buffer, size_t size) override{
@@ -103,22 +116,22 @@ namespace ams::fs {
R_SUCCEED_IF(size == 0); R_SUCCEED_IF(size == 0);
/* Validate arguments and write. */ /* Validate arguments and write. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument()); R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange()); R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
return m_storage.Write(m_offset + offset, buffer, size); R_RETURN(m_storage.Write(m_offset + offset, buffer, size));
} }
virtual Result Flush() override { virtual Result Flush() override {
return m_storage.Flush(); R_RETURN(m_storage.Flush());
} }
virtual Result GetSize(s64 *out) override { virtual Result GetSize(s64 *out) override {
*out = m_size; *out = m_size;
return ResultSuccess(); R_SUCCEED();
} }
virtual Result SetSize(s64 size) override { virtual Result SetSize(s64 size) override {
return fs::ResultUnsupportedSetSizeForNotResizableSubStorage(); R_THROW(fs::ResultUnsupportedSetSizeForNotResizableSubStorage());
} }
}; };

View File

@@ -33,11 +33,11 @@ namespace ams::nxboot {
ShowFatalError("SdCard: unaligned access to %" PRIx64 ", size=%" PRIx64"\n", static_cast<u64>(offset), static_cast<u64>(size)); ShowFatalError("SdCard: unaligned access to %" PRIx64 ", size=%" PRIx64"\n", static_cast<u64>(offset), static_cast<u64>(size));
} }
return ReadSdCard(buffer, size, offset / sdmmc::SectorSize, size / sdmmc::SectorSize); R_RETURN(ReadSdCard(buffer, size, offset / sdmmc::SectorSize, size / sdmmc::SectorSize));
} }
virtual Result Flush() override { virtual Result Flush() override {
return ResultSuccess(); R_SUCCEED();
} }
virtual Result GetSize(s64 *out) override { virtual Result GetSize(s64 *out) override {
@@ -45,15 +45,15 @@ namespace ams::nxboot {
R_TRY(GetSdCardMemoryCapacity(std::addressof(num_sectors))); R_TRY(GetSdCardMemoryCapacity(std::addressof(num_sectors)));
*out = static_cast<s64>(num_sectors) * static_cast<s64>(sdmmc::SectorSize); *out = static_cast<s64>(num_sectors) * static_cast<s64>(sdmmc::SectorSize);
return ResultSuccess(); R_SUCCEED();
} }
virtual Result Write(s64 offset, const void *buffer, size_t size) override { virtual Result Write(s64 offset, const void *buffer, size_t size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
virtual Result SetSize(s64 size) override { virtual Result SetSize(s64 size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
}; };
@@ -67,11 +67,11 @@ namespace ams::nxboot {
ShowFatalError("SdCard: unaligned access to %" PRIx64 ", size=%" PRIx64"\n", static_cast<u64>(offset), static_cast<u64>(size)); ShowFatalError("SdCard: unaligned access to %" PRIx64 ", size=%" PRIx64"\n", static_cast<u64>(offset), static_cast<u64>(size));
} }
return ReadMmc(buffer, size, Partition, offset / sdmmc::SectorSize, size / sdmmc::SectorSize); R_RETURN(ReadMmc(buffer, size, Partition, offset / sdmmc::SectorSize, size / sdmmc::SectorSize));
} }
virtual Result Flush() override { virtual Result Flush() override {
return ResultSuccess(); R_SUCCEED();
} }
virtual Result GetSize(s64 *out) override { virtual Result GetSize(s64 *out) override {
@@ -79,15 +79,15 @@ namespace ams::nxboot {
R_TRY(GetMmcMemoryCapacity(std::addressof(num_sectors), Partition)); R_TRY(GetMmcMemoryCapacity(std::addressof(num_sectors), Partition));
*out = num_sectors * sdmmc::SectorSize; *out = num_sectors * sdmmc::SectorSize;
return ResultSuccess(); R_SUCCEED();
} }
virtual Result Write(s64 offset, const void *buffer, size_t size) override { virtual Result Write(s64 offset, const void *buffer, size_t size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
virtual Result SetSize(s64 size) override { virtual Result SetSize(s64 size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
}; };
@@ -153,23 +153,23 @@ namespace ams::nxboot {
subofs = 0; subofs = 0;
} }
return ResultSuccess(); R_SUCCEED();
} }
virtual Result Flush() override { virtual Result Flush() override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
virtual Result GetSize(s64 *out) override { virtual Result GetSize(s64 *out) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
virtual Result Write(s64 offset, const void *buffer, size_t size) override { virtual Result Write(s64 offset, const void *buffer, size_t size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
virtual Result SetSize(s64 size) override { virtual Result SetSize(s64 size) override {
return fs::ResultUnsupportedOperation(); R_THROW(fs::ResultUnsupportedOperation());
} }
}; };
@@ -349,11 +349,11 @@ namespace ams::nxboot {
} }
Result ReadBoot0(s64 offset, void *dst, size_t size) { Result ReadBoot0(s64 offset, void *dst, size_t size) {
return g_boot0_storage->Read(offset, dst, size); R_RETURN(g_boot0_storage->Read(offset, dst, size));
} }
Result ReadPackage2(s64 offset, void *dst, size_t size) { Result ReadPackage2(s64 offset, void *dst, size_t size) {
return g_package2_storage->Read(offset, dst, size); R_RETURN(g_package2_storage->Read(offset, dst, size));
} }
} }

View File

@@ -45,7 +45,7 @@ namespace ams::nxboot {
/* Write the context to the file. */ /* Write the context to the file. */
R_TRY(fs::WriteFile(file, 0, ctx, sizeof(*ctx), fs::WriteOption::Flush)); R_TRY(fs::WriteFile(file, 0, ctx, sizeof(*ctx), fs::WriteOption::Flush));
return ResultSuccess(); R_SUCCEED();
} }
} }

View File

@@ -23,17 +23,17 @@ namespace ams::nxboot {
alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSource[se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSource[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */ /* TODO: Update on next change of keys. */
0xD2, 0x68, 0xC6, 0x53, 0x9D, 0x94, 0xF9, 0xA8, 0xA5, 0xA8, 0xA7, 0xC8, 0x8F, 0x53, 0x4B, 0x7A 0xA5, 0xEC, 0x16, 0x39, 0x1A, 0x30, 0x16, 0x08, 0x2E, 0xCF, 0x09, 0x6F, 0x5E, 0x7C, 0xEE, 0xA9
}; };
alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSourceDev[se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSourceDev[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */ /* TODO: Update on next change of keys. */
0xEC, 0x5E, 0xB5, 0x11, 0xD5, 0x43, 0x1E, 0x6A, 0x4E, 0x54, 0x6F, 0xD4, 0xD3, 0x22, 0xCE, 0x87 0x3A, 0x9C, 0xF0, 0x39, 0x70, 0x23, 0xF6, 0xAF, 0x71, 0x44, 0x60, 0xF4, 0x6D, 0xED, 0xA1, 0xD6
}; };
alignas(se::AesBlockSize) constexpr inline const u8 EristaMasterKekSource[se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 EristaMasterKekSource[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */ /* TODO: Update on next change of keys. */
0xF0, 0x13, 0x37, 0x9A, 0xD5, 0x63, 0x51, 0xC3, 0xB4, 0x96, 0x35, 0xBC, 0x9C, 0xE8, 0x76, 0x81 0x99, 0x22, 0x09, 0x57, 0xA7, 0xF9, 0x5E, 0x94, 0xFE, 0x78, 0x7F, 0x41, 0xD6, 0xE7, 0x56, 0xE6
}; };
alignas(se::AesBlockSize) constexpr inline const u8 KeyblobKeySource[se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 KeyblobKeySource[se::AesBlockSize] = {
@@ -68,6 +68,8 @@ namespace ams::nxboot {
{ 0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6 }, /* 12.1.0 Device Master Key Source Source. */ { 0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6 }, /* 12.1.0 Device Master Key Source Source. */
{ 0xE4, 0xF3, 0x45, 0x6F, 0x18, 0xA1, 0x89, 0xF8, 0xDA, 0x4C, 0x64, 0x75, 0x68, 0xE6, 0xBD, 0x4F }, /* 13.0.0 Device Master Key Source Source. */ { 0xE4, 0xF3, 0x45, 0x6F, 0x18, 0xA1, 0x89, 0xF8, 0xDA, 0x4C, 0x64, 0x75, 0x68, 0xE6, 0xBD, 0x4F }, /* 13.0.0 Device Master Key Source Source. */
{ 0x5B, 0x94, 0x63, 0xF7, 0xAD, 0x96, 0x1B, 0xA6, 0x23, 0x30, 0x06, 0x4D, 0x01, 0xE4, 0xCE, 0x1D }, /* 14.0.0 Device Master Key Source Source. */ { 0x5B, 0x94, 0x63, 0xF7, 0xAD, 0x96, 0x1B, 0xA6, 0x23, 0x30, 0x06, 0x4D, 0x01, 0xE4, 0xCE, 0x1D }, /* 14.0.0 Device Master Key Source Source. */
{ 0x5E, 0xC9, 0xC5, 0x0A, 0xD0, 0x5F, 0x8B, 0x7B, 0xA7, 0x39, 0xEA, 0xBC, 0x60, 0x0F, 0x74, 0xE6 }, /* 15.0.0 Device Master Key Source Source. */
{ 0xEA, 0x90, 0x6E, 0xA8, 0xAE, 0x92, 0x99, 0x64, 0x36, 0xC1, 0xF3, 0x1C, 0xC6, 0x32, 0x83, 0x8C }, /* 16.0.0 Device Master Key Source Source. */
}; };
alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSources[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSources[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = {
@@ -82,6 +84,8 @@ namespace ams::nxboot {
{ 0xC2, 0x65, 0x34, 0x6E, 0xC7, 0xC6, 0x5D, 0x97, 0x3E, 0x34, 0x5C, 0x6B, 0xB3, 0x7E, 0xC6, 0xE3 }, /* 12.1.0 Device Master Kek Source. */ { 0xC2, 0x65, 0x34, 0x6E, 0xC7, 0xC6, 0x5D, 0x97, 0x3E, 0x34, 0x5C, 0x6B, 0xB3, 0x7E, 0xC6, 0xE3 }, /* 12.1.0 Device Master Kek Source. */
{ 0x77, 0x52, 0x92, 0xF0, 0xAA, 0xE3, 0xFB, 0xE0, 0x60, 0x16, 0xB3, 0x78, 0x68, 0x53, 0xF7, 0xA8 }, /* 13.0.0 Device Master Kek Source. */ { 0x77, 0x52, 0x92, 0xF0, 0xAA, 0xE3, 0xFB, 0xE0, 0x60, 0x16, 0xB3, 0x78, 0x68, 0x53, 0xF7, 0xA8 }, /* 13.0.0 Device Master Kek Source. */
{ 0x67, 0xD5, 0xD6, 0x0C, 0x08, 0xF5, 0xA3, 0x11, 0xBD, 0x6D, 0x5A, 0xEB, 0x96, 0x24, 0xB0, 0xD2 }, /* 14.0.0 Device Master Kek Source. */ { 0x67, 0xD5, 0xD6, 0x0C, 0x08, 0xF5, 0xA3, 0x11, 0xBD, 0x6D, 0x5A, 0xEB, 0x96, 0x24, 0xB0, 0xD2 }, /* 14.0.0 Device Master Kek Source. */
{ 0x7C, 0x30, 0xED, 0x8B, 0x39, 0x25, 0x2C, 0x08, 0x8F, 0x48, 0xDC, 0x28, 0xE6, 0x1A, 0x6B, 0x49 }, /* 15.0.0 Device Master Kek Source. */
{ 0xF0, 0xF3, 0xFF, 0x52, 0x75, 0x2F, 0xBA, 0x4D, 0x09, 0x72, 0x30, 0x89, 0xA9, 0xDF, 0xFE, 0x1F }, /* 16.0.0 Device Master Kek Source. */
}; };
alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSourcesDev[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSourcesDev[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = {
@@ -96,6 +100,8 @@ namespace ams::nxboot {
{ 0xC4, 0xBB, 0xF3, 0x9F, 0xA3, 0xAA, 0x00, 0x99, 0x7C, 0x97, 0xAD, 0x91, 0x8F, 0xE8, 0x45, 0xCB }, /* 12.1.0 Device Master Kek Source. */ { 0xC4, 0xBB, 0xF3, 0x9F, 0xA3, 0xAA, 0x00, 0x99, 0x7C, 0x97, 0xAD, 0x91, 0x8F, 0xE8, 0x45, 0xCB }, /* 12.1.0 Device Master Kek Source. */
{ 0x20, 0x20, 0xAA, 0xFB, 0x89, 0xC2, 0xF0, 0x70, 0xB5, 0xE0, 0xA3, 0x11, 0x8A, 0x29, 0x8D, 0x0F }, /* 13.0.0 Device Master Kek Source. */ { 0x20, 0x20, 0xAA, 0xFB, 0x89, 0xC2, 0xF0, 0x70, 0xB5, 0xE0, 0xA3, 0x11, 0x8A, 0x29, 0x8D, 0x0F }, /* 13.0.0 Device Master Kek Source. */
{ 0xCE, 0x14, 0x74, 0x66, 0x98, 0xA8, 0x6D, 0x7D, 0xBD, 0x54, 0x91, 0x68, 0x5F, 0x1D, 0x0E, 0xEA }, /* 14.0.0 Device Master Kek Source. */ { 0xCE, 0x14, 0x74, 0x66, 0x98, 0xA8, 0x6D, 0x7D, 0xBD, 0x54, 0x91, 0x68, 0x5F, 0x1D, 0x0E, 0xEA }, /* 14.0.0 Device Master Kek Source. */
{ 0xAE, 0x05, 0x48, 0x65, 0xAB, 0x17, 0x9D, 0x3D, 0x51, 0xB7, 0x56, 0xBD, 0x9B, 0x0B, 0x5B, 0x6E }, /* 15.0.0 Device Master Kek Source. */
{ 0xFF, 0xF6, 0x4B, 0x0F, 0xFF, 0x0D, 0xC0, 0x4F, 0x56, 0x8A, 0x40, 0x74, 0x67, 0xC5, 0xFE, 0x9F }, /* 16.0.0 Device Master Kek Source. */
}; };
alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySources[pkg1::KeyGeneration_Count][se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySources[pkg1::KeyGeneration_Count][se::AesBlockSize] = {
@@ -113,6 +119,8 @@ namespace ams::nxboot {
{ 0xC1, 0x8D, 0x16, 0xBB, 0x2A, 0xE4, 0x1D, 0xD4, 0xC2, 0xC1, 0xB6, 0x40, 0x94, 0x35, 0x63, 0x98 }, /* Master key 0A encrypted with Master key 0B. */ { 0xC1, 0x8D, 0x16, 0xBB, 0x2A, 0xE4, 0x1D, 0xD4, 0xC2, 0xC1, 0xB6, 0x40, 0x94, 0x35, 0x63, 0x98 }, /* Master key 0A encrypted with Master key 0B. */
{ 0xA3, 0x24, 0x65, 0x75, 0xEA, 0xCC, 0x6E, 0x8D, 0xFB, 0x5A, 0x16, 0x50, 0x74, 0xD2, 0x15, 0x06 }, /* Master key 0B encrypted with Master key 0C. */ { 0xA3, 0x24, 0x65, 0x75, 0xEA, 0xCC, 0x6E, 0x8D, 0xFB, 0x5A, 0x16, 0x50, 0x74, 0xD2, 0x15, 0x06 }, /* Master key 0B encrypted with Master key 0C. */
{ 0x83, 0x67, 0xAF, 0x01, 0xCF, 0x93, 0xA1, 0xAB, 0x80, 0x45, 0xF7, 0x3F, 0x72, 0xFD, 0x3B, 0x38 }, /* Master key 0C encrypted with Master key 0D. */ { 0x83, 0x67, 0xAF, 0x01, 0xCF, 0x93, 0xA1, 0xAB, 0x80, 0x45, 0xF7, 0x3F, 0x72, 0xFD, 0x3B, 0x38 }, /* Master key 0C encrypted with Master key 0D. */
{ 0xB1, 0x81, 0xA6, 0x0D, 0x72, 0xC7, 0xEE, 0x15, 0x21, 0xF3, 0xC0, 0xB5, 0x6B, 0x61, 0x6D, 0xE7 }, /* Master key 0D encrypted with Master key 0E. */
{ 0xAF, 0x11, 0x4C, 0x67, 0x17, 0x7A, 0x52, 0x43, 0xF7, 0x70, 0x2F, 0xC7, 0xEF, 0x81, 0x72, 0x16 }, /* Master key 0E encrypted with Master key 0F. */
}; };
alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySourcesDev[pkg1::KeyGeneration_Count][se::AesBlockSize] = { alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySourcesDev[pkg1::KeyGeneration_Count][se::AesBlockSize] = {
@@ -130,6 +138,8 @@ namespace ams::nxboot {
{ 0x21, 0x88, 0x6B, 0x10, 0x9E, 0x83, 0xD6, 0x52, 0xAB, 0x08, 0xDB, 0x6D, 0x39, 0xFF, 0x1C, 0x9C }, /* Master key 0A encrypted with Master key 0B. */ { 0x21, 0x88, 0x6B, 0x10, 0x9E, 0x83, 0xD6, 0x52, 0xAB, 0x08, 0xDB, 0x6D, 0x39, 0xFF, 0x1C, 0x9C }, /* Master key 0A encrypted with Master key 0B. */
{ 0x8A, 0xCE, 0xC4, 0x7F, 0xBE, 0x08, 0x61, 0x88, 0xD3, 0x73, 0x64, 0x51, 0xE2, 0xB6, 0x53, 0x15 }, /* Master key 0B encrypted with Master key 0C. */ { 0x8A, 0xCE, 0xC4, 0x7F, 0xBE, 0x08, 0x61, 0x88, 0xD3, 0x73, 0x64, 0x51, 0xE2, 0xB6, 0x53, 0x15 }, /* Master key 0B encrypted with Master key 0C. */
{ 0x08, 0xE0, 0xF4, 0xBE, 0xAA, 0x6E, 0x5A, 0xC3, 0xA6, 0xBC, 0xFE, 0xB9, 0xE2, 0xA3, 0x24, 0x12 }, /* Master key 0C encrypted with Master key 0D. */ { 0x08, 0xE0, 0xF4, 0xBE, 0xAA, 0x6E, 0x5A, 0xC3, 0xA6, 0xBC, 0xFE, 0xB9, 0xE2, 0xA3, 0x24, 0x12 }, /* Master key 0C encrypted with Master key 0D. */
{ 0xD6, 0x80, 0x98, 0xC0, 0xFA, 0xC7, 0x13, 0xCB, 0x93, 0xD2, 0x0B, 0x82, 0x4C, 0xA1, 0x7B, 0x8D }, /* Master key 0D encrypted with Master key 0E. */
{ 0x78, 0x66, 0x19, 0xBD, 0x86, 0xE7, 0xC1, 0x09, 0x9B, 0x6F, 0x92, 0xB2, 0x58, 0x7D, 0xCF, 0x26 }, /* Master key 0E encrypted with Master key 0F. */
}; };
alignas(se::AesBlockSize) constinit u8 MasterKeys[pkg1::OldMasterKeyCount][se::AesBlockSize] = {}; alignas(se::AesBlockSize) constinit u8 MasterKeys[pkg1::OldMasterKeyCount][se::AesBlockSize] = {};

View File

@@ -34,7 +34,7 @@ namespace ams::nxboot {
g_mmc_partition = partition; g_mmc_partition = partition;
} }
return ResultSuccess(); R_SUCCEED();
} }
} }
@@ -47,29 +47,29 @@ namespace ams::nxboot {
sdmmc::SetMmcWorkBuffer(MmcPort, g_mmc_work_buffer, sizeof(g_mmc_work_buffer)); sdmmc::SetMmcWorkBuffer(MmcPort, g_mmc_work_buffer, sizeof(g_mmc_work_buffer));
/* Activate the mmc. */ /* Activate the mmc. */
return sdmmc::Activate(MmcPort); R_RETURN(sdmmc::Activate(MmcPort));
} }
Result CheckMmcConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) { Result CheckMmcConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) {
return sdmmc::CheckMmcConnection(out_sm, out_bw, MmcPort); R_RETURN(sdmmc::CheckMmcConnection(out_sm, out_bw, MmcPort));
} }
Result GetMmcMemoryCapacity(u32 *out_num_sectors, sdmmc::MmcPartition partition) { Result GetMmcMemoryCapacity(u32 *out_num_sectors, sdmmc::MmcPartition partition) {
if (partition == sdmmc::MmcPartition_UserData) { if (partition == sdmmc::MmcPartition_UserData) {
return sdmmc::GetDeviceMemoryCapacity(out_num_sectors, MmcPort); R_RETURN(sdmmc::GetDeviceMemoryCapacity(out_num_sectors, MmcPort));
} else { } else {
return sdmmc::GetMmcBootPartitionCapacity(out_num_sectors, MmcPort); R_RETURN(sdmmc::GetMmcBootPartitionCapacity(out_num_sectors, MmcPort));
} }
} }
Result ReadMmc(void *dst, size_t size, sdmmc::MmcPartition partition, size_t sector_index, size_t sector_count) { Result ReadMmc(void *dst, size_t size, sdmmc::MmcPartition partition, size_t sector_index, size_t sector_count) {
R_TRY(SelectMmcPartition(partition)); R_TRY(SelectMmcPartition(partition));
return sdmmc::Read(dst, size, MmcPort, sector_index, sector_count); R_RETURN(sdmmc::Read(dst, size, MmcPort, sector_index, sector_count));
} }
Result WriteMmc(sdmmc::MmcPartition partition, size_t sector_index, size_t sector_count, const void *src, size_t size) { Result WriteMmc(sdmmc::MmcPartition partition, size_t sector_index, size_t sector_count, const void *src, size_t size) {
R_TRY(SelectMmcPartition(partition)); R_TRY(SelectMmcPartition(partition));
return sdmmc::Write(MmcPort, sector_index, sector_count, src, size); R_RETURN(sdmmc::Write(MmcPort, sector_index, sector_count, src, size));
} }
} }

View File

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

View File

@@ -78,7 +78,7 @@ namespace ams::nxboot {
sdmmc::SetSdCardWorkBuffer(SdCardPort, g_sd_work_buffer, sizeof(g_sd_work_buffer)); sdmmc::SetSdCardWorkBuffer(SdCardPort, g_sd_work_buffer, sizeof(g_sd_work_buffer));
/* Activate the SD card. */ /* Activate the SD card. */
return sdmmc::Activate(SdCardPort); R_RETURN(sdmmc::Activate(SdCardPort));
} }
void FinalizeSdCard() { void FinalizeSdCard() {
@@ -90,19 +90,19 @@ namespace ams::nxboot {
} }
Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) { Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) {
return sdmmc::CheckSdCardConnection(out_sm, out_bw, SdCardPort); R_RETURN(sdmmc::CheckSdCardConnection(out_sm, out_bw, SdCardPort));
} }
Result GetSdCardMemoryCapacity(u32 *out_num_sectors) { Result GetSdCardMemoryCapacity(u32 *out_num_sectors) {
return sdmmc::GetDeviceMemoryCapacity(out_num_sectors, SdCardPort); R_RETURN(sdmmc::GetDeviceMemoryCapacity(out_num_sectors, SdCardPort));
} }
Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count) { Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count) {
return sdmmc::Read(dst, size, SdCardPort, sector_index, sector_count); R_RETURN(sdmmc::Read(dst, size, SdCardPort, sector_index, sector_count));
} }
Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size) { Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size) {
return sdmmc::Write(SdCardPort, sector_index, sector_count, src, size); R_RETURN(sdmmc::Write(SdCardPort, sector_index, sector_count, src, size));
} }
} }

View File

@@ -253,6 +253,10 @@ namespace ams::nxboot {
return ams::TargetFirmware_13_2_1; return ams::TargetFirmware_13_2_1;
} else if (std::memcmp(package1 + 0x10, "20220209", 8) == 0) { } else if (std::memcmp(package1 + 0x10, "20220209", 8) == 0) {
return ams::TargetFirmware_14_0_0; return ams::TargetFirmware_14_0_0;
} else if (std::memcmp(package1 + 0x10, "20220801", 8) == 0) {
return ams::TargetFirmware_15_0_0;
} else if (std::memcmp(package1 + 0x10, "20230111", 8) == 0) {
return ams::TargetFirmware_16_0_0;
} }
break; break;
default: default:

View File

@@ -156,6 +156,15 @@ namespace ams::nxboot {
FsVersion_14_0_0, FsVersion_14_0_0,
FsVersion_14_0_0_Exfat, FsVersion_14_0_0_Exfat,
FsVersion_15_0_0,
FsVersion_15_0_0_Exfat,
FsVersion_16_0_0,
FsVersion_16_0_0_Exfat,
FsVersion_16_0_3,
FsVersion_16_0_3_Exfat,
FsVersion_Count, FsVersion_Count,
}; };
@@ -227,6 +236,15 @@ namespace ams::nxboot {
{ 0x88, 0x7A, 0xC1, 0x50, 0x80, 0x6C, 0x75, 0xCC }, /* FsVersion_14_0_0 */ { 0x88, 0x7A, 0xC1, 0x50, 0x80, 0x6C, 0x75, 0xCC }, /* FsVersion_14_0_0 */
{ 0xD4, 0x88, 0xD1, 0xF2, 0x92, 0x17, 0x35, 0x5C }, /* FsVersion_14_0_0_Exfat */ { 0xD4, 0x88, 0xD1, 0xF2, 0x92, 0x17, 0x35, 0x5C }, /* FsVersion_14_0_0_Exfat */
{ 0xD0, 0xD4, 0x49, 0x18, 0x14, 0xB5, 0x62, 0xAF }, /* FsVersion_15_0_0 */
{ 0x34, 0xC0, 0xD9, 0xED, 0x6A, 0xD1, 0x87, 0x3D }, /* FsVersion_15_0_0_Exfat */
{ 0x56, 0xE8, 0x56, 0x56, 0x6C, 0x38, 0xD8, 0xBE }, /* FsVersion_16_0_0 */
{ 0xCF, 0xAB, 0x45, 0x0C, 0x2C, 0x53, 0x9D, 0xA9 }, /* FsVersion_16_0_0_Exfat */
{ 0x39, 0xEE, 0x1F, 0x1E, 0x0E, 0xA7, 0x32, 0x5D }, /* FsVersion_16_0_3 */
{ 0x62, 0xC6, 0x5E, 0xFD, 0x9A, 0xBF, 0x7C, 0x43 }, /* FsVersion_16_0_3_Exfat */
}; };
const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) { const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) {
@@ -628,6 +646,30 @@ namespace ams::nxboot {
AddPatch(fs_meta, 0x195769, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x195769, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x16F6B0, NogcPatch1, sizeof(NogcPatch1)); AddPatch(fs_meta, 0x16F6B0, NogcPatch1, sizeof(NogcPatch1));
break; break;
case FsVersion_15_0_0:
AddPatch(fs_meta, 0x184259, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x15EDE4, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_15_0_0_Exfat:
AddPatch(fs_meta, 0x18F1E9, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x169D74, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_16_0_0:
AddPatch(fs_meta, 0x1866D9, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x160C70, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_16_0_0_Exfat:
AddPatch(fs_meta, 0x1913B9, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x16B950, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_16_0_3:
AddPatch(fs_meta, 0x186729, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x160CC0, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_16_0_3_Exfat:
AddPatch(fs_meta, 0x191409, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x16B9A0, NogcPatch1, sizeof(NogcPatch1));
break;
default: default:
break; break;
} }

View File

@@ -85,7 +85,6 @@ namespace ams::nxboot {
HANDLE_DRAM_CASE( 3, 12) HANDLE_DRAM_CASE( 3, 12)
HANDLE_DRAM_CASE( 5, 12) HANDLE_DRAM_CASE( 5, 12)
HANDLE_DRAM_CASE( 6, 12) HANDLE_DRAM_CASE( 6, 12)
HANDLE_DRAM_CASE( 7, 0)
HANDLE_DRAM_CASE( 8, 1) HANDLE_DRAM_CASE( 8, 1)
HANDLE_DRAM_CASE( 9, 2) HANDLE_DRAM_CASE( 9, 2)
HANDLE_DRAM_CASE(10, 3) HANDLE_DRAM_CASE(10, 3)
@@ -94,7 +93,6 @@ namespace ams::nxboot {
HANDLE_DRAM_CASE(13, 2) HANDLE_DRAM_CASE(13, 2)
HANDLE_DRAM_CASE(14, 3) HANDLE_DRAM_CASE(14, 3)
HANDLE_DRAM_CASE(15, 4) HANDLE_DRAM_CASE(15, 4)
HANDLE_DRAM_CASE(16, 5)
HANDLE_DRAM_CASE(17, 6) HANDLE_DRAM_CASE(17, 6)
HANDLE_DRAM_CASE(18, 7) HANDLE_DRAM_CASE(18, 7)
HANDLE_DRAM_CASE(19, 6) HANDLE_DRAM_CASE(19, 6)
@@ -107,6 +105,12 @@ namespace ams::nxboot {
HANDLE_DRAM_CASE(26, 11) HANDLE_DRAM_CASE(26, 11)
HANDLE_DRAM_CASE(27, 11) HANDLE_DRAM_CASE(27, 11)
HANDLE_DRAM_CASE(28, 7) HANDLE_DRAM_CASE(28, 7)
HANDLE_DRAM_CASE(29, 0)
HANDLE_DRAM_CASE(30, 0)
HANDLE_DRAM_CASE(31, 0)
HANDLE_DRAM_CASE(32, 5)
HANDLE_DRAM_CASE(33, 5)
HANDLE_DRAM_CASE(34, 5)
default: default:
AMS_ABORT("Invalid DRAM id"); AMS_ABORT("Invalid DRAM id");
} }

View File

@@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master branch = master
commit = 0d161b8588aa6482b84f3c44dd001055b01a047f commit = c3dc418a28e390bc57426016aa2c9e7e87d7a584
parent = 4efa5d7dd0bfbdf89a6261af0aef3878ca784b05 parent = e488b6ee478f5b3a0380e75e4b468e1e4b1d816f
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.1

View File

@@ -1,5 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_WINDOWS export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_WINDOWS
export ATMOSPHERE_SETTINGS += -fno-omit-frame-pointer export ATMOSPHERE_SETTINGS += -fno-omit-frame-pointer -fno-data-sections
export ATMOSPHERE_CFLAGS += export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS += export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS += export ATMOSPHERE_ASFLAGS +=

View File

@@ -58,7 +58,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,exit -Wl,--wrap,exit
else ifeq ($(ATMOSPHERE_BOARD),generic_windows) else ifeq ($(ATMOSPHERE_BOARD),generic_windows)
export CXXREQUIRED := export CXXREQUIRED :=
export CXXWRAPS := -Wl,--wrap,__p__acmdln export CXXWRAPS := -Wl,--wrap,__p__acmdln -Wl,--wrap,_set_invalid_parameter_handler
else else
export CXXREQUIRED := export CXXREQUIRED :=
export CXXWRAPS := export CXXWRAPS :=
@@ -67,6 +67,8 @@ endif
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001) ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map) export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map)
else ifeq ($(ATMOSPHERE_OS_NAME),macos)
export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-map,$(notdir $@.map)
else else
export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $@.map) export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $@.map)
endif endif

View File

@@ -55,7 +55,7 @@ namespace ams::fuse {
DramId_IcosaSamsung6GB = 4, DramId_IcosaSamsung6GB = 4,
DramId_HoagHynix1y4GB = 5, DramId_HoagHynix1y4GB = 5,
DramId_AulaHynix1y4GB = 6, DramId_AulaHynix1y4GB = 6,
DramId_IowaX1X2Samsung4GB = 7, DramId_Deprecated7 = 7,
DramId_IowaSansung4GB = 8, DramId_IowaSansung4GB = 8,
DramId_IowaSamsung8GB = 9, DramId_IowaSamsung8GB = 9,
DramId_IowaHynix4GB = 10, DramId_IowaHynix4GB = 10,
@@ -64,7 +64,7 @@ namespace ams::fuse {
DramId_HoagSamsung8GB = 13, DramId_HoagSamsung8GB = 13,
DramId_HoagHynix4GB = 14, DramId_HoagHynix4GB = 14,
DramId_HoagMicron4GB = 15, DramId_HoagMicron4GB = 15,
DramId_IowaSamsung4GBY = 16, DramId_Deprecated16 = 16,
DramId_IowaSamsung1y4GBX = 17, DramId_IowaSamsung1y4GBX = 17,
DramId_IowaSamsung1y8GBX = 18, DramId_IowaSamsung1y8GBX = 18,
DramId_HoagSamsung1y4GBX = 19, DramId_HoagSamsung1y4GBX = 19,
@@ -77,6 +77,12 @@ namespace ams::fuse {
DramId_HoagMicron1y4GB = 26, DramId_HoagMicron1y4GB = 26,
DramId_AulaMicron1y4GB = 27, DramId_AulaMicron1y4GB = 27,
DramId_AulaSamsung1y8GBX = 28, DramId_AulaSamsung1y8GBX = 28,
DramId_IowaX1X2Samsung4GB = 29,
DramId_HoagX1X2Samsung4GB = 30,
DramId_AulaX1X2Samsung4GB = 31,
DramId_IowaSamsung4GBY = 32,
DramId_HoagSamsung4GBY = 33,
DramId_AulaSamsung4GBY = 34,
DramId_Count, DramId_Count,
}; };
@@ -119,4 +125,4 @@ namespace ams::fuse {
bool IsOdmProductionMode(); bool IsOdmProductionMode();
void ConfigureFuseBypass(); void ConfigureFuseBypass();
} }

View File

@@ -27,7 +27,7 @@ namespace ams::pkg1 {
enum MemoryArrange { enum MemoryArrange {
MemoryArrange_Normal = 1, MemoryArrange_Normal = 1,
MemoryArrange_AppletDev = 2, MemoryArrange_AppletDev = 2,
MemoryArrange_SystemDev = 2, MemoryArrange_SystemDev = 3,
}; };
enum MemoryMode { enum MemoryMode {

View File

@@ -34,6 +34,8 @@ namespace ams::pkg1 {
KeyGeneration_12_1_0 = 0x0B, KeyGeneration_12_1_0 = 0x0B,
KeyGeneration_13_0_0 = 0x0C, KeyGeneration_13_0_0 = 0x0C,
KeyGeneration_14_0_0 = 0x0D, KeyGeneration_14_0_0 = 0x0D,
KeyGeneration_15_0_0 = 0x0E,
KeyGeneration_16_0_0 = 0x0F,
KeyGeneration_Count, KeyGeneration_Count,

View File

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

View File

@@ -39,12 +39,13 @@ namespace ams::fuse {
struct OdmWord4 { struct OdmWord4 {
using HardwareState1 = util::BitPack32::Field<0, 2, int>; using HardwareState1 = util::BitPack32::Field<0, 2, int>;
using HardwareType1 = util::BitPack32::Field<HardwareState1::Next, 1, int>; using HardwareType1 = util::BitPack32::Field<HardwareState1::Next, 1, int>;
using DramId = util::BitPack32::Field<HardwareType1::Next, 5, int>; using DramId1 = util::BitPack32::Field<HardwareType1::Next, 5, int>;
using HardwareType2 = util::BitPack32::Field<DramId::Next, 1, int>; using HardwareType2 = util::BitPack32::Field<DramId1::Next, 1, int>;
using HardwareState2 = util::BitPack32::Field<HardwareType2::Next, 1, int>; using HardwareState2 = util::BitPack32::Field<HardwareType2::Next, 1, int>;
using RetailInteractiveDisplayState = util::BitPack32::Field<HardwareState2::Next, 1, int>; using RetailInteractiveDisplayState = util::BitPack32::Field<HardwareState2::Next, 1, int>;
using FormatVersion = util::BitPack32::Field<RetailInteractiveDisplayState::Next, 1, int>; using FormatVersion = util::BitPack32::Field<RetailInteractiveDisplayState::Next, 1, int>;
using Reserved = util::BitPack32::Field<FormatVersion::Next, 4, int>; using DramId2 = util::BitPack32::Field<FormatVersion::Next, 3, int>;
using Reserved = util::BitPack32::Field<DramId2::Next, 1, int>;
using HardwareType3 = util::BitPack32::Field<Reserved::Next, 4, int>; using HardwareType3 = util::BitPack32::Field<Reserved::Next, 4, int>;
}; };
@@ -71,6 +72,15 @@ namespace ams::fuse {
(odm_word4.Get<OdmWord4::HardwareType3>() << HardwareType3Shift); (odm_word4.Get<OdmWord4::HardwareType3>() << HardwareType3Shift);
} }
constexpr ALWAYS_INLINE int GetDramIdValue(const util::BitPack32 odm_word4) {
constexpr auto DramId1Shift = 0;
constexpr auto DramId2Shift = OdmWord4::DramId1::Count + DramId1Shift;
return (odm_word4.Get<OdmWord4::DramId1>() << DramId1Shift) |
(odm_word4.Get<OdmWord4::DramId2>() << DramId2Shift);
}
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceFuses.GetAddress(); constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceFuses.GetAddress();
constinit bool g_checked_for_rcm_bug_patch = false; constinit bool g_checked_for_rcm_bug_patch = false;
@@ -167,6 +177,8 @@ namespace ams::fuse {
} }
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = { constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
TargetFirmware_16_0_0,
TargetFirmware_15_0_0,
TargetFirmware_13_2_1, TargetFirmware_13_2_1,
TargetFirmware_12_0_2, TargetFirmware_12_0_2,
TargetFirmware_11_0_0, TargetFirmware_11_0_0,
@@ -305,7 +317,8 @@ namespace ams::fuse {
} }
DramId GetDramId() { DramId GetDramId() {
return static_cast<DramId>(util::BitPack32{GetCommonOdmWord(4)}.Get<OdmWord4::DramId>()); /* Get the value. */
return static_cast<DramId>(GetDramIdValue(util::BitPack32{GetCommonOdmWord(4)}));
} }
HardwareType GetHardwareType() { HardwareType GetHardwareType() {

View File

@@ -29,8 +29,6 @@ namespace ams::kern::init {
u64 sp; u64 sp;
u64 entrypoint; u64 entrypoint;
u64 argument; u64 argument;
u64 setup_function;
u64 exception_stack;
}; };
static_assert(alignof(KInitArguments) == util::CeilingPowerOfTwo(INIT_ARGUMENTS_SIZE)); static_assert(alignof(KInitArguments) == util::CeilingPowerOfTwo(INIT_ARGUMENTS_SIZE));
static_assert(sizeof(KInitArguments) == std::max(INIT_ARGUMENTS_SIZE, util::CeilingPowerOfTwo(INIT_ARGUMENTS_SIZE))); static_assert(sizeof(KInitArguments) == std::max(INIT_ARGUMENTS_SIZE, util::CeilingPowerOfTwo(INIT_ARGUMENTS_SIZE)));
@@ -45,7 +43,5 @@ namespace ams::kern::init {
static_assert(AMS_OFFSETOF(KInitArguments, sp) == INIT_ARGUMENTS_SP); static_assert(AMS_OFFSETOF(KInitArguments, sp) == INIT_ARGUMENTS_SP);
static_assert(AMS_OFFSETOF(KInitArguments, entrypoint) == INIT_ARGUMENTS_ENTRYPOINT); static_assert(AMS_OFFSETOF(KInitArguments, entrypoint) == INIT_ARGUMENTS_ENTRYPOINT);
static_assert(AMS_OFFSETOF(KInitArguments, argument) == INIT_ARGUMENTS_ARGUMENT); static_assert(AMS_OFFSETOF(KInitArguments, argument) == INIT_ARGUMENTS_ARGUMENT);
static_assert(AMS_OFFSETOF(KInitArguments, setup_function) == INIT_ARGUMENTS_SETUP_FUNCTION);
static_assert(AMS_OFFSETOF(KInitArguments, exception_stack) == INIT_ARGUMENTS_EXCEPTION_STACK);
} }

View File

@@ -23,17 +23,6 @@
namespace ams::kern::arch::arm64::init { namespace ams::kern::arch::arm64::init {
inline void ClearPhysicalMemory(KPhysicalAddress address, size_t size) {
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(size, sizeof(u64)));
/* This Physical Address -> void * conversion is valid, because this is init page table code. */
/* The MMU is necessarily not yet turned on, if we are creating an initial page table. */
volatile u64 *ptr = reinterpret_cast<volatile u64 *>(GetInteger(address));
for (size_t i = 0; i < size / sizeof(u64); ++i) {
ptr[i] = 0;
}
}
/* NOTE: Nintendo uses virtual functions, rather than a concept + template. */ /* NOTE: Nintendo uses virtual functions, rather than a concept + template. */
template<typename T> template<typename T>
concept IsInitialPageAllocator = requires (T &t, KPhysicalAddress phys_addr, size_t size) { concept IsInitialPageAllocator = requires (T &t, KPhysicalAddress phys_addr, size_t size) {
@@ -41,25 +30,23 @@ namespace ams::kern::arch::arm64::init {
{ t.Free(phys_addr, size) } -> std::same_as<void>; { t.Free(phys_addr, size) } -> std::same_as<void>;
}; };
template<IsInitialPageAllocator _PageAllocator> class KInitialPageTable {
class KInitialPageTableTemplate {
public:
using PageAllocator = _PageAllocator;
private: private:
KPhysicalAddress m_l1_tables[2]; KPhysicalAddress m_l1_tables[2];
u32 m_num_entries[2]; u32 m_num_entries[2];
public: public:
KInitialPageTableTemplate(KVirtualAddress start_address, KVirtualAddress end_address, PageAllocator &allocator) { template<IsInitialPageAllocator PageAllocator>
KInitialPageTable(KVirtualAddress start_address, KVirtualAddress end_address, PageAllocator &allocator) {
/* Set tables. */ /* Set tables. */
m_l1_tables[0] = AllocateNewPageTable(allocator); m_l1_tables[0] = AllocateNewPageTable(allocator, 0);
m_l1_tables[1] = AllocateNewPageTable(allocator); m_l1_tables[1] = AllocateNewPageTable(allocator, 0);
/* Set counts. */ /* Set counts. */
m_num_entries[0] = MaxPageTableEntries; m_num_entries[0] = MaxPageTableEntries;
m_num_entries[1] = ((end_address / L1BlockSize) & (MaxPageTableEntries - 1)) - ((start_address / L1BlockSize) & (MaxPageTableEntries - 1)) + 1; m_num_entries[1] = ((end_address / L1BlockSize) & (MaxPageTableEntries - 1)) - ((start_address / L1BlockSize) & (MaxPageTableEntries - 1)) + 1;
} }
KInitialPageTableTemplate() { KInitialPageTable() {
/* Set tables. */ /* Set tables. */
m_l1_tables[0] = util::AlignDown(cpu::GetTtbr0El1(), PageSize); m_l1_tables[0] = util::AlignDown(cpu::GetTtbr0El1(), PageSize);
m_l1_tables[1] = util::AlignDown(cpu::GetTtbr1El1(), PageSize); m_l1_tables[1] = util::AlignDown(cpu::GetTtbr1El1(), PageSize);
@@ -82,30 +69,35 @@ namespace ams::kern::arch::arm64::init {
return GetInteger(m_l1_tables[1]); return GetInteger(m_l1_tables[1]);
} }
private: private:
constexpr ALWAYS_INLINE L1PageTableEntry *GetL1Entry(KVirtualAddress address) const { constexpr ALWAYS_INLINE L1PageTableEntry *GetL1Entry(KVirtualAddress address, u64 phys_to_virt_offset = 0) const {
const size_t index = (GetInteger(address) >> (BITSIZEOF(address) - 1)) & 1; const size_t index = (GetInteger(address) >> (BITSIZEOF(address) - 1)) & 1;
L1PageTableEntry *l1_table = reinterpret_cast<L1PageTableEntry *>(GetInteger(m_l1_tables[index])); L1PageTableEntry *l1_table = reinterpret_cast<L1PageTableEntry *>(GetInteger(m_l1_tables[index]) + phys_to_virt_offset);
return l1_table + ((GetInteger(address) / L1BlockSize) & (m_num_entries[index] - 1)); return l1_table + ((GetInteger(address) / L1BlockSize) & (m_num_entries[index] - 1));
} }
static constexpr ALWAYS_INLINE L2PageTableEntry *GetL2Entry(const L1PageTableEntry *entry, KVirtualAddress address) { static constexpr ALWAYS_INLINE L2PageTableEntry *GetL2Entry(const L1PageTableEntry *entry, KVirtualAddress address, u64 phys_to_virt_offset = 0) {
L2PageTableEntry *l2_table = reinterpret_cast<L2PageTableEntry *>(GetInteger(entry->GetTable())); L2PageTableEntry *l2_table = reinterpret_cast<L2PageTableEntry *>(GetInteger(entry->GetTable()) + phys_to_virt_offset);
return l2_table + ((GetInteger(address) / L2BlockSize) & (MaxPageTableEntries - 1)); return l2_table + ((GetInteger(address) / L2BlockSize) & (MaxPageTableEntries - 1));
} }
static constexpr ALWAYS_INLINE L3PageTableEntry *GetL3Entry(const L2PageTableEntry *entry, KVirtualAddress address) { static constexpr ALWAYS_INLINE L3PageTableEntry *GetL3Entry(const L2PageTableEntry *entry, KVirtualAddress address, u64 phys_to_virt_offset = 0) {
L3PageTableEntry *l3_table = reinterpret_cast<L3PageTableEntry *>(GetInteger(entry->GetTable())); L3PageTableEntry *l3_table = reinterpret_cast<L3PageTableEntry *>(GetInteger(entry->GetTable()) + phys_to_virt_offset);
return l3_table + ((GetInteger(address) / L3BlockSize) & (MaxPageTableEntries - 1)); return l3_table + ((GetInteger(address) / L3BlockSize) & (MaxPageTableEntries - 1));
} }
static ALWAYS_INLINE KPhysicalAddress AllocateNewPageTable(PageAllocator &allocator) { template<IsInitialPageAllocator PageAllocator>
static ALWAYS_INLINE KPhysicalAddress AllocateNewPageTable(PageAllocator &allocator, u64 phys_to_virt_offset) {
auto address = allocator.Allocate(PageSize); auto address = allocator.Allocate(PageSize);
ClearNewPageTable(address); ClearNewPageTable(address, phys_to_virt_offset);
return address; return address;
} }
static ALWAYS_INLINE void ClearNewPageTable(KPhysicalAddress address) { static ALWAYS_INLINE void ClearNewPageTable(KPhysicalAddress address, u64 phys_to_virt_offset) {
ClearPhysicalMemory(address, PageSize); /* Convert to a deferenceable address, and clear. */
volatile u64 *ptr = reinterpret_cast<volatile u64 *>(GetInteger(address) + phys_to_virt_offset);
for (size_t i = 0; i < PageSize / sizeof(u64); ++i) {
ptr[i] = 0;
}
} }
public: public:
static consteval size_t GetMaximumOverheadSize(size_t size) { static consteval size_t GetMaximumOverheadSize(size_t size) {
@@ -327,7 +319,8 @@ namespace ams::kern::arch::arm64::init {
} }
} }
public: public:
void NOINLINE Map(KVirtualAddress virt_addr, size_t size, KPhysicalAddress phys_addr, const PageTableEntry &attr, PageAllocator &allocator) { template<IsInitialPageAllocator PageAllocator>
void NOINLINE Map(KVirtualAddress virt_addr, size_t size, KPhysicalAddress phys_addr, const PageTableEntry &attr, PageAllocator &allocator, u64 phys_to_virt_offset) {
/* Ensure that addresses and sizes are page aligned. */ /* Ensure that addresses and sizes are page aligned. */
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), PageSize)); MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), PageSize));
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(phys_addr), PageSize)); MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(phys_addr), PageSize));
@@ -335,7 +328,7 @@ namespace ams::kern::arch::arm64::init {
/* Iteratively map pages until the requested region is mapped. */ /* Iteratively map pages until the requested region is mapped. */
while (size > 0) { while (size > 0) {
L1PageTableEntry *l1_entry = this->GetL1Entry(virt_addr); L1PageTableEntry *l1_entry = this->GetL1Entry(virt_addr, phys_to_virt_offset);
/* Can we make an L1 block? */ /* Can we make an L1 block? */
if (util::IsAligned(GetInteger(virt_addr), L1BlockSize) && util::IsAligned(GetInteger(phys_addr), L1BlockSize) && size >= L1BlockSize) { if (util::IsAligned(GetInteger(virt_addr), L1BlockSize) && util::IsAligned(GetInteger(phys_addr), L1BlockSize) && size >= L1BlockSize) {
@@ -349,12 +342,12 @@ namespace ams::kern::arch::arm64::init {
/* If we don't already have an L2 table, we need to make a new one. */ /* If we don't already have an L2 table, we need to make a new one. */
if (!l1_entry->IsTable()) { if (!l1_entry->IsTable()) {
KPhysicalAddress new_table = AllocateNewPageTable(allocator); KPhysicalAddress new_table = AllocateNewPageTable(allocator, phys_to_virt_offset);
cpu::DataSynchronizationBarrierInnerShareable(); cpu::DataSynchronizationBarrierInnerShareable();
*l1_entry = L1PageTableEntry(PageTableEntry::TableTag{}, new_table, attr.IsPrivilegedExecuteNever()); *l1_entry = L1PageTableEntry(PageTableEntry::TableTag{}, new_table, attr.IsPrivilegedExecuteNever());
} }
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr); L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr, phys_to_virt_offset);
/* Can we make a contiguous L2 block? */ /* Can we make a contiguous L2 block? */
if (util::IsAligned(GetInteger(virt_addr), L2ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L2ContiguousBlockSize) && size >= L2ContiguousBlockSize) { if (util::IsAligned(GetInteger(virt_addr), L2ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L2ContiguousBlockSize) && size >= L2ContiguousBlockSize) {
@@ -380,12 +373,12 @@ namespace ams::kern::arch::arm64::init {
/* If we don't already have an L3 table, we need to make a new one. */ /* If we don't already have an L3 table, we need to make a new one. */
if (!l2_entry->IsTable()) { if (!l2_entry->IsTable()) {
KPhysicalAddress new_table = AllocateNewPageTable(allocator); KPhysicalAddress new_table = AllocateNewPageTable(allocator, phys_to_virt_offset);
cpu::DataSynchronizationBarrierInnerShareable(); cpu::DataSynchronizationBarrierInnerShareable();
*l2_entry = L2PageTableEntry(PageTableEntry::TableTag{}, new_table, attr.IsPrivilegedExecuteNever()); *l2_entry = L2PageTableEntry(PageTableEntry::TableTag{}, new_table, attr.IsPrivilegedExecuteNever());
} }
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr); L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr, phys_to_virt_offset);
/* Can we make a contiguous L3 block? */ /* Can we make a contiguous L3 block? */
if (util::IsAligned(GetInteger(virt_addr), L3ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L3ContiguousBlockSize) && size >= L3ContiguousBlockSize) { if (util::IsAligned(GetInteger(virt_addr), L3ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L3ContiguousBlockSize) && size >= L3ContiguousBlockSize) {
@@ -410,6 +403,98 @@ namespace ams::kern::arch::arm64::init {
cpu::DataSynchronizationBarrierInnerShareable(); cpu::DataSynchronizationBarrierInnerShareable();
} }
void UnmapTtbr0Entries(u64 phys_to_virt_offset) {
/* Ensure data consistency before we unmap. */
cpu::DataSynchronizationBarrierInnerShareable();
/* Define helper, as we only want to clear non-nGnRE pages. */
constexpr auto ShouldUnmap = [](const PageTableEntry *entry) ALWAYS_INLINE_LAMBDA -> bool {
return entry->GetPageAttribute() != PageTableEntry::PageAttribute_Device_nGnRE;
};
/* Iterate all L1 entries. */
L1PageTableEntry * const l1_table = reinterpret_cast<L1PageTableEntry *>(GetInteger(m_l1_tables[0]) + phys_to_virt_offset);
for (size_t l1_index = 0; l1_index < m_num_entries[0]; l1_index++) {
/* Get L1 entry. */
L1PageTableEntry * const l1_entry = l1_table + l1_index;
if (l1_entry->IsBlock()) {
/* Unmap the L1 entry, if we should. */
if (ShouldUnmap(l1_entry)) {
*static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry;
}
} else if (l1_entry->IsTable()) {
/* Get the L2 table. */
L2PageTableEntry * const l2_table = reinterpret_cast<L2PageTableEntry *>(GetInteger(l1_entry->GetTable()) + phys_to_virt_offset);
/* Unmap all L2 entries, as relevant. */
size_t remaining_l2_entries = 0;
for (size_t l2_index = 0; l2_index < MaxPageTableEntries; ++l2_index) {
/* Get L2 entry. */
L2PageTableEntry * const l2_entry = l2_table + l2_index;
if (l2_entry->IsBlock()) {
const size_t num_to_clear = (l2_entry->IsContiguous() ? L2ContiguousBlockSize : L2BlockSize) / L2BlockSize;
if (ShouldUnmap(l2_entry)) {
for (size_t i = 0; i < num_to_clear; ++i) {
static_cast<PageTableEntry *>(l2_entry)[i] = InvalidPageTableEntry;
}
} else {
remaining_l2_entries += num_to_clear;
}
l2_index = l2_index + num_to_clear - 1;
} else if (l2_entry->IsTable()) {
/* Get the L3 table. */
L3PageTableEntry * const l3_table = reinterpret_cast<L3PageTableEntry *>(GetInteger(l2_entry->GetTable()) + phys_to_virt_offset);
/* Unmap all L3 entries, as relevant. */
size_t remaining_l3_entries = 0;
for (size_t l3_index = 0; l3_index < MaxPageTableEntries; ++l3_index) {
/* Get L3 entry. */
if (L3PageTableEntry * const l3_entry = l3_table + l3_index; l3_entry->IsBlock()) {
const size_t num_to_clear = (l3_entry->IsContiguous() ? L3ContiguousBlockSize : L3BlockSize) / L3BlockSize;
if (ShouldUnmap(l3_entry)) {
for (size_t i = 0; i < num_to_clear; ++i) {
static_cast<PageTableEntry *>(l3_entry)[i] = InvalidPageTableEntry;
}
} else {
remaining_l3_entries += num_to_clear;
}
l3_index = l3_index + num_to_clear - 1;
}
}
/* If we unmapped all L3 entries, clear the L2 entry. */
if (remaining_l3_entries == 0) {
*static_cast<PageTableEntry *>(l2_entry) = InvalidPageTableEntry;
/* Invalidate the entire tlb. */
cpu::DataSynchronizationBarrierInnerShareable();
cpu::InvalidateEntireTlb();
} else {
remaining_l2_entries++;
}
}
}
/* If we unmapped all L2 entries, clear the L1 entry. */
if (remaining_l2_entries == 0) {
*static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry;
/* Invalidate the entire tlb. */
cpu::DataSynchronizationBarrierInnerShareable();
cpu::InvalidateEntireTlb();
}
}
}
/* Invalidate the entire tlb. */
cpu::DataSynchronizationBarrierInnerShareable();
cpu::InvalidateEntireTlb();
}
KPhysicalAddress GetPhysicalAddress(KVirtualAddress virt_addr) const { KPhysicalAddress GetPhysicalAddress(KVirtualAddress virt_addr) const {
/* Get the L1 entry. */ /* Get the L1 entry. */
const L1PageTableEntry *l1_entry = this->GetL1Entry(virt_addr); const L1PageTableEntry *l1_entry = this->GetL1Entry(virt_addr);
@@ -861,6 +946,4 @@ namespace ams::kern::arch::arm64::init {
}; };
static_assert(IsInitialPageAllocator<KInitialPageAllocator>); static_assert(IsInitialPageAllocator<KInitialPageAllocator>);
using KInitialPageTable = KInitialPageTableTemplate<KInitialPageAllocator>;
} }

View File

@@ -23,7 +23,7 @@
#define THREAD_KERNEL_STACK_TOP 0x280 #define THREAD_KERNEL_STACK_TOP 0x280
/* ams::kern::KThread::StackParameters, https://github.com/Atmosphere-NX/Atmosphere/blob/master/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp */ /* ams::kern::KThread::StackParameters, https://github.com/Atmosphere-NX/Atmosphere/blob/master/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp */
#define THREAD_STACK_PARAMETERS_SIZE 0x130 #define THREAD_STACK_PARAMETERS_SIZE 0x140
#define THREAD_STACK_PARAMETERS_SVC_PERMISSION 0x00 #define THREAD_STACK_PARAMETERS_SVC_PERMISSION 0x00
#define THREAD_STACK_PARAMETERS_CALLER_SAVE_FPU_REGISTERS 0x18 #define THREAD_STACK_PARAMETERS_CALLER_SAVE_FPU_REGISTERS 0x18
#define THREAD_STACK_PARAMETERS_CUR_THREAD 0x20 #define THREAD_STACK_PARAMETERS_CUR_THREAD 0x20
@@ -34,7 +34,8 @@
#define THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS 0x2D #define THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS 0x2D
#define THREAD_STACK_PARAMETERS_IS_PINNED 0x2E #define THREAD_STACK_PARAMETERS_IS_PINNED 0x2E
#define THREAD_STACK_PARAMETERS_RESERVED_2F 0x2F #define THREAD_STACK_PARAMETERS_RESERVED_2F 0x2F
#define THREAD_STACK_PARAMETERS_THREAD_CONTEXT 0x30 #define THREAD_STACK_PARAMETERS_RESERVED_30 0x30
#define THREAD_STACK_PARAMETERS_THREAD_CONTEXT 0x40
#define THREAD_EXCEPTION_FLAG_BIT_INDEX_IS_CALLING_SVC (0) #define THREAD_EXCEPTION_FLAG_BIT_INDEX_IS_CALLING_SVC (0)
#define THREAD_EXCEPTION_FLAG_BIT_INDEX_IS_IN_EXCEPTION_HANDLER (1) #define THREAD_EXCEPTION_FLAG_BIT_INDEX_IS_IN_EXCEPTION_HANDLER (1)
@@ -245,7 +246,7 @@
#define THREAD_LOCAL_REGION_SIZE 0x200 #define THREAD_LOCAL_REGION_SIZE 0x200
/* ams::kern::init::KInitArguments, https://github.com/Atmosphere-NX/Atmosphere/blob/master/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_arguments.hpp */ /* ams::kern::init::KInitArguments, https://github.com/Atmosphere-NX/Atmosphere/blob/master/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_arguments.hpp */
#define INIT_ARGUMENTS_SIZE 0x60 #define INIT_ARGUMENTS_SIZE 0x50
#define INIT_ARGUMENTS_TTBR0 0x00 #define INIT_ARGUMENTS_TTBR0 0x00
#define INIT_ARGUMENTS_TTBR1 0x08 #define INIT_ARGUMENTS_TTBR1 0x08
#define INIT_ARGUMENTS_TCR 0x10 #define INIT_ARGUMENTS_TCR 0x10
@@ -256,14 +257,12 @@
#define INIT_ARGUMENTS_SP 0x38 #define INIT_ARGUMENTS_SP 0x38
#define INIT_ARGUMENTS_ENTRYPOINT 0x40 #define INIT_ARGUMENTS_ENTRYPOINT 0x40
#define INIT_ARGUMENTS_ARGUMENT 0x48 #define INIT_ARGUMENTS_ARGUMENT 0x48
#define INIT_ARGUMENTS_SETUP_FUNCTION 0x50
#define INIT_ARGUMENTS_EXCEPTION_STACK 0x58
/* ams::kern::KScheduler (::SchedulingState), https://github.com/Atmosphere-NX/Atmosphere/blob/master/libraries/libmesosphere/include/mesosphere/kern_k_scheduler.hpp */ /* ams::kern::KScheduler (::SchedulingState), https://github.com/Atmosphere-NX/Atmosphere/blob/master/libraries/libmesosphere/include/mesosphere/kern_k_scheduler.hpp */
/* NOTE: Due to constraints on ldarb relative offsets, KSCHEDULER_NEEDS_SCHEDULING cannot trivially be changed, and will require assembly edits. */ /* NOTE: Due to constraints on ldarb relative offsets, KSCHEDULER_NEEDS_SCHEDULING cannot trivially be changed, and will require assembly edits. */
#define KSCHEDULER_NEEDS_SCHEDULING 0x00 #define KSCHEDULER_NEEDS_SCHEDULING 0x00
#define KSCHEDULER_INTERRUPT_TASK_RUNNABLE 0x01 #define KSCHEDULER_INTERRUPT_TASK_RUNNABLE 0x01
#define KSCHEDULER_HIGHEST_PRIORITY_THREAD 0x10 #define KSCHEDULER_HIGHEST_PRIORITY_THREAD 0x18
#define KSCHEDULER_IDLE_THREAD_STACK 0x18 #define KSCHEDULER_IDLE_THREAD_STACK 0x20
#define KSCHEDULER_PREVIOUS_THREAD 0x20 #define KSCHEDULER_PREVIOUS_THREAD 0x28
#define KSCHEDULER_INTERRUPT_TASK_MANAGER 0x28 #define KSCHEDULER_INTERRUPT_TASK_MANAGER 0x30

View File

@@ -36,6 +36,9 @@ namespace ams::kern::arch::arm64::cpu {
#error "Unknown Board for cpu::NumCores" #error "Unknown Board for cpu::NumCores"
#endif #endif
constexpr inline u32 El0Aarch64PsrMask = 0xF0000000;
constexpr inline u32 El0Aarch32PsrMask = 0xFE0FFE20;
/* Initialization. */ /* Initialization. */
NOINLINE void InitializeInterruptThreads(s32 core_id); NOINLINE void InitializeInterruptThreads(s32 core_id);
@@ -186,6 +189,14 @@ namespace ams::kern::arch::arm64::cpu {
return (par >> (BITSIZEOF(par) - BITSIZEOF(u8))) == 0xFF; return (par >> (BITSIZEOF(par) - BITSIZEOF(u8))) == 0xFF;
} }
ALWAYS_INLINE void StoreDataCacheForInitArguments(const void *addr, size_t size) {
const uintptr_t start = util::AlignDown(reinterpret_cast<uintptr_t>(addr), DataCacheLineSize);
for (size_t stored = 0; stored < size; stored += cpu::DataCacheLineSize) {
__asm__ __volatile__("dc cvac, %[cur]" :: [cur]"r"(start + stored) : "memory");
}
DataSynchronizationBarrier();
}
/* Synchronization helpers. */ /* Synchronization helpers. */
NOINLINE void SynchronizeAllCores(); NOINLINE void SynchronizeAllCores();
void SynchronizeCores(u64 core_mask); void SynchronizeCores(u64 core_mask);

View File

@@ -178,7 +178,7 @@ namespace ams::kern::arch::arm64 {
} }
NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end); NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager, KResourceLimit *resource_limit); NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
Result Finalize(); Result Finalize();
private: private:
Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll); Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
@@ -208,7 +208,7 @@ namespace ams::kern::arch::arm64 {
} }
} }
Result MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll); Result MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, bool not_first, PageLinkedList *page_list, bool reuse_ll);
Result MapGroup(KProcessAddress virt_addr, const KPageGroup &pg, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll); Result MapGroup(KProcessAddress virt_addr, const KPageGroup &pg, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
bool MergePages(KProcessAddress virt_addr, PageLinkedList *page_list); bool MergePages(KProcessAddress virt_addr, PageLinkedList *page_list);
@@ -216,7 +216,7 @@ namespace ams::kern::arch::arm64 {
ALWAYS_INLINE Result SeparatePagesImpl(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll); ALWAYS_INLINE Result SeparatePagesImpl(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
Result SeparatePages(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll); Result SeparatePages(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll); Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, bool flush_mapping, PageLinkedList *page_list, bool reuse_ll);
static ALWAYS_INLINE void PteDataMemoryBarrier() { static ALWAYS_INLINE void PteDataMemoryBarrier() {
cpu::DataMemoryBarrierInnerShareableStore(); cpu::DataMemoryBarrierInnerShareableStore();

View File

@@ -161,9 +161,12 @@ namespace ams::kern::arch::arm64 {
constexpr ALWAYS_INLINE bool IsPrivilegedExecuteNever() const { return this->GetBits(53, 1) != 0; } constexpr ALWAYS_INLINE bool IsPrivilegedExecuteNever() const { return this->GetBits(53, 1) != 0; }
constexpr ALWAYS_INLINE bool IsContiguous() const { return this->GetBits(52, 1) != 0; } constexpr ALWAYS_INLINE bool IsContiguous() const { return this->GetBits(52, 1) != 0; }
constexpr ALWAYS_INLINE bool IsGlobal() const { return this->GetBits(11, 1) == 0; } constexpr ALWAYS_INLINE bool IsGlobal() const { return this->GetBits(11, 1) == 0; }
constexpr ALWAYS_INLINE AccessFlag GetAccessFlag() const { return static_cast<AccessFlag>(this->GetBits(10, 1)); } constexpr ALWAYS_INLINE AccessFlag GetAccessFlag() const { return static_cast<AccessFlag>(this->SelectBits(10, 1)); }
constexpr ALWAYS_INLINE Shareable GetShareable() const { return static_cast<Shareable>(this->GetBits(8, 2)); } constexpr ALWAYS_INLINE Shareable GetShareable() const { return static_cast<Shareable>(this->SelectBits(8, 2)); }
constexpr ALWAYS_INLINE PageAttribute GetPageAttribute() const { return static_cast<PageAttribute>(this->GetBits(2, 3)); } constexpr ALWAYS_INLINE PageAttribute GetPageAttribute() const { return static_cast<PageAttribute>(this->SelectBits(2, 3)); }
constexpr ALWAYS_INLINE int GetAccessFlagInteger() const { return static_cast<int>(this->GetBits(10, 1)); }
constexpr ALWAYS_INLINE int GetShareableInteger() const { return static_cast<int>(this->GetBits(8, 2)); }
constexpr ALWAYS_INLINE int GetPageAttributeInteger() const { return static_cast<int>(this->GetBits(2, 3)); }
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; } constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; } constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; } constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }

View File

@@ -28,8 +28,8 @@ namespace ams::kern::arch::arm64 {
m_page_table.Activate(id); m_page_table.Activate(id);
} }
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager, KResourceLimit *resource_limit) { Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
R_RETURN(m_page_table.InitializeForProcess(id, as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager, resource_limit)); R_RETURN(m_page_table.InitializeForProcess(id, as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, system_resource, resource_limit));
} }
void Finalize() { m_page_table.Finalize(); } void Finalize() { m_page_table.Finalize(); }
@@ -98,8 +98,8 @@ namespace ams::kern::arch::arm64 {
R_RETURN(m_page_table.MapIoRegion(dst_address, phys_addr, size, mapping, perm)); R_RETURN(m_page_table.MapIoRegion(dst_address, phys_addr, size, mapping, perm));
} }
Result UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size) { Result UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping) {
R_RETURN(m_page_table.UnmapIoRegion(dst_address, phys_addr, size)); R_RETURN(m_page_table.UnmapIoRegion(dst_address, phys_addr, size, mapping));
} }
Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) { Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) {
@@ -110,6 +110,14 @@ namespace ams::kern::arch::arm64 {
R_RETURN(m_page_table.MapRegion(region_type, perm)); R_RETURN(m_page_table.MapRegion(region_type, perm));
} }
Result MapInsecureMemory(KProcessAddress address, size_t size) {
R_RETURN(m_page_table.MapInsecureMemory(address, size));
}
Result UnmapInsecureMemory(KProcessAddress address, size_t size) {
R_RETURN(m_page_table.UnmapInsecureMemory(address, size));
}
Result MapPageGroup(KProcessAddress addr, const KPageGroup &pg, KMemoryState state, KMemoryPermission perm) { Result MapPageGroup(KProcessAddress addr, const KPageGroup &pg, KMemoryState state, KMemoryPermission perm) {
R_RETURN(m_page_table.MapPageGroup(addr, pg, state, perm)); R_RETURN(m_page_table.MapPageGroup(addr, pg, state, perm));
} }
@@ -158,12 +166,12 @@ namespace ams::kern::arch::arm64 {
R_RETURN(m_page_table.WriteDebugIoMemory(address, buffer, size)); R_RETURN(m_page_table.WriteDebugIoMemory(address, buffer, size));
} }
Result LockForMapDeviceAddressSpace(KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) { Result LockForMapDeviceAddressSpace(bool *out_is_io, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned, bool check_heap) {
R_RETURN(m_page_table.LockForMapDeviceAddressSpace(address, size, perm, is_aligned)); R_RETURN(m_page_table.LockForMapDeviceAddressSpace(out_is_io, address, size, perm, is_aligned, check_heap));
} }
Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size) { Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size, bool check_heap) {
R_RETURN(m_page_table.LockForUnmapDeviceAddressSpace(address, size)); R_RETURN(m_page_table.LockForUnmapDeviceAddressSpace(address, size, check_heap));
} }
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size) { Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size) {

View File

@@ -77,7 +77,7 @@ namespace ams::kern::arch::arm64 {
__asm__ __volatile__( __asm__ __volatile__(
" prfm pstl1keep, %[m_next_ticket]\n" " prfm pstl1keep, %[m_next_ticket]\n"
"1:\n" "1:\n"
" ldaxrh %w[tmp0], %[m_next_ticket]\n" " ldxrh %w[tmp0], %[m_next_ticket]\n"
" add %w[tmp1], %w[tmp0], #0x1\n" " add %w[tmp1], %w[tmp0], #0x1\n"
" stxrh %w[got_lock], %w[tmp1], %[m_next_ticket]\n" " stxrh %w[got_lock], %w[tmp1], %[m_next_ticket]\n"
" cbnz %w[got_lock], 1b\n" " cbnz %w[got_lock], 1b\n"

View File

@@ -44,8 +44,8 @@ namespace ams::kern::board::generic {
R_THROW(ams::kern::svc::ResultNotImplemented()); R_THROW(ams::kern::svc::ResultNotImplemented());
} }
Result ALWAYS_INLINE Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) { Result ALWAYS_INLINE Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool is_io) {
MESOSPHERE_UNUSED(page_table, process_address, size, device_address, device_perm, is_aligned); MESOSPHERE_UNUSED(page_table, process_address, size, device_address, device_perm, is_aligned, is_io);
R_THROW(ams::kern::svc::ResultNotImplemented()); R_THROW(ams::kern::svc::ResultNotImplemented());
} }

View File

@@ -74,7 +74,7 @@ namespace ams::kern::board::nintendo::nx {
Result Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size); Result Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size);
Result Detach(ams::svc::DeviceName device_name); Result Detach(ams::svc::DeviceName device_name);
Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned); Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool is_io);
Result Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address); Result Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address);
void Unmap(KDeviceVirtualAddress device_address, size_t size) { void Unmap(KDeviceVirtualAddress device_address, size_t size) {

View File

@@ -20,14 +20,20 @@
namespace ams::kern::board::nintendo::nx { namespace ams::kern::board::nintendo::nx {
class KSystemControl : public KSystemControlBase { class KSystemControl : public KSystemControlBase {
public:
/* This can be overridden as needed. */
static constexpr size_t SecureAppletMemorySize = 4_MB;
public: public:
class Init : public KSystemControlBase::Init { class Init : public KSystemControlBase::Init {
private:
friend class KSystemControlBase::Init;
private:
static void CpuOnImpl(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
public: public:
/* Initialization. */ /* Initialization. */
static size_t GetRealMemorySize(); static size_t GetRealMemorySize();
static size_t GetIntendedMemorySize(); static size_t GetIntendedMemorySize();
static bool ShouldIncreaseThreadResourceLimit(); static bool ShouldIncreaseThreadResourceLimit();
static void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
static size_t GetApplicationPoolSize(); static size_t GetApplicationPoolSize();
static size_t GetAppletPoolSize(); static size_t GetAppletPoolSize();
static size_t GetMinimumNonSecureSystemPoolSize(); static size_t GetMinimumNonSecureSystemPoolSize();

View File

@@ -26,6 +26,6 @@ namespace ams::kern::init {
static_assert(util::IsPowerOfTwo(alignof(KInitArguments)) && util::IsPowerOfTwo(sizeof(KInitArguments))); static_assert(util::IsPowerOfTwo(alignof(KInitArguments)) && util::IsPowerOfTwo(sizeof(KInitArguments)));
KPhysicalAddress GetInitArgumentsAddress(s32 core_id); KInitArguments *GetInitArguments(s32 core_id);
} }

View File

@@ -36,13 +36,13 @@ namespace ams::kern::init {
size_t num_KDebug; size_t num_KDebug;
size_t num_KIoPool; size_t num_KIoPool;
size_t num_KIoRegion; size_t num_KIoRegion;
size_t num_KSessionRequestMappings;
}; };
NOINLINE void InitializeSlabResourceCounts(); NOINLINE void InitializeSlabResourceCounts();
const KSlabResourceCounts &GetSlabResourceCounts(); const KSlabResourceCounts &GetSlabResourceCounts();
size_t CalculateTotalSlabHeapSize(); size_t CalculateTotalSlabHeapSize();
NOINLINE void InitializeKPageBufferSlabHeap();
NOINLINE void InitializeSlabHeaps(); NOINLINE void InitializeSlabHeaps();
} }

View File

@@ -42,6 +42,11 @@
#define MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP #define MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP
#define MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP #define MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP
/* NOTE: In 16.0.0, Nintendo deleted the creation time field for KProcess, */
/* but this may be useful for some debugging applications, and so can be. */
/* re-enabled by toggling this define. */
//#define MESOSPHERE_ENABLE_PROCESS_CREATION_TIME
/* NOTE: This enables fast class token storage using a class member. */ /* NOTE: This enables fast class token storage using a class member. */
/* This saves a virtual call when doing KAutoObject->DynCast<>(), */ /* This saves a virtual call when doing KAutoObject->DynCast<>(), */
/* at the cost of storing class tokens inside the class object. */ /* at the cost of storing class tokens inside the class object. */

View File

@@ -40,12 +40,16 @@ namespace ams::kern {
static uintptr_t GetAddressSpaceStart(size_t width, Type type); static uintptr_t GetAddressSpaceStart(size_t width, Type type);
static size_t GetAddressSpaceSize(size_t width, Type type); static size_t GetAddressSpaceSize(size_t width, Type type);
static void SetAddressSpaceSize(size_t width, Type type, size_t size);
constexpr KAddressSpaceInfo(size_t bw, size_t a, size_t s, Type t) : m_bit_width(bw), m_address(a), m_size(s), m_type(t) { /* ... */ } constexpr KAddressSpaceInfo(size_t bw, size_t a, size_t s, Type t) : m_bit_width(bw), m_address(a), m_size(s), m_type(t) { /* ... */ }
constexpr size_t GetWidth() const { return m_bit_width; } constexpr size_t GetWidth() const { return m_bit_width; }
constexpr size_t GetAddress() const { return m_address; } constexpr size_t GetAddress() const { return m_address; }
constexpr size_t GetSize() const { return m_size; } constexpr size_t GetSize() const { return m_size; }
constexpr Type GetType() const { return m_type; } constexpr Type GetType() const { return m_type; }
constexpr void SetSize(size_t size) { m_size = size; }
}; };
} }

View File

@@ -79,7 +79,7 @@ namespace ams::kern {
} }
ALWAYS_INLINE bool Close() { ALWAYS_INLINE bool Close() {
/* Atomically decrement the reference count, not allowing it to become negative. */ /* Atomically decrement the reference count, not allowing it to decrement past zero. */
u32 cur = m_value.Load<std::memory_order_relaxed>(); u32 cur = m_value.Load<std::memory_order_relaxed>();
do { do {
MESOSPHERE_ABORT_UNLESS(cur > 0); MESOSPHERE_ABORT_UNLESS(cur > 0);
@@ -257,7 +257,7 @@ namespace ams::kern {
class KScopedAutoObject { class KScopedAutoObject {
NON_COPYABLE(KScopedAutoObject); NON_COPYABLE(KScopedAutoObject);
private: private:
template<typename U> template<typename U> requires std::derived_from<U, KAutoObject>
friend class KScopedAutoObject; friend class KScopedAutoObject;
private: private:
T *m_obj; T *m_obj;

View File

@@ -21,6 +21,8 @@ namespace ams::kern {
class KAutoObject; class KAutoObject;
class KSystemResource;
#define FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(HANDLER) \ #define FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(HANDLER) \
HANDLER(KAutoObject) \ HANDLER(KAutoObject) \
\ \
@@ -48,7 +50,8 @@ namespace ams::kern {
HANDLER(KSessionRequest) \ HANDLER(KSessionRequest) \
HANDLER(KCodeMemory) \ HANDLER(KCodeMemory) \
HANDLER(KIoPool) \ HANDLER(KIoPool) \
HANDLER(KIoRegion) HANDLER(KIoRegion) \
HANDLER(KSystemResource)
class KClassTokenGenerator { class KClassTokenGenerator {
public: public:
@@ -95,7 +98,7 @@ namespace ams::kern {
if constexpr (std::is_same<T, KAutoObject>::value) { if constexpr (std::is_same<T, KAutoObject>::value) {
static_assert(T::ObjectType == ObjectType::KAutoObject); static_assert(T::ObjectType == ObjectType::KAutoObject);
return 0; return 0;
} else if constexpr (!std::is_final<T>::value) { } else if constexpr (!std::is_final<T>::value && !std::same_as<T, KSystemResource>) {
static_assert(ObjectType::BaseClassesStart <= T::ObjectType && T::ObjectType < ObjectType::BaseClassesEnd); static_assert(ObjectType::BaseClassesStart <= T::ObjectType && T::ObjectType < ObjectType::BaseClassesEnd);
constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - static_cast<TokenBaseType>(ObjectType::BaseClassesStart); constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - static_cast<TokenBaseType>(ObjectType::BaseClassesStart);
return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>(); return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
@@ -142,6 +145,12 @@ namespace ams::kern {
KIoPool, KIoPool,
KIoRegion, KIoRegion,
/* NOTE: What occupies these gaps? They can be inferred, but they don't make sense. */
KAlpha,
KBeta,
KSystemResource,
FinalClassesLast, FinalClassesLast,
FinalClassesEnd = FinalClassesStart + NumFinalClasses, FinalClassesEnd = FinalClassesStart + NumFinalClasses,
@@ -178,8 +187,10 @@ namespace ams::kern {
} }
for (auto fin = util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesStart); fin < util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesLast); ++fin) { for (auto fin = util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesStart); fin < util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesLast); ++fin) {
if (!IsObjectTypeIncludedByMacro(static_cast<KClassTokenGenerator::ObjectType>(fin))) { if (const auto o = static_cast<KClassTokenGenerator::ObjectType>(fin); !IsObjectTypeIncludedByMacro(o)) {
return false; if (o != KClassTokenGenerator::ObjectType::KAlpha && o != KClassTokenGenerator::ObjectType::KBeta) {
return false;
}
} }
} }

View File

@@ -74,7 +74,7 @@ namespace ams::kern {
return m_process_holder.Get(); return m_process_holder.Get();
} }
private: private:
void PushDebugEvent(ams::svc::DebugEvent event, uintptr_t param0 = 0, uintptr_t param1 = 0, uintptr_t param2 = 0, uintptr_t param3 = 0, uintptr_t param4 = 0); void PushDebugEvent(ams::svc::DebugEvent event, const uintptr_t *params, size_t num_params);
void EnqueueDebugEventInfo(KEventInfo *info); void EnqueueDebugEventInfo(KEventInfo *info);
template<typename T> requires (std::same_as<T, ams::svc::lp64::DebugEventInfo> || std::same_as<T, ams::svc::ilp32::DebugEventInfo>) template<typename T> requires (std::same_as<T, ams::svc::lp64::DebugEventInfo> || std::same_as<T, ams::svc::ilp32::DebugEventInfo>)
@@ -85,13 +85,13 @@ namespace ams::kern {
/* NOTE: This is public/virtual override in Nintendo's kernel. */ /* NOTE: This is public/virtual override in Nintendo's kernel. */
void OnFinalizeSynchronizationObject(); void OnFinalizeSynchronizationObject();
private: private:
static Result ProcessDebugEvent(ams::svc::DebugEvent event, uintptr_t param0, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4); static Result ProcessDebugEvent(ams::svc::DebugEvent event, const uintptr_t *params, size_t num_params);
public: public:
static Result OnDebugEvent(ams::svc::DebugEvent event, uintptr_t param0 = 0, uintptr_t param1 = 0, uintptr_t param2 = 0, uintptr_t param3 = 0, uintptr_t param4 = 0); static Result OnDebugEvent(ams::svc::DebugEvent event, const uintptr_t *params, size_t num_params);
static Result OnExitProcess(KProcess *process); static Result OnExitProcess(KProcess *process);
static Result OnTerminateProcess(KProcess *process); static Result OnTerminateProcess(KProcess *process);
static Result OnExitThread(KThread *thread); static Result OnExitThread(KThread *thread);
static KEventInfo *CreateDebugEvent(ams::svc::DebugEvent event, uintptr_t param0, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4, u64 thread_id); static KEventInfo *CreateDebugEvent(ams::svc::DebugEvent event, u64 thread_id, const uintptr_t *params, size_t num_params);
}; };
} }

View File

@@ -41,17 +41,17 @@ namespace ams::kern {
Result Attach(ams::svc::DeviceName device_name); Result Attach(ams::svc::DeviceName device_name);
Result Detach(ams::svc::DeviceName device_name); Result Detach(ams::svc::DeviceName device_name);
Result MapByForce(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm) { Result MapByForce(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option) {
R_RETURN(this->Map(page_table, process_address, size, device_address, device_perm, false)); R_RETURN(this->Map(page_table, process_address, size, device_address, option, false));
} }
Result MapAligned(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm) { Result MapAligned(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option) {
R_RETURN(this->Map(page_table, process_address, size, device_address, device_perm, true)); R_RETURN(this->Map(page_table, process_address, size, device_address, option, true));
} }
Result Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address); Result Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address);
private: private:
Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned); Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option, bool is_aligned);
public: public:
static void Initialize(); static void Initialize();
}; };

View File

@@ -38,30 +38,37 @@ namespace ams::kern {
size_t m_peak; size_t m_peak;
size_t m_count; size_t m_count;
KVirtualAddress m_address; KVirtualAddress m_address;
KVirtualAddress m_aligned_address;
size_t m_size; size_t m_size;
public: public:
KDynamicPageManager() : m_lock(), m_page_bitmap(), m_used(), m_peak(), m_count(), m_address(Null<KVirtualAddress>), m_size() { /* ... */ } KDynamicPageManager() : m_lock(), m_page_bitmap(), m_used(), m_peak(), m_count(), m_address(Null<KVirtualAddress>), m_aligned_address(Null<KVirtualAddress>), m_size() { /* ... */ }
Result Initialize(KVirtualAddress memory, size_t sz) { Result Initialize(KVirtualAddress memory, size_t size, size_t align) {
/* We need to have positive size. */ /* We need to have positive size. */
R_UNLESS(sz > 0, svc::ResultOutOfMemory()); R_UNLESS(size > 0, svc::ResultOutOfMemory());
/* Calculate management overhead. */ /* Set addresses. */
const size_t management_size = KPageBitmap::CalculateManagementOverheadSize(sz / sizeof(PageBuffer)); m_address = memory;
const size_t allocatable_size = sz - management_size; m_aligned_address = util::AlignDown(GetInteger(memory), align);
/* Calculate extents. */
const size_t managed_size = m_address + size - m_aligned_address;
const size_t overhead_size = util::AlignUp(KPageBitmap::CalculateManagementOverheadSize(managed_size / sizeof(PageBuffer)), sizeof(PageBuffer));
R_UNLESS(overhead_size < size, svc::ResultOutOfMemory());
/* Set tracking fields. */ /* Set tracking fields. */
m_address = memory; m_size = util::AlignDown(size - overhead_size, sizeof(PageBuffer));
m_size = util::AlignDown(allocatable_size, sizeof(PageBuffer)); m_count = m_size / sizeof(PageBuffer);
m_count = allocatable_size / sizeof(PageBuffer);
R_UNLESS(m_count > 0, svc::ResultOutOfMemory());
/* Clear the management region. */ /* Clear the management region. */
u64 *management_ptr = GetPointer<u64>(m_address + allocatable_size); u64 *management_ptr = GetPointer<u64>(m_address + size - overhead_size);
std::memset(management_ptr, 0, management_size); std::memset(management_ptr, 0, overhead_size);
/* Initialize the bitmap. */ /* Initialize the bitmap. */
m_page_bitmap.Initialize(management_ptr, m_count); const size_t allocatable_region_size = (GetInteger(m_address) + size - overhead_size) - GetInteger(m_aligned_address);
MESOSPHERE_ABORT_UNLESS(allocatable_region_size >= sizeof(PageBuffer));
m_page_bitmap.Initialize(management_ptr, allocatable_region_size / sizeof(PageBuffer));
/* Free the pages to the bitmap. */ /* Free the pages to the bitmap. */
for (size_t i = 0; i < m_count; i++) { for (size_t i = 0; i < m_count; i++) {
@@ -69,7 +76,7 @@ namespace ams::kern {
cpu::ClearPageToZero(GetPointer<PageBuffer>(m_address) + i); cpu::ClearPageToZero(GetPointer<PageBuffer>(m_address) + i);
/* Set the bit for the free page. */ /* Set the bit for the free page. */
m_page_bitmap.SetBit(i); m_page_bitmap.SetBit((GetInteger(m_address) + (i * sizeof(PageBuffer)) - GetInteger(m_aligned_address)) / sizeof(PageBuffer));
} }
R_SUCCEED(); R_SUCCEED();
@@ -98,7 +105,28 @@ namespace ams::kern {
m_page_bitmap.ClearBit(offset); m_page_bitmap.ClearBit(offset);
m_peak = std::max(m_peak, (++m_used)); m_peak = std::max(m_peak, (++m_used));
return GetPointer<PageBuffer>(m_address) + offset; return GetPointer<PageBuffer>(m_aligned_address) + offset;
}
PageBuffer *Allocate(size_t count) {
/* Take the lock. */
KScopedInterruptDisable di;
KScopedSpinLock lk(m_lock);
/* Find a random free block. */
ssize_t soffset = m_page_bitmap.FindFreeRange(count);
if (AMS_UNLIKELY(soffset < 0)) {
return nullptr;
}
const size_t offset = static_cast<size_t>(soffset);
/* Update our tracking. */
m_page_bitmap.ClearRange(offset, count);
m_used += count;
m_peak = std::max(m_peak, m_used);
return GetPointer<PageBuffer>(m_aligned_address) + offset;
} }
void Free(PageBuffer *pb) { void Free(PageBuffer *pb) {
@@ -110,7 +138,7 @@ namespace ams::kern {
KScopedSpinLock lk(m_lock); KScopedSpinLock lk(m_lock);
/* Set the bit for the free page. */ /* Set the bit for the free page. */
size_t offset = (reinterpret_cast<uintptr_t>(pb) - GetInteger(m_address)) / sizeof(PageBuffer); size_t offset = (reinterpret_cast<uintptr_t>(pb) - GetInteger(m_aligned_address)) / sizeof(PageBuffer);
m_page_bitmap.SetBit(offset); m_page_bitmap.SetBit(offset);
/* Decrement our used count. */ /* Decrement our used count. */

View File

@@ -38,7 +38,7 @@ namespace ams::kern {
ams::svc::DebugException exception_type; ams::svc::DebugException exception_type;
s32 exception_data_count; s32 exception_data_count;
uintptr_t exception_address; uintptr_t exception_address;
uintptr_t exception_data[4]; uintptr_t exception_data[std::max<size_t>(4, cpu::NumCores)];
}; };
struct InfoSystemCall { struct InfoSystemCall {

View File

@@ -70,15 +70,20 @@ namespace ams::kern {
u16 m_next_linear_id; u16 m_next_linear_id;
u16 m_count; u16 m_count;
public: public:
constexpr explicit KHandleTable(util::ConstantInitializeTag) : m_entry_infos(), m_objects(), m_lock(), m_free_head_index(-1), m_table_size(), m_max_count(), m_next_linear_id(MinLinearId), m_count() { /* ... */ } constexpr explicit KHandleTable(util::ConstantInitializeTag) : m_entry_infos(), m_objects(), m_lock(), m_free_head_index(-1), m_table_size(), m_max_count(), m_next_linear_id(), m_count() { /* ... */ }
explicit KHandleTable() : m_lock(), m_free_head_index(-1), m_count() { MESOSPHERE_ASSERT_THIS(); } explicit KHandleTable() : m_lock(), m_free_head_index(-1), m_table_size(), m_max_count(), m_next_linear_id(), m_count() { MESOSPHERE_ASSERT_THIS(); }
constexpr MESOSPHERE_NOINLINE_IF_DEBUG Result Initialize(s32 size) { MESOSPHERE_NOINLINE_IF_DEBUG Result Initialize(s32 size) {
MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT_THIS();
/* Check that the table size is valid. */
R_UNLESS(size <= static_cast<s32>(MaxTableSize), svc::ResultOutOfMemory()); R_UNLESS(size <= static_cast<s32>(MaxTableSize), svc::ResultOutOfMemory());
/* Lock. */
KScopedDisableDispatch dd;
KScopedSpinLock lk(m_lock);
/* Initialize all fields. */ /* Initialize all fields. */
m_max_count = 0; m_max_count = 0;
m_table_size = (size <= 0) ? MaxTableSize : size; m_table_size = (size <= 0) ? MaxTableSize : size;

View File

@@ -22,9 +22,7 @@
namespace ams::kern { namespace ams::kern {
class KInterruptEventTask; class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent>, public KInterruptTask {
class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent> {
MESOSPHERE_AUTOOBJECT_TRAITS(KInterruptEvent, KReadableEvent); MESOSPHERE_AUTOOBJECT_TRAITS(KInterruptEvent, KReadableEvent);
private: private:
s32 m_interrupt_id; s32 m_interrupt_id;
@@ -54,21 +52,9 @@ namespace ams::kern {
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ } static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
constexpr s32 GetInterruptId() const { return m_interrupt_id; } constexpr s32 GetInterruptId() const { return m_interrupt_id; }
};
class KInterruptEventTask : public KSlabAllocated<KInterruptEventTask>, public KInterruptTask {
private:
KInterruptEvent *m_event;
public:
constexpr KInterruptEventTask() : m_event(nullptr) { /* ... */ }
~KInterruptEventTask() { /* ... */ }
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override; virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override;
virtual void DoTask() override; virtual void DoTask() override;
void Unregister(s32 interrupt_id, s32 core_id);
public:
static Result Register(s32 interrupt_id, s32 core_id, bool level, KInterruptEvent *event);
}; };
} }

View File

@@ -24,10 +24,10 @@ namespace ams::kern {
class KIoPool final : public KAutoObjectWithSlabHeapAndContainer<KIoPool, KAutoObjectWithList> { class KIoPool final : public KAutoObjectWithSlabHeapAndContainer<KIoPool, KAutoObjectWithList> {
MESOSPHERE_AUTOOBJECT_TRAITS(KIoPool, KAutoObject); MESOSPHERE_AUTOOBJECT_TRAITS(KIoPool, KAutoObject);
private: private:
using IoRegionList = util::IntrusiveListMemberTraits<&KIoRegion::m_pool_list_node>::ListType; using IoRegionTree = util::IntrusiveRedBlackTreeBaseTraits<KIoRegion>::TreeType<KIoRegion>;
private: private:
KLightLock m_lock; KLightLock m_lock;
IoRegionList m_io_region_list; IoRegionTree m_io_region_tree;
ams::svc::IoPoolType m_pool_type; ams::svc::IoPoolType m_pool_type;
bool m_is_initialized; bool m_is_initialized;
public: public:

View File

@@ -23,11 +23,30 @@ namespace ams::kern {
class KProcess; class KProcess;
class KIoPool; class KIoPool;
class KIoRegion final : public KAutoObjectWithSlabHeapAndContainer<KIoRegion, KAutoObjectWithList> { class KIoRegion final : public KAutoObjectWithSlabHeapAndContainer<KIoRegion, KAutoObjectWithList>, public util::IntrusiveRedBlackTreeBaseNode<KIoRegion> {
MESOSPHERE_AUTOOBJECT_TRAITS(KIoRegion, KAutoObject); MESOSPHERE_AUTOOBJECT_TRAITS(KIoRegion, KAutoObject);
private: private:
friend class KProcess; friend class KProcess;
friend class KIoPool; friend class KIoPool;
public:
using RedBlackKeyType = KPhysicalAddress;
static constexpr ALWAYS_INLINE RedBlackKeyType GetRedBlackKey(const RedBlackKeyType &v) { return v; }
static constexpr ALWAYS_INLINE RedBlackKeyType GetRedBlackKey(const KIoRegion &v) { return v.GetAddress(); }
template<typename T> requires (std::same_as<T, KIoRegion> || std::same_as<T, RedBlackKeyType>)
static constexpr ALWAYS_INLINE int Compare(const T &lhs, const KIoRegion &rhs) {
const RedBlackKeyType lval = GetRedBlackKey(lhs);
const RedBlackKeyType rval = GetRedBlackKey(rhs);
if (lval < rval) {
return -1;
} else if (lval == rval) {
return 0;
} else {
return 1;
}
}
private: private:
KLightLock m_lock; KLightLock m_lock;
KIoPool *m_pool; KIoPool *m_pool;
@@ -38,7 +57,6 @@ namespace ams::kern {
bool m_is_initialized; bool m_is_initialized;
bool m_is_mapped; bool m_is_mapped;
util::IntrusiveListNode m_process_list_node; util::IntrusiveListNode m_process_list_node;
util::IntrusiveListNode m_pool_list_node;
public: public:
explicit KIoRegion() : m_pool(nullptr), m_is_initialized(false) { /* ... */ } explicit KIoRegion() : m_pool(nullptr), m_is_initialized(false) { /* ... */ }
@@ -51,12 +69,25 @@ namespace ams::kern {
Result Map(KProcessAddress address, size_t size, ams::svc::MemoryPermission map_perm); Result Map(KProcessAddress address, size_t size, ams::svc::MemoryPermission map_perm);
Result Unmap(KProcessAddress address, size_t size); Result Unmap(KProcessAddress address, size_t size);
bool Overlaps(KPhysicalAddress address, size_t size) const { constexpr bool Overlaps(KPhysicalAddress address, size_t size) const {
return m_physical_address <= (address + size - 1) && address <= (m_physical_address + m_size - 1); return m_physical_address <= (address + size - 1) && address <= (m_physical_address + m_size - 1);
} }
ALWAYS_INLINE KPhysicalAddress GetAddress() const { return m_physical_address; } constexpr ALWAYS_INLINE KPhysicalAddress GetAddress() const { return m_physical_address; }
ALWAYS_INLINE size_t GetSize() const { return m_size; } constexpr ALWAYS_INLINE size_t GetSize() const { return m_size; }
constexpr uintptr_t GetHint() const {
/* TODO: Is this architecture specific? */
if (m_size >= 2_MB) {
return GetInteger(m_physical_address) & (2_MB - 1);
} else if (m_size >= 64_KB) {
return GetInteger(m_physical_address) & (64_KB - 1);
} else if (m_size >= 4_KB) {
return GetInteger(m_physical_address) & (4_KB - 1);
} else {
return 0;
}
}
}; };
} }

View File

@@ -43,6 +43,7 @@ namespace ams::kern {
KMemoryState_FlagCanMapProcess = (1 << 23), KMemoryState_FlagCanMapProcess = (1 << 23),
KMemoryState_FlagCanChangeAttribute = (1 << 24), KMemoryState_FlagCanChangeAttribute = (1 << 24),
KMemoryState_FlagCanCodeMemory = (1 << 25), KMemoryState_FlagCanCodeMemory = (1 << 25),
KMemoryState_FlagLinearMapped = (1 << 26),
KMemoryState_FlagsData = KMemoryState_FlagCanReprotect | KMemoryState_FlagCanUseIpc | KMemoryState_FlagsData = KMemoryState_FlagCanReprotect | KMemoryState_FlagCanUseIpc |
KMemoryState_FlagCanUseNonDeviceIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc | KMemoryState_FlagCanUseNonSecureIpc |
@@ -50,25 +51,27 @@ namespace ams::kern {
KMemoryState_FlagCanTransfer | KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanTransfer | KMemoryState_FlagCanQueryPhysical |
KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap |
KMemoryState_FlagCanIpcUserBuffer | KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanIpcUserBuffer | KMemoryState_FlagReferenceCounted |
KMemoryState_FlagCanChangeAttribute, KMemoryState_FlagCanChangeAttribute | KMemoryState_FlagLinearMapped,
KMemoryState_FlagsCode = KMemoryState_FlagCanDebug | KMemoryState_FlagCanUseIpc | KMemoryState_FlagsCode = KMemoryState_FlagCanDebug | KMemoryState_FlagCanUseIpc |
KMemoryState_FlagCanUseNonDeviceIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc | KMemoryState_FlagCanUseNonSecureIpc |
KMemoryState_FlagMapped | KMemoryState_FlagCode | KMemoryState_FlagMapped | KMemoryState_FlagCode |
KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanDeviceMap |
KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagReferenceCounted, KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagReferenceCounted |
KMemoryState_FlagLinearMapped,
KMemoryState_FlagsMisc = KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagsMisc = KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted |
KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanDeviceMap, KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanDeviceMap |
KMemoryState_FlagLinearMapped,
KMemoryState_Free = ams::svc::MemoryState_Free, KMemoryState_Free = ams::svc::MemoryState_Free,
KMemoryState_Io = ams::svc::MemoryState_Io | KMemoryState_FlagMapped, KMemoryState_Io = ams::svc::MemoryState_Io | KMemoryState_FlagMapped | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap,
KMemoryState_Static = ams::svc::MemoryState_Static | KMemoryState_FlagMapped | KMemoryState_FlagCanQueryPhysical, KMemoryState_Static = ams::svc::MemoryState_Static | KMemoryState_FlagMapped | KMemoryState_FlagCanQueryPhysical,
KMemoryState_Code = ams::svc::MemoryState_Code | KMemoryState_FlagsCode | KMemoryState_FlagCanMapProcess, KMemoryState_Code = ams::svc::MemoryState_Code | KMemoryState_FlagsCode | KMemoryState_FlagCanMapProcess,
KMemoryState_CodeData = ams::svc::MemoryState_CodeData | KMemoryState_FlagsData | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeMemory, KMemoryState_CodeData = ams::svc::MemoryState_CodeData | KMemoryState_FlagsData | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeMemory,
KMemoryState_Normal = ams::svc::MemoryState_Normal | KMemoryState_FlagsData | KMemoryState_FlagCanCodeMemory, KMemoryState_Normal = ams::svc::MemoryState_Normal | KMemoryState_FlagsData | KMemoryState_FlagCanCodeMemory,
KMemoryState_Shared = ams::svc::MemoryState_Shared | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted, KMemoryState_Shared = ams::svc::MemoryState_Shared | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped,
/* KMemoryState_Alias was removed after 1.0.0. */ /* KMemoryState_Alias was removed after 1.0.0. */
@@ -82,7 +85,7 @@ namespace ams::kern {
KMemoryState_Stack = ams::svc::MemoryState_Stack | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap KMemoryState_Stack = ams::svc::MemoryState_Stack | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap
| KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, | KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
KMemoryState_ThreadLocal = ams::svc::MemoryState_ThreadLocal | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted, KMemoryState_ThreadLocal = ams::svc::MemoryState_ThreadLocal | KMemoryState_FlagMapped | KMemoryState_FlagLinearMapped,
KMemoryState_Transfered = ams::svc::MemoryState_Transfered | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanChangeAttribute KMemoryState_Transfered = ams::svc::MemoryState_Transfered | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanChangeAttribute
| KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, | KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
@@ -90,7 +93,7 @@ namespace ams::kern {
KMemoryState_SharedTransfered = ams::svc::MemoryState_SharedTransfered | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap KMemoryState_SharedTransfered = ams::svc::MemoryState_SharedTransfered | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap
| KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
KMemoryState_SharedCode = ams::svc::MemoryState_SharedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted KMemoryState_SharedCode = ams::svc::MemoryState_SharedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped
| KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
KMemoryState_Inaccessible = ams::svc::MemoryState_Inaccessible, KMemoryState_Inaccessible = ams::svc::MemoryState_Inaccessible,
@@ -103,36 +106,41 @@ namespace ams::kern {
KMemoryState_Kernel = ams::svc::MemoryState_Kernel | KMemoryState_FlagMapped, KMemoryState_Kernel = ams::svc::MemoryState_Kernel | KMemoryState_FlagMapped,
KMemoryState_GeneratedCode = ams::svc::MemoryState_GeneratedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanDebug, KMemoryState_GeneratedCode = ams::svc::MemoryState_GeneratedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanDebug | KMemoryState_FlagLinearMapped,
KMemoryState_CodeOut = ams::svc::MemoryState_CodeOut | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted, KMemoryState_CodeOut = ams::svc::MemoryState_CodeOut | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped,
KMemoryState_Coverage = ams::svc::MemoryState_Coverage | KMemoryState_FlagMapped, KMemoryState_Coverage = ams::svc::MemoryState_Coverage | KMemoryState_FlagMapped,
KMemoryState_Insecure = ams::svc::MemoryState_Insecure | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped | KMemoryState_FlagCanChangeAttribute
| KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap
| KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
}; };
#if 1 #if 1
static_assert(KMemoryState_Free == 0x00000000); static_assert(KMemoryState_Free == 0x00000000);
static_assert(KMemoryState_Io == 0x00002001); static_assert(KMemoryState_Io == 0x00182001);
static_assert(KMemoryState_Static == 0x00042002); static_assert(KMemoryState_Static == 0x00042002);
static_assert(KMemoryState_Code == 0x00DC7E03); static_assert(KMemoryState_Code == 0x04DC7E03);
static_assert(KMemoryState_CodeData == 0x03FEBD04); static_assert(KMemoryState_CodeData == 0x07FEBD04);
static_assert(KMemoryState_Normal == 0x037EBD05); static_assert(KMemoryState_Normal == 0x077EBD05);
static_assert(KMemoryState_Shared == 0x00402006); static_assert(KMemoryState_Shared == 0x04402006);
static_assert(KMemoryState_AliasCode == 0x00DD7E08); static_assert(KMemoryState_AliasCode == 0x04DD7E08);
static_assert(KMemoryState_AliasCodeData == 0x03FFBD09); static_assert(KMemoryState_AliasCodeData == 0x07FFBD09);
static_assert(KMemoryState_Ipc == 0x005C3C0A); static_assert(KMemoryState_Ipc == 0x045C3C0A);
static_assert(KMemoryState_Stack == 0x005C3C0B); static_assert(KMemoryState_Stack == 0x045C3C0B);
static_assert(KMemoryState_ThreadLocal == 0x0040200C); static_assert(KMemoryState_ThreadLocal == 0x0400200C);
static_assert(KMemoryState_Transfered == 0x015C3C0D); static_assert(KMemoryState_Transfered == 0x055C3C0D);
static_assert(KMemoryState_SharedTransfered == 0x005C380E); static_assert(KMemoryState_SharedTransfered == 0x045C380E);
static_assert(KMemoryState_SharedCode == 0x0040380F); static_assert(KMemoryState_SharedCode == 0x0440380F);
static_assert(KMemoryState_Inaccessible == 0x00000010); static_assert(KMemoryState_Inaccessible == 0x00000010);
static_assert(KMemoryState_NonSecureIpc == 0x005C3811); static_assert(KMemoryState_NonSecureIpc == 0x045C3811);
static_assert(KMemoryState_NonDeviceIpc == 0x004C2812); static_assert(KMemoryState_NonDeviceIpc == 0x044C2812);
static_assert(KMemoryState_Kernel == 0x00002013); static_assert(KMemoryState_Kernel == 0x00002013);
static_assert(KMemoryState_GeneratedCode == 0x00402214); static_assert(KMemoryState_GeneratedCode == 0x04402214);
static_assert(KMemoryState_CodeOut == 0x00402015); static_assert(KMemoryState_CodeOut == 0x04402015);
static_assert(KMemoryState_Coverage == 0x00002016); static_assert(KMemoryState_Coverage == 0x00002016);
static_assert(KMemoryState_Insecure == 0x05583817);
#endif #endif
enum KMemoryPermission : u8 { enum KMemoryPermission : u8 {

View File

@@ -50,9 +50,11 @@ namespace ams::kern {
constexpr size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSizeMax; constexpr size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSizeMax;
/* NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x800. */ /* NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x800. */
constexpr size_t KernelPageBufferHeapSize = 0x3E0000;
constexpr size_t KernelSlabHeapAdditionalSize = 0x148000; constexpr size_t KernelSlabHeapAdditionalSize = 0x148000;
constexpr size_t KernelPageBufferAdditionalSize = 0x33C000;
constexpr size_t KernelResourceSize = KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize; constexpr size_t KernelResourceSize = KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize + KernelPageBufferHeapSize;
class KMemoryLayout { class KMemoryLayout {
private: private:
@@ -150,6 +152,8 @@ namespace ams::kern {
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelTraceBuffer)); } static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelTraceBuffer)); }
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetSecureAppletMemoryRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelSecureAppletMemory)); }
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetVirtualLinearRegion(KVirtualAddress address) { return Dereference(FindLinear(address)); } static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetVirtualLinearRegion(KVirtualAddress address) { return Dereference(FindLinear(address)); }
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetPhysicalLinearRegion(KPhysicalAddress address) { return Dereference(FindLinear(address)); } static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetPhysicalLinearRegion(KPhysicalAddress address) { return Dereference(FindLinear(address)); }
@@ -179,15 +183,15 @@ namespace ams::kern {
return std::make_tuple(total_size, kernel_size); return std::make_tuple(total_size, kernel_size);
} }
static void InitializeLinearMemoryAddresses(KPhysicalAddress aligned_linear_phys_start, KVirtualAddress linear_virtual_start) { static void InitializeLinearMemoryAddresses(u64 phys_to_virt_diff) {
/* Set static differences. */ /* Set static differences. */
s_linear_phys_to_virt_diff = GetInteger(linear_virtual_start) - GetInteger(aligned_linear_phys_start); s_linear_phys_to_virt_diff = phys_to_virt_diff;
s_linear_virt_to_phys_diff = GetInteger(aligned_linear_phys_start) - GetInteger(linear_virtual_start); s_linear_virt_to_phys_diff = -phys_to_virt_diff;
} }
static void InitializeLinearMemoryRegionTrees(); static void InitializeLinearMemoryRegionTrees();
static size_t GetResourceRegionSizeForInit(); static size_t GetResourceRegionSizeForInit(bool use_extra_resource);
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel); } static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelCodeRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode); } static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelCodeRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode); }
@@ -209,6 +213,7 @@ namespace ams::kern {
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelBase); } static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelBase); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelCodeRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelCode); } static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelCodeRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelCode); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelSlabRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSlab); } static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelSlabRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSlab); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelSecureAppletMemoryRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSecureAppletMemory); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelPageTableHeapRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelPtHeap); } static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelPageTableHeapRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelPtHeap); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelInitPageTableRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelInitPt); } static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelInitPageTableRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelInitPt); }

View File

@@ -200,7 +200,7 @@ namespace ams::kern {
NOINLINE KPhysicalAddress AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option); NOINLINE KPhysicalAddress AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
NOINLINE Result AllocateAndOpen(KPageGroup *out, size_t num_pages, u32 option); NOINLINE Result AllocateAndOpen(KPageGroup *out, size_t num_pages, u32 option);
NOINLINE Result AllocateAndOpenForProcess(KPageGroup *out, size_t num_pages, u32 option, u64 process_id, u8 fill_pattern); NOINLINE Result AllocateForProcess(KPageGroup *out, size_t num_pages, u32 option, u64 process_id, u8 fill_pattern);
Pool GetPool(KPhysicalAddress address) const { Pool GetPool(KPhysicalAddress address) const {
return this->GetManager(address).GetPool(); return this->GetManager(address).GetPool();
@@ -222,6 +222,22 @@ namespace ams::kern {
} }
} }
void OpenFirst(KPhysicalAddress address, size_t num_pages) {
/* Repeatedly open references until we've done so for all pages. */
while (num_pages) {
auto &manager = this->GetManager(address);
const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address));
{
KScopedLightLock lk(m_pool_locks[manager.GetPool()]);
manager.OpenFirst(address, cur_pages);
}
num_pages -= cur_pages;
address += cur_pages * PageSize;
}
}
void Close(KPhysicalAddress address, size_t num_pages) { void Close(KPhysicalAddress address, size_t num_pages) {
/* Repeatedly close references until we've done so for all pages. */ /* Repeatedly close references until we've done so for all pages. */
while (num_pages) { while (num_pages) {

View File

@@ -211,6 +211,8 @@ namespace ams::kern {
static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() == (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped)); static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() == (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() == (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped)); static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() == (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
constexpr inline const auto KMemoryRegionType_DramKernelSecureAppletMemory = KMemoryRegionType_DramKernelBase.DeriveSparse(1, 3, 0).SetAttribute(KMemoryRegionAttr_LinearMapped);
static_assert(KMemoryRegionType_DramKernelSecureAppletMemory.GetValue() == (0x18E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
constexpr inline const auto KMemoryRegionType_DramReservedEarly = KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap); constexpr inline const auto KMemoryRegionType_DramReservedEarly = KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
static_assert(KMemoryRegionType_DramReservedEarly.GetValue() == (0x16 | KMemoryRegionAttr_NoUserMap)); static_assert(KMemoryRegionType_DramReservedEarly.GetValue() == (0x16 | KMemoryRegionAttr_NoUserMap));
@@ -251,6 +253,9 @@ namespace ams::kern {
constexpr inline const auto KMemoryRegionType_VirtualDramUnknownDebug = KMemoryRegionType_Dram.DeriveSparse(2, 2, 1); constexpr inline const auto KMemoryRegionType_VirtualDramUnknownDebug = KMemoryRegionType_Dram.DeriveSparse(2, 2, 1);
static_assert(KMemoryRegionType_VirtualDramUnknownDebug.GetValue() == (0x52)); static_assert(KMemoryRegionType_VirtualDramUnknownDebug.GetValue() == (0x52));
constexpr inline const auto KMemoryRegionType_VirtualDramKernelSecureAppletMemory = KMemoryRegionType_Dram.DeriveSparse(3, 1, 0);
static_assert(KMemoryRegionType_VirtualDramKernelSecureAppletMemory.GetValue() == (0x62));
constexpr inline const auto KMemoryRegionType_VirtualDramKernelInitPt = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0); constexpr inline const auto KMemoryRegionType_VirtualDramKernelInitPt = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0);
constexpr inline const auto KMemoryRegionType_VirtualDramPoolManagement = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1); constexpr inline const auto KMemoryRegionType_VirtualDramPoolManagement = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1);
constexpr inline const auto KMemoryRegionType_VirtualDramUserPool = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2); constexpr inline const auto KMemoryRegionType_VirtualDramUserPool = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2);
@@ -327,6 +332,8 @@ namespace ams::kern {
return KMemoryRegionType_VirtualDramKernelTraceBuffer; return KMemoryRegionType_VirtualDramKernelTraceBuffer;
} else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) { } else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) {
return KMemoryRegionType_VirtualDramKernelPtHeap; return KMemoryRegionType_VirtualDramKernelPtHeap;
} else if (KMemoryRegionType_DramKernelSecureAppletMemory.IsAncestorOf(type_id)) {
return KMemoryRegionType_VirtualDramKernelSecureAppletMemory;
} else if ((type_id | KMemoryRegionAttr_ShouldKernelMap) == type_id) { } else if ((type_id | KMemoryRegionAttr_ShouldKernelMap) == type_id) {
return KMemoryRegionType_VirtualDramUnknownDebug; return KMemoryRegionType_VirtualDramUnknownDebug;
} else { } else {

View File

@@ -48,7 +48,7 @@ namespace ams::kern {
/* Check that the object is closed. */ /* Check that the object is closed. */
R_UNLESS(derived->IsServerClosed(), svc::ResultInvalidState()); R_UNLESS(derived->IsServerClosed(), svc::ResultInvalidState());
return Delete(obj.GetPointerUnsafe(), name); R_RETURN(Delete(obj.GetPointerUnsafe(), name));
} }
template<typename Derived> requires std::derived_from<Derived, KAutoObject> template<typename Derived> requires std::derived_from<Derived, KAutoObject>

View File

@@ -113,11 +113,12 @@ namespace ams::kern {
static constexpr size_t MaxDepth = 4; static constexpr size_t MaxDepth = 4;
private: private:
u64 *m_bit_storages[MaxDepth]; u64 *m_bit_storages[MaxDepth];
u64 *m_end_storages[MaxDepth];
RandomBitGenerator m_rng; RandomBitGenerator m_rng;
size_t m_num_bits; size_t m_num_bits;
size_t m_used_depths; size_t m_used_depths;
public: public:
KPageBitmap() : m_bit_storages(), m_rng(), m_num_bits(), m_used_depths() { /* ... */ } KPageBitmap() : m_bit_storages(), m_end_storages(), m_rng(), m_num_bits(), m_used_depths() { /* ... */ }
constexpr size_t GetNumBits() const { return m_num_bits; } constexpr size_t GetNumBits() const { return m_num_bits; }
constexpr s32 GetHighestDepthIndex() const { return static_cast<s32>(m_used_depths) - 1; } constexpr s32 GetHighestDepthIndex() const { return static_cast<s32>(m_used_depths) - 1; }
@@ -135,6 +136,7 @@ namespace ams::kern {
m_bit_storages[depth] = storage; m_bit_storages[depth] = storage;
size = util::AlignUp(size, BITSIZEOF(u64)) / BITSIZEOF(u64); size = util::AlignUp(size, BITSIZEOF(u64)) / BITSIZEOF(u64);
storage += size; storage += size;
m_end_storages[depth] = storage;
} }
return storage; return storage;
@@ -171,6 +173,45 @@ namespace ams::kern {
return static_cast<ssize_t>(offset); return static_cast<ssize_t>(offset);
} }
ssize_t FindFreeRange(size_t count) {
/* Check that it is possible to find a range. */
const u64 * const storage_start = m_bit_storages[m_used_depths - 1];
const u64 * const storage_end = m_end_storages[m_used_depths - 1];
/* If we don't have a storage to iterate (or want more blocks than fit in a single storage), we can't find a free range. */
if (!(storage_start < storage_end && count <= BITSIZEOF(u64))) {
return -1;
}
/* Walk the storages to select a random free range. */
const size_t options_per_storage = std::max<size_t>(BITSIZEOF(u64) / count, 1);
const size_t num_entries = std::max<size_t>(storage_end - storage_start, 1);
const u64 free_mask = (static_cast<u64>(1) << count) - 1;
size_t num_valid_options = 0;
ssize_t chosen_offset = -1;
for (size_t storage_index = 0; storage_index < num_entries; ++storage_index) {
u64 storage = storage_start[storage_index];
for (size_t option = 0; option < options_per_storage; ++option) {
if ((storage & free_mask) == free_mask) {
/* We've found a new valid option. */
++num_valid_options;
/* Select the Kth valid option with probability 1/K. This leads to an overall uniform distribution. */
if (num_valid_options == 1 || m_rng.GenerateRandom(num_valid_options) == 0) {
/* This is our first option, so select it. */
chosen_offset = storage_index * BITSIZEOF(u64) + option * count;
}
}
storage >>= count;
}
}
/* Return the random offset we chose.*/
return chosen_offset;
}
void SetBit(size_t offset) { void SetBit(size_t offset) {
this->SetBit(this->GetHighestDepthIndex(), offset); this->SetBit(this->GetHighestDepthIndex(), offset);
m_num_bits++; m_num_bits++;

View File

@@ -16,12 +16,33 @@
#pragma once #pragma once
#include <mesosphere/kern_slab_helpers.hpp> #include <mesosphere/kern_slab_helpers.hpp>
#include <mesosphere/kern_k_memory_layout.hpp> #include <mesosphere/kern_k_memory_layout.hpp>
#include <mesosphere/kern_k_dynamic_page_manager.hpp>
namespace ams::kern { namespace ams::kern {
class KPageBuffer : public KSlabAllocated<KPageBuffer> { class KDynamicPageManager;
class KPageBuffer;
class KPageBufferSlabHeap : protected impl::KSlabHeapImpl {
public:
static constexpr size_t BufferSize = PageSize;
static constinit inline size_t s_buffer_count = 0;
private: private:
alignas(PageSize) u8 m_buffer[PageSize]; size_t m_obj_size{};
public:
constexpr KPageBufferSlabHeap() = default;
/* See kern_init_slab_setup.cpp for definition. */
void Initialize(KDynamicPageManager &allocator);
KPageBuffer *Allocate();
void Free(KPageBuffer *pb);
};
class KPageBuffer {
private:
u8 m_buffer[KPageBufferSlabHeap::BufferSize];
public: public:
KPageBuffer() { KPageBuffer() {
std::memset(m_buffer, 0, sizeof(m_buffer)); std::memset(m_buffer, 0, sizeof(m_buffer));
@@ -39,8 +60,49 @@ namespace ams::kern {
return GetPointer<KPageBuffer>(virt_addr); return GetPointer<KPageBuffer>(virt_addr);
} }
private:
static constinit inline KPageBufferSlabHeap s_slab_heap;
public:
static void InitializeSlabHeap(KDynamicPageManager &allocator) {
s_slab_heap.Initialize(allocator);
}
static KPageBuffer *Allocate() {
return s_slab_heap.Allocate();
}
static void Free(KPageBuffer *obj) {
s_slab_heap.Free(obj);
}
template<size_t ExpectedSize>
static ALWAYS_INLINE KPageBuffer *AllocateChecked() {
/* Check that the allocation is valid. */
MESOSPHERE_ABORT_UNLESS(sizeof(KPageBuffer) == ExpectedSize);
return Allocate();
}
template<size_t ExpectedSize>
static ALWAYS_INLINE void FreeChecked(KPageBuffer *obj) {
/* Check that the free is valid. */
MESOSPHERE_ABORT_UNLESS(sizeof(KPageBuffer) == ExpectedSize);
return Free(obj);
}
}; };
static_assert(sizeof(KPageBuffer) == PageSize); static_assert(sizeof(KPageBuffer) == KPageBufferSlabHeap::BufferSize);
static_assert(alignof(KPageBuffer) == PageSize);
ALWAYS_INLINE KPageBuffer *KPageBufferSlabHeap::Allocate() {
KPageBuffer *pb = static_cast<KPageBuffer *>(KSlabHeapImpl::Allocate());
if (AMS_LIKELY(pb != nullptr)) {
std::construct_at(pb);
}
return pb;
}
ALWAYS_INLINE void KPageBufferSlabHeap::Free(KPageBuffer *pb) {
KSlabHeapImpl::Free(pb);
}
} }

View File

@@ -138,6 +138,7 @@ namespace ams::kern {
Result AddBlock(KPhysicalAddress addr, size_t num_pages); Result AddBlock(KPhysicalAddress addr, size_t num_pages);
void Open() const; void Open() const;
void OpenFirst() const;
void Close() const; void Close() const;
size_t GetNumPages() const; size_t GetNumPages() const;

View File

@@ -48,6 +48,7 @@ namespace ams::kern {
static_assert(sizeof(KPageProperties) == sizeof(u32)); static_assert(sizeof(KPageProperties) == sizeof(u32));
class KResourceLimit; class KResourceLimit;
class KSystemResource;
class KPageTableBase { class KPageTableBase {
NON_COPYABLE(KPageTableBase); NON_COPYABLE(KPageTableBase);
@@ -56,11 +57,26 @@ namespace ams::kern {
using TraversalEntry = KPageTableImpl::TraversalEntry; using TraversalEntry = KPageTableImpl::TraversalEntry;
using TraversalContext = KPageTableImpl::TraversalContext; using TraversalContext = KPageTableImpl::TraversalContext;
struct MemoryRange { class MemoryRange {
KPhysicalAddress address; private:
size_t size; KPhysicalAddress m_address;
size_t m_size;
bool m_heap;
public:
constexpr MemoryRange() : m_address(Null<KPhysicalAddress>), m_size(0), m_heap(false) { /* ... */ }
void Close(); void Set(KPhysicalAddress address, size_t size, bool heap) {
m_address = address;
m_size = size;
m_heap = heap;
}
constexpr KPhysicalAddress GetAddress() const { return m_address; }
constexpr size_t GetSize() const { return m_size; }
constexpr bool IsHeap() const { return m_heap; }
void Open();
void Close();
}; };
protected: protected:
enum MemoryFillValue { enum MemoryFillValue {
@@ -71,11 +87,14 @@ namespace ams::kern {
}; };
enum OperationType { enum OperationType {
OperationType_Map = 0, OperationType_Map = 0,
OperationType_MapGroup = 1, OperationType_MapFirst = 1,
OperationType_Unmap = 2, OperationType_MapGroup = 2,
OperationType_ChangePermissions = 3, OperationType_Unmap = 3,
OperationType_ChangePermissionsAndRefresh = 4, OperationType_ChangePermissions = 4,
OperationType_ChangePermissionsAndRefresh = 5,
OperationType_ChangePermissionsAndRefreshAndFlush = 6,
OperationType_Separate = 7,
}; };
static constexpr size_t MaxPhysicalMapAlignment = 1_GB; static constexpr size_t MaxPhysicalMapAlignment = 1_GB;
@@ -162,6 +181,7 @@ namespace ams::kern {
size_t m_max_heap_size; size_t m_max_heap_size;
size_t m_mapped_physical_memory_size; size_t m_mapped_physical_memory_size;
size_t m_mapped_unsafe_physical_memory; size_t m_mapped_unsafe_physical_memory;
size_t m_mapped_insecure_memory;
size_t m_mapped_ipc_server_memory; size_t m_mapped_ipc_server_memory;
mutable KLightLock m_general_lock; mutable KLightLock m_general_lock;
mutable KLightLock m_map_physical_memory_lock; mutable KLightLock m_map_physical_memory_lock;
@@ -188,8 +208,8 @@ namespace ams::kern {
m_alias_region_end(Null<KProcessAddress>), m_stack_region_start(Null<KProcessAddress>), m_stack_region_end(Null<KProcessAddress>), m_alias_region_end(Null<KProcessAddress>), m_stack_region_start(Null<KProcessAddress>), m_stack_region_end(Null<KProcessAddress>),
m_kernel_map_region_start(Null<KProcessAddress>), m_kernel_map_region_end(Null<KProcessAddress>), m_alias_code_region_start(Null<KProcessAddress>), m_kernel_map_region_start(Null<KProcessAddress>), m_kernel_map_region_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_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_ipc_server_memory(), m_general_lock(), m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(),
m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize), 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_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_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_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value()
@@ -200,7 +220,7 @@ namespace ams::kern {
explicit KPageTableBase() { /* ... */ } explicit KPageTableBase() { /* ... */ }
NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end); NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KResourceLimit *resource_limit); NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_device_address_space_merge, 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);
void Finalize(); void Finalize();
@@ -359,9 +379,11 @@ namespace ams::kern {
Result UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size); Result UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size);
Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm); Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm);
Result MapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm); Result MapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm);
Result UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size); Result UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping);
Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm); Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm);
Result MapRegion(KMemoryRegionType region_type, KMemoryPermission perm); Result MapRegion(KMemoryRegionType region_type, KMemoryPermission perm);
Result MapInsecureMemory(KProcessAddress address, size_t size);
Result UnmapInsecureMemory(KProcessAddress address, size_t size);
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) { Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
R_RETURN(this->MapPages(out_addr, num_pages, alignment, phys_addr, true, region_start, region_num_pages, state, perm)); R_RETURN(this->MapPages(out_addr, num_pages, alignment, phys_addr, true, region_start, region_num_pages, state, perm));
@@ -392,8 +414,8 @@ namespace ams::kern {
Result WriteDebugMemory(KProcessAddress address, const void *buffer, size_t size); Result WriteDebugMemory(KProcessAddress address, const void *buffer, size_t size);
Result WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size); Result WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size);
Result LockForMapDeviceAddressSpace(KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned); Result LockForMapDeviceAddressSpace(bool *out_is_io, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned, bool check_heap);
Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size); Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size, bool check_heap);
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size); Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size);
Result UnlockForDeviceAddressSpacePartialMap(KProcessAddress address, size_t size); Result UnlockForDeviceAddressSpacePartialMap(KProcessAddress address, size_t size);

View File

@@ -234,11 +234,11 @@ namespace ams::kern {
KPriorityQueueImpl m_scheduled_queue; KPriorityQueueImpl m_scheduled_queue;
KPriorityQueueImpl m_suggested_queue; KPriorityQueueImpl m_suggested_queue;
private: private:
constexpr ALWAYS_INLINE void ClearAffinityBit(u64 &affinity, s32 core) { static constexpr ALWAYS_INLINE void ClearAffinityBit(u64 &affinity, s32 core) {
affinity &= ~(UINT64_C(1) << core); affinity &= ~(UINT64_C(1) << core);
} }
constexpr ALWAYS_INLINE s32 GetNextCore(u64 &affinity) { static constexpr ALWAYS_INLINE s32 GetNextCore(u64 &affinity) {
const s32 core = __builtin_ctzll(static_cast<unsigned long long>(affinity)); const s32 core = __builtin_ctzll(static_cast<unsigned long long>(affinity));
ClearAffinityBit(affinity, core); ClearAffinityBit(affinity, core);
return core; return core;

View File

@@ -31,6 +31,7 @@
#include <mesosphere/kern_k_wait_object.hpp> #include <mesosphere/kern_k_wait_object.hpp>
#include <mesosphere/kern_k_dynamic_resource_manager.hpp> #include <mesosphere/kern_k_dynamic_resource_manager.hpp>
#include <mesosphere/kern_k_page_table_manager.hpp> #include <mesosphere/kern_k_page_table_manager.hpp>
#include <mesosphere/kern_k_system_resource.hpp>
namespace ams::kern { namespace ams::kern {
@@ -64,8 +65,7 @@ namespace ams::kern {
s32 m_ideal_core_id; s32 m_ideal_core_id;
void *m_attached_object; void *m_attached_object;
KResourceLimit *m_resource_limit; KResourceLimit *m_resource_limit;
KVirtualAddress m_system_resource_address; KSystemResource *m_system_resource;
size_t m_system_resource_num_pages;
size_t m_memory_release_hint; size_t m_memory_release_hint;
State m_state; State m_state;
KLightLock m_state_lock; KLightLock m_state_lock;
@@ -84,7 +84,9 @@ namespace ams::kern {
KCapabilities m_capabilities; KCapabilities m_capabilities;
ams::svc::ProgramId m_program_id; ams::svc::ProgramId m_program_id;
u64 m_process_id; u64 m_process_id;
#if defined(MESOSPHERE_ENABLE_PROCESS_CREATION_TIME)
s64 m_creation_time; s64 m_creation_time;
#endif
KProcessAddress m_code_address; KProcessAddress m_code_address;
size_t m_code_size; size_t m_code_size;
size_t m_main_thread_stack_size; size_t m_main_thread_stack_size;
@@ -108,6 +110,7 @@ namespace ams::kern {
KWaitObject m_wait_object; KWaitObject m_wait_object;
KThread *m_running_threads[cpu::NumCores]; KThread *m_running_threads[cpu::NumCores];
u64 m_running_thread_idle_counts[cpu::NumCores]; u64 m_running_thread_idle_counts[cpu::NumCores];
u64 m_running_thread_switch_counts[cpu::NumCores];
KThread *m_pinned_threads[cpu::NumCores]; KThread *m_pinned_threads[cpu::NumCores];
util::Atomic<s64> m_cpu_time; util::Atomic<s64> m_cpu_time;
util::Atomic<s64> m_num_process_switches; util::Atomic<s64> m_num_process_switches;
@@ -117,13 +120,6 @@ namespace ams::kern {
util::Atomic<s64> m_num_ipc_messages; util::Atomic<s64> m_num_ipc_messages;
util::Atomic<s64> m_num_ipc_replies; util::Atomic<s64> m_num_ipc_replies;
util::Atomic<s64> m_num_ipc_receives; util::Atomic<s64> m_num_ipc_receives;
KDynamicPageManager m_dynamic_page_manager;
KMemoryBlockSlabManager m_memory_block_slab_manager;
KBlockInfoManager m_block_info_manager;
KPageTableManager m_page_table_manager;
KMemoryBlockSlabHeap m_memory_block_heap;
KBlockInfoSlabHeap m_block_info_heap;
KPageTableSlabHeap m_page_table_heap;
private: private:
Result Initialize(const ams::svc::CreateProcessParameter &params); Result Initialize(const ams::svc::CreateProcessParameter &params);
@@ -284,17 +280,18 @@ namespace ams::kern {
void IncrementRunningThreadCount(); void IncrementRunningThreadCount();
void DecrementRunningThreadCount(); void DecrementRunningThreadCount();
size_t GetTotalSystemResourceSize() const { return m_system_resource_num_pages * PageSize; } size_t GetTotalSystemResourceSize() const {
size_t GetUsedSystemResourceSize() const { return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetSize() : 0;
if (m_system_resource_num_pages == 0) {
return 0;
}
return m_dynamic_page_manager.GetUsed() * PageSize;
} }
void SetRunningThread(s32 core, KThread *thread, u64 idle_count) { size_t GetUsedSystemResourceSize() const {
m_running_threads[core] = thread; return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetUsedSize() : 0;
m_running_thread_idle_counts[core] = idle_count; }
void SetRunningThread(s32 core, KThread *thread, u64 idle_count, u64 switch_count) {
m_running_threads[core] = thread;
m_running_thread_idle_counts[core] = idle_count;
m_running_thread_switch_counts[core] = switch_count;
} }
void ClearRunningThread(KThread *thread) { void ClearRunningThread(KThread *thread) {
@@ -305,13 +302,15 @@ namespace ams::kern {
} }
} }
const KDynamicPageManager &GetDynamicPageManager() const { return m_dynamic_page_manager; } const KSystemResource &GetSystemResource() const { return *m_system_resource; }
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return m_memory_block_slab_manager; }
const KBlockInfoManager &GetBlockInfoManager() const { return m_block_info_manager; } const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return m_system_resource->GetMemoryBlockSlabManager(); }
const KPageTableManager &GetPageTableManager() const { return m_page_table_manager; } const KBlockInfoManager &GetBlockInfoManager() const { return m_system_resource->GetBlockInfoManager(); }
const KPageTableManager &GetPageTableManager() const { return m_system_resource->GetPageTableManager(); }
constexpr KThread *GetRunningThread(s32 core) const { return m_running_threads[core]; } constexpr KThread *GetRunningThread(s32 core) const { return m_running_threads[core]; }
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return m_running_thread_idle_counts[core]; } constexpr u64 GetRunningThreadIdleCount(s32 core) const { return m_running_thread_idle_counts[core]; }
constexpr u64 GetRunningThreadSwitchCount(s32 core) const { return m_running_thread_switch_counts[core]; }
void RegisterThread(KThread *thread); void RegisterThread(KThread *thread);
void UnregisterThread(KThread *thread); void UnregisterThread(KThread *thread);

View File

@@ -43,6 +43,7 @@ namespace ams::kern {
bool interrupt_task_runnable{false}; bool interrupt_task_runnable{false};
bool should_count_idle{false}; bool should_count_idle{false};
u64 idle_count{0}; u64 idle_count{0};
u64 switch_count{0};
KThread *highest_priority_thread{nullptr}; KThread *highest_priority_thread{nullptr};
void *idle_thread_stack{nullptr}; void *idle_thread_stack{nullptr};
KThread *prev_thread{nullptr}; KThread *prev_thread{nullptr};
@@ -67,6 +68,7 @@ namespace ams::kern {
m_state.interrupt_task_runnable = false; m_state.interrupt_task_runnable = false;
m_state.should_count_idle = false; m_state.should_count_idle = false;
m_state.idle_count = 0; m_state.idle_count = 0;
m_state.switch_count = 0;
m_state.idle_thread_stack = nullptr; m_state.idle_thread_stack = nullptr;
m_state.highest_priority_thread = nullptr; m_state.highest_priority_thread = nullptr;
m_state.prev_thread = nullptr; m_state.prev_thread = nullptr;
@@ -93,6 +95,10 @@ namespace ams::kern {
return m_state.idle_count; return m_state.idle_count;
} }
ALWAYS_INLINE u64 GetSwitchCount() const {
return m_state.switch_count;
}
ALWAYS_INLINE KThread *GetIdleThread() const { ALWAYS_INLINE KThread *GetIdleThread() const {
return m_idle_thread; return m_idle_thread;
} }
@@ -152,7 +158,7 @@ namespace ams::kern {
static NOINLINE void OnThreadPriorityChanged(KThread *thread, s32 old_priority); static NOINLINE void OnThreadPriorityChanged(KThread *thread, s32 old_priority);
static NOINLINE void OnThreadAffinityMaskChanged(KThread *thread, const KAffinityMask &old_affinity, s32 old_core); static NOINLINE void OnThreadAffinityMaskChanged(KThread *thread, const KAffinityMask &old_affinity, s32 old_core);
static NOINLINE void RotateScheduledQueue(s32 priority, s32 core_id); static NOINLINE void RotateScheduledQueue(s32 core_id, s32 priority);
static NOINLINE void YieldWithoutCoreMigration(); static NOINLINE void YieldWithoutCoreMigration();
static NOINLINE void YieldWithCoreMigration(); static NOINLINE void YieldWithCoreMigration();

View File

@@ -49,9 +49,9 @@ namespace ams::kern {
MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT_THIS();
if (this->IsLockedByCurrentThread()) { if (this->IsLockedByCurrentThread()) {
/* If we already own the lock, we can just increment the count. */ /* If we already own the lock, the lock count should be > 0. */
/* For debug, ensure this is true. */
MESOSPHERE_ASSERT(m_lock_count > 0); MESOSPHERE_ASSERT(m_lock_count > 0);
m_lock_count++;
} else { } else {
/* Otherwise, we want to disable scheduling and acquire the spinlock. */ /* Otherwise, we want to disable scheduling and acquire the spinlock. */
SchedulerType::DisableScheduling(); SchedulerType::DisableScheduling();
@@ -61,10 +61,12 @@ namespace ams::kern {
MESOSPHERE_ASSERT(m_lock_count == 0); MESOSPHERE_ASSERT(m_lock_count == 0);
MESOSPHERE_ASSERT(m_owner_thread == nullptr); MESOSPHERE_ASSERT(m_owner_thread == nullptr);
/* Increment count, take ownership. */ /* Take ownership of the lock. */
m_lock_count = 1;
m_owner_thread = GetCurrentThreadPointer(); m_owner_thread = GetCurrentThreadPointer();
} }
/* Increment the lock count. */
m_lock_count++;
} }
MESOSPHERE_ALWAYS_INLINE_IF_RELEASE void Unlock() { MESOSPHERE_ALWAYS_INLINE_IF_RELEASE void Unlock() {

View File

@@ -29,7 +29,10 @@ namespace ams::kern {
public: public:
class SessionMappings { class SessionMappings {
private: private:
static constexpr size_t NumStaticMappings = 8; /* At most 15 buffers of each type (4-bit descriptor counts), for 45 total. */
static constexpr size_t NumMappings = ((1ul << 4) - 1) * 3;
static constexpr size_t NumStaticMappings = 8;
static constexpr size_t NumDynamicMappings = NumMappings - NumStaticMappings;
class Mapping { class Mapping {
private: private:
@@ -50,16 +53,27 @@ namespace ams::kern {
constexpr ALWAYS_INLINE size_t GetSize() const { return m_size; } constexpr ALWAYS_INLINE size_t GetSize() const { return m_size; }
constexpr ALWAYS_INLINE KMemoryState GetMemoryState() const { return m_state; } constexpr ALWAYS_INLINE KMemoryState GetMemoryState() const { return m_state; }
}; };
public:
class DynamicMappings : public KSlabAllocated<DynamicMappings, true> {
private:
Mapping m_mappings[NumDynamicMappings];
public:
constexpr explicit DynamicMappings() : m_mappings() { /* ... */ }
constexpr ALWAYS_INLINE Mapping &Get(size_t idx) { return m_mappings[idx]; }
constexpr ALWAYS_INLINE const Mapping &Get(size_t idx) const { return m_mappings[idx]; }
};
static_assert(sizeof(DynamicMappings) == sizeof(Mapping) * NumDynamicMappings);
private: private:
Mapping m_static_mappings[NumStaticMappings]; Mapping m_static_mappings[NumStaticMappings];
Mapping *m_mappings; DynamicMappings *m_dynamic_mappings;
u8 m_num_send; u8 m_num_send;
u8 m_num_recv; u8 m_num_recv;
u8 m_num_exch; u8 m_num_exch;
public: public:
constexpr explicit SessionMappings(util::ConstantInitializeTag) : m_static_mappings(), m_mappings(), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ } constexpr explicit SessionMappings(util::ConstantInitializeTag) : m_static_mappings(), m_dynamic_mappings(), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
explicit SessionMappings() : m_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ } explicit SessionMappings() : m_dynamic_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
void Initialize() { /* ... */ } void Initialize() { /* ... */ }
void Finalize(); void Finalize();
@@ -96,7 +110,7 @@ namespace ams::kern {
if (index < NumStaticMappings) { if (index < NumStaticMappings) {
return m_static_mappings[index]; return m_static_mappings[index];
} else { } else {
return m_mappings[index - NumStaticMappings]; return m_dynamic_mappings->Get(index - NumStaticMappings);
} }
} }
@@ -107,7 +121,7 @@ namespace ams::kern {
if (index < NumStaticMappings) { if (index < NumStaticMappings) {
return m_static_mappings[index]; return m_static_mappings[index];
} else { } else {
return m_mappings[index - NumStaticMappings]; return m_dynamic_mappings->Get(index - NumStaticMappings);
} }
} }
@@ -118,7 +132,7 @@ namespace ams::kern {
if (index < NumStaticMappings) { if (index < NumStaticMappings) {
return m_static_mappings[index]; return m_static_mappings[index];
} else { } else {
return m_mappings[index - NumStaticMappings]; return m_dynamic_mappings->Get(index - NumStaticMappings);
} }
} }
}; };

View File

@@ -35,7 +35,7 @@ namespace ams::kern {
bool m_is_initialized; bool m_is_initialized;
public: public:
explicit KSharedMemory() explicit KSharedMemory()
: m_page_group(std::addressof(Kernel::GetSystemBlockInfoManager())), m_resource_limit(nullptr), m_owner_process_id(std::numeric_limits<u64>::max()), : m_page_group(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer()), m_resource_limit(nullptr), m_owner_process_id(std::numeric_limits<u64>::max()),
m_owner_perm(ams::svc::MemoryPermission_None), m_remote_perm(ams::svc::MemoryPermission_None), m_is_initialized(false) m_owner_perm(ams::svc::MemoryPermission_None), m_remote_perm(ams::svc::MemoryPermission_None), m_is_initialized(false)
{ {
/* ... */ /* ... */

View File

@@ -21,11 +21,22 @@ namespace ams::kern {
struct InitialProcessBinaryLayout; struct InitialProcessBinaryLayout;
namespace init {
struct KInitArguments;
}
} }
namespace ams::kern { namespace ams::kern {
class KResourceLimit;
class KSystemControlBase { class KSystemControlBase {
public:
/* This can be overridden as needed. */
static constexpr size_t SecureAppletMemorySize = 0;
protected: protected:
/* Nintendo uses std::mt19937_t for randomness. */ /* Nintendo uses std::mt19937_t for randomness. */
/* To save space (and because mt19337_t isn't secure anyway), */ /* To save space (and because mt19337_t isn't secure anyway), */
@@ -35,6 +46,8 @@ namespace ams::kern {
static constinit inline KSpinLock s_random_lock; static constinit inline KSpinLock s_random_lock;
public: public:
class Init { class Init {
private:
static void CpuOnImpl(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
public: public:
/* Initialization. */ /* Initialization. */
static size_t GetRealMemorySize(); static size_t GetRealMemorySize();
@@ -42,7 +55,7 @@ namespace ams::kern {
static KPhysicalAddress GetKernelPhysicalBaseAddress(KPhysicalAddress base_address); static KPhysicalAddress GetKernelPhysicalBaseAddress(KPhysicalAddress base_address);
static void GetInitialProcessBinaryLayout(InitialProcessBinaryLayout *out); static void GetInitialProcessBinaryLayout(InitialProcessBinaryLayout *out);
static bool ShouldIncreaseThreadResourceLimit(); static bool ShouldIncreaseThreadResourceLimit();
static void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg); static void TurnOnCpu(u64 core_id, const ams::kern::init::KInitArguments *args);
static size_t GetApplicationPoolSize(); static size_t GetApplicationPoolSize();
static size_t GetAppletPoolSize(); static size_t GetAppletPoolSize();
static size_t GetMinimumNonSecureSystemPoolSize(); static size_t GetMinimumNonSecureSystemPoolSize();
@@ -52,9 +65,11 @@ namespace ams::kern {
static void GenerateRandom(u64 *dst, size_t count); static void GenerateRandom(u64 *dst, size_t count);
static u64 GenerateRandomRange(u64 min, u64 max); static u64 GenerateRandomRange(u64 min, u64 max);
}; };
protected:
static NOINLINE void InitializePhase1Base(u64 seed);
public: public:
/* Initialization. */ /* Initialization. */
static NOINLINE void InitializePhase1(bool skip_target_system = false); static NOINLINE void InitializePhase1();
static NOINLINE void InitializePhase2(); static NOINLINE void InitializePhase2();
static NOINLINE u32 GetCreateProcessMemoryPool(); static NOINLINE u32 GetCreateProcessMemoryPool();
@@ -83,6 +98,10 @@ namespace ams::kern {
static size_t CalculateRequiredSecureMemorySize(size_t size, u32 pool); static size_t CalculateRequiredSecureMemorySize(size_t size, u32 pool);
static Result AllocateSecureMemory(KVirtualAddress *out, size_t size, u32 pool); static Result AllocateSecureMemory(KVirtualAddress *out, size_t size, u32 pool);
static void FreeSecureMemory(KVirtualAddress address, size_t size, u32 pool); static void FreeSecureMemory(KVirtualAddress address, size_t size, u32 pool);
/* Insecure Memory. */
static KResourceLimit *GetInsecureMemoryResourceLimit();
static u32 GetInsecureMemoryPool();
protected: protected:
template<typename F> template<typename F>
static ALWAYS_INLINE u64 GenerateUniformRange(u64 min, u64 max, F f) { static ALWAYS_INLINE u64 GenerateUniformRange(u64 min, u64 max, F f) {

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <mesosphere/kern_common.hpp>
#include <mesosphere/kern_k_auto_object.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
#include <mesosphere/kern_k_memory_manager.hpp>
#include <mesosphere/kern_k_dynamic_resource_manager.hpp>
#include <mesosphere/kern_k_page_table_manager.hpp>
#include <mesosphere/kern_k_resource_limit.hpp>
namespace ams::kern {
/* NOTE: Nintendo's implementation does not have the "is_secure_resource" field, and instead uses virtual IsSecureResource(). */
class KSystemResource : public KAutoObject {
MESOSPHERE_AUTOOBJECT_TRAITS(KSystemResource, KAutoObject);
private:
KMemoryBlockSlabManager *m_p_memory_block_slab_manager{};
KBlockInfoManager *m_p_block_info_manager{};
KPageTableManager *m_p_page_table_manager{};
bool m_is_secure_resource{false};
public:
explicit KSystemResource() : KAutoObject() { /* ... */ }
constexpr explicit KSystemResource(util::ConstantInitializeTag) : KAutoObject(util::ConstantInitialize) { /* ... */ }
protected:
ALWAYS_INLINE void SetSecureResource() { m_is_secure_resource = true; }
public:
virtual void Destroy() override { MESOSPHERE_PANIC("KSystemResource::Destroy() was called"); }
ALWAYS_INLINE bool IsSecureResource() const { return m_is_secure_resource; }
void SetManagers(KMemoryBlockSlabManager &mb, KBlockInfoManager &bi, KPageTableManager &pt) {
MESOSPHERE_ASSERT(m_p_memory_block_slab_manager == nullptr);
MESOSPHERE_ASSERT(m_p_block_info_manager == nullptr);
MESOSPHERE_ASSERT(m_p_page_table_manager == nullptr);
m_p_memory_block_slab_manager = std::addressof(mb);
m_p_block_info_manager = std::addressof(bi);
m_p_page_table_manager = std::addressof(pt);
}
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return *m_p_memory_block_slab_manager; }
const KBlockInfoManager &GetBlockInfoManager() const { return *m_p_block_info_manager; }
const KPageTableManager &GetPageTableManager() const { return *m_p_page_table_manager; }
KMemoryBlockSlabManager &GetMemoryBlockSlabManager() { return *m_p_memory_block_slab_manager; }
KBlockInfoManager &GetBlockInfoManager() { return *m_p_block_info_manager; }
KPageTableManager &GetPageTableManager() { return *m_p_page_table_manager; }
KMemoryBlockSlabManager *GetMemoryBlockSlabManagerPointer() { return m_p_memory_block_slab_manager; }
KBlockInfoManager *GetBlockInfoManagerPointer() { return m_p_block_info_manager; }
KPageTableManager *GetPageTableManagerPointer() { return m_p_page_table_manager; }
};
class KSecureSystemResource final : public KAutoObjectWithSlabHeap<KSecureSystemResource, KSystemResource> {
private:
bool m_is_initialized;
KMemoryManager::Pool m_resource_pool;
KDynamicPageManager m_dynamic_page_manager;
KMemoryBlockSlabManager m_memory_block_slab_manager;
KBlockInfoManager m_block_info_manager;
KPageTableManager m_page_table_manager;
KMemoryBlockSlabHeap m_memory_block_heap;
KBlockInfoSlabHeap m_block_info_heap;
KPageTableSlabHeap m_page_table_heap;
KResourceLimit *m_resource_limit;
KVirtualAddress m_resource_address;
size_t m_resource_size;
public:
explicit KSecureSystemResource() : m_is_initialized(false), m_resource_limit(nullptr) {
/* Mark ourselves as being a secure resource. */
this->SetSecureResource();
}
Result Initialize(size_t size, KResourceLimit *resource_limit, KMemoryManager::Pool pool);
void Finalize();
bool IsInitialized() const { return m_is_initialized; }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
ALWAYS_INLINE size_t CalculateRequiredSecureMemorySize() const {
return CalculateRequiredSecureMemorySize(m_resource_size, m_resource_pool);
}
ALWAYS_INLINE size_t GetSize() const { return m_resource_size; }
ALWAYS_INLINE size_t GetUsedSize() const { return m_dynamic_page_manager.GetUsed() * PageSize; }
const KDynamicPageManager &GetDynamicPageManager() const { return m_dynamic_page_manager; }
public:
static size_t CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool);
};
}

View File

@@ -108,10 +108,12 @@ namespace ams::kern {
u8 exception_flags; u8 exception_flags;
bool is_pinned; bool is_pinned;
u8 reserved_2f; u8 reserved_2f;
u8 reserved_30[0x10];
KThreadContext context; KThreadContext context;
}; };
static_assert(util::IsAligned(AMS_OFFSETOF(StackParameters, context), 0x10)); static_assert(util::IsAligned(AMS_OFFSETOF(StackParameters, context), 0x10));
static_assert(sizeof(StackParameters) == THREAD_STACK_PARAMETERS_SIZE);
static_assert(AMS_OFFSETOF(StackParameters, svc_access_flags) == THREAD_STACK_PARAMETERS_SVC_PERMISSION); static_assert(AMS_OFFSETOF(StackParameters, svc_access_flags) == THREAD_STACK_PARAMETERS_SVC_PERMISSION);
static_assert(AMS_OFFSETOF(StackParameters, caller_save_fpu_registers) == THREAD_STACK_PARAMETERS_CALLER_SAVE_FPU_REGISTERS); static_assert(AMS_OFFSETOF(StackParameters, caller_save_fpu_registers) == THREAD_STACK_PARAMETERS_CALLER_SAVE_FPU_REGISTERS);
@@ -123,8 +125,10 @@ namespace ams::kern {
static_assert(AMS_OFFSETOF(StackParameters, exception_flags) == THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS); static_assert(AMS_OFFSETOF(StackParameters, exception_flags) == THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS);
static_assert(AMS_OFFSETOF(StackParameters, is_pinned) == THREAD_STACK_PARAMETERS_IS_PINNED); static_assert(AMS_OFFSETOF(StackParameters, is_pinned) == THREAD_STACK_PARAMETERS_IS_PINNED);
static_assert(AMS_OFFSETOF(StackParameters, reserved_2f) == THREAD_STACK_PARAMETERS_RESERVED_2F); static_assert(AMS_OFFSETOF(StackParameters, reserved_2f) == THREAD_STACK_PARAMETERS_RESERVED_2F);
static_assert(AMS_OFFSETOF(StackParameters, reserved_30) == THREAD_STACK_PARAMETERS_RESERVED_30);
static_assert(AMS_OFFSETOF(StackParameters, context) == THREAD_STACK_PARAMETERS_THREAD_CONTEXT); static_assert(AMS_OFFSETOF(StackParameters, context) == THREAD_STACK_PARAMETERS_THREAD_CONTEXT);
static_assert(ExceptionFlag_IsCallingSvc == THREAD_EXCEPTION_FLAG_IS_CALLING_SVC); static_assert(ExceptionFlag_IsCallingSvc == THREAD_EXCEPTION_FLAG_IS_CALLING_SVC);
static_assert(ExceptionFlag_IsInExceptionHandler == THREAD_EXCEPTION_FLAG_IS_IN_EXCEPTION_HANDLER); static_assert(ExceptionFlag_IsInExceptionHandler == THREAD_EXCEPTION_FLAG_IS_IN_EXCEPTION_HANDLER);
static_assert(ExceptionFlag_IsFpuContextRestoreNeeded == THREAD_EXCEPTION_FLAG_IS_FPU_CONTEXT_RESTORE_NEEDED); static_assert(ExceptionFlag_IsFpuContextRestoreNeeded == THREAD_EXCEPTION_FLAG_IS_FPU_CONTEXT_RESTORE_NEEDED);
@@ -197,6 +201,28 @@ namespace ams::kern {
}; };
static_assert(ams::util::HasRedBlackKeyType<ConditionVariableComparator>); static_assert(ams::util::HasRedBlackKeyType<ConditionVariableComparator>);
static_assert(std::same_as<ams::util::RedBlackKeyType<ConditionVariableComparator, void>, ConditionVariableComparator::RedBlackKeyType>); static_assert(std::same_as<ams::util::RedBlackKeyType<ConditionVariableComparator, void>, ConditionVariableComparator::RedBlackKeyType>);
struct LockWithPriorityInheritanceComparator {
struct RedBlackKeyType {
s32 m_priority;
constexpr ALWAYS_INLINE s32 GetPriority() const {
return m_priority;
}
};
template<typename T> requires (std::same_as<T, KThread> || std::same_as<T, RedBlackKeyType>)
static constexpr ALWAYS_INLINE int Compare(const T &lhs, const KThread &rhs) {
if (lhs.GetPriority() < rhs.GetPriority()) {
/* Sort by priority. */
return -1;
} else {
return 1;
}
}
};
static_assert(ams::util::HasRedBlackKeyType<LockWithPriorityInheritanceComparator>);
static_assert(std::same_as<ams::util::RedBlackKeyType<LockWithPriorityInheritanceComparator, void>, LockWithPriorityInheritanceComparator::RedBlackKeyType>);
private: private:
util::IntrusiveListNode m_process_list_node; util::IntrusiveListNode m_process_list_node;
util::IntrusiveRedBlackTreeNode m_condvar_arbiter_tree_node; util::IntrusiveRedBlackTreeNode m_condvar_arbiter_tree_node;
@@ -205,6 +231,67 @@ namespace ams::kern {
using ConditionVariableThreadTreeTraits = util::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&KThread::m_condvar_arbiter_tree_node>; using ConditionVariableThreadTreeTraits = util::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&KThread::m_condvar_arbiter_tree_node>;
using ConditionVariableThreadTree = ConditionVariableThreadTreeTraits::TreeType<ConditionVariableComparator>; using ConditionVariableThreadTree = ConditionVariableThreadTreeTraits::TreeType<ConditionVariableComparator>;
using LockWithPriorityInheritanceThreadTreeTraits = util::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&KThread::m_condvar_arbiter_tree_node>;
using LockWithPriorityInheritanceThreadTree = ConditionVariableThreadTreeTraits::TreeType<LockWithPriorityInheritanceComparator>;
public:
class LockWithPriorityInheritanceInfo : public KSlabAllocated<LockWithPriorityInheritanceInfo>, public util::IntrusiveListBaseNode<LockWithPriorityInheritanceInfo> {
private:
LockWithPriorityInheritanceThreadTree m_tree;
KProcessAddress m_address_key;
KThread *m_owner;
u32 m_waiter_count;
public:
constexpr LockWithPriorityInheritanceInfo() : m_tree(), m_address_key(Null<KProcessAddress>), m_owner(nullptr), m_waiter_count() {
/* ... */
}
static LockWithPriorityInheritanceInfo *Create(KProcessAddress address_key) {
/* Create a new lock info. */
auto *new_lock = LockWithPriorityInheritanceInfo::Allocate();
MESOSPHERE_ABORT_UNLESS(new_lock != nullptr);
/* Set the new lock's address key. */
new_lock->m_address_key = address_key;
return new_lock;
}
void SetOwner(KThread *new_owner) {
/* Set new owner. */
m_owner = new_owner;
}
void AddWaiter(KThread *waiter) {
/* Insert the waiter. */
m_tree.insert(*waiter);
m_waiter_count++;
waiter->SetWaitingLockInfo(this);
}
[[nodiscard]] bool RemoveWaiter(KThread *waiter) {
m_tree.erase(m_tree.iterator_to(*waiter));
waiter->SetWaitingLockInfo(nullptr);
return (--m_waiter_count) == 0;
}
KThread *GetHighestPriorityWaiter() { return std::addressof(m_tree.front()); }
const KThread *GetHighestPriorityWaiter() const { return std::addressof(m_tree.front()); }
LockWithPriorityInheritanceThreadTree &GetThreadTree() { return m_tree; }
const LockWithPriorityInheritanceThreadTree &GetThreadTree() const { return m_tree; }
constexpr KProcessAddress GetAddressKey() const { return m_address_key; }
constexpr KThread *GetOwner() const { return m_owner; }
constexpr u32 GetWaiterCount() const { return m_waiter_count; }
};
private:
using LockWithPriorityInheritanceInfoList = util::IntrusiveListBaseTraits<LockWithPriorityInheritanceInfo>::ListType;
ConditionVariableThreadTree *m_condvar_tree; ConditionVariableThreadTree *m_condvar_tree;
uintptr_t m_condvar_key; uintptr_t m_condvar_key;
alignas(16) KThreadContext::CallerSaveFpuRegisters m_caller_save_fpu_registers; alignas(16) KThreadContext::CallerSaveFpuRegisters m_caller_save_fpu_registers;
@@ -224,9 +311,9 @@ namespace ams::kern {
s64 m_last_scheduled_tick; s64 m_last_scheduled_tick;
QueueEntry m_per_core_priority_queue_entry[cpu::NumCores]; QueueEntry m_per_core_priority_queue_entry[cpu::NumCores];
KThreadQueue *m_wait_queue; KThreadQueue *m_wait_queue;
WaiterList m_waiter_list; LockWithPriorityInheritanceInfoList m_held_lock_info_list;
LockWithPriorityInheritanceInfo *m_waiting_lock_info;
WaiterList m_pinned_waiter_list; WaiterList m_pinned_waiter_list;
KThread *m_lock_owner;
uintptr_t m_debug_params[3]; uintptr_t m_debug_params[3];
KAutoObject *m_closed_object; KAutoObject *m_closed_object;
u32 m_address_key_value; u32 m_address_key_value;
@@ -260,8 +347,8 @@ namespace ams::kern {
m_process_list_node{}, m_condvar_arbiter_tree_node{util::ConstantInitialize}, m_priority{-1}, m_condvar_tree{}, m_condvar_key{}, 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_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_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_waiter_list{}, m_pinned_waiter_list{}, 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_lock_owner{}, m_debug_params{}, m_closed_object{}, m_address_key_value{}, m_suspend_request_flags{}, m_suspend_allowed_flags{}, m_synced_index{}, 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_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_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_original_physical_ideal_core_id{}, m_num_core_migration_disables{}, m_thread_state{}, m_termination_requested{false}, m_wait_cancelled{},
@@ -407,6 +494,10 @@ namespace ams::kern {
void ClearUsermodeExceptionSvcPermissions(); void ClearUsermodeExceptionSvcPermissions();
private: private:
void UpdateState(); void UpdateState();
ALWAYS_INLINE void AddHeldLock(LockWithPriorityInheritanceInfo *lock_info);
ALWAYS_INLINE LockWithPriorityInheritanceInfo *FindHeldLock(KProcessAddress address_key);
ALWAYS_INLINE void AddWaiterImpl(KThread *thread); ALWAYS_INLINE void AddWaiterImpl(KThread *thread);
ALWAYS_INLINE void RemoveWaiterImpl(KThread *thread); ALWAYS_INLINE void RemoveWaiterImpl(KThread *thread);
ALWAYS_INLINE static void RestorePriority(KThread *thread); ALWAYS_INLINE static void RestorePriority(KThread *thread);
@@ -441,6 +532,8 @@ namespace ams::kern {
constexpr uintptr_t GetAddressArbiterKey() const { return m_condvar_key; } constexpr uintptr_t GetAddressArbiterKey() const { return m_condvar_key; }
constexpr void SetConditionVariable(ConditionVariableThreadTree *tree, KProcessAddress address, uintptr_t cv_key, u32 value) { constexpr void SetConditionVariable(ConditionVariableThreadTree *tree, KProcessAddress address, uintptr_t cv_key, u32 value) {
MESOSPHERE_ASSERT(m_waiting_lock_info == nullptr);
m_condvar_tree = tree; m_condvar_tree = tree;
m_condvar_key = cv_key; m_condvar_key = cv_key;
m_address_key = address; m_address_key = address;
@@ -456,6 +549,8 @@ namespace ams::kern {
} }
constexpr void SetAddressArbiter(ConditionVariableThreadTree *tree, uintptr_t address) { constexpr void SetAddressArbiter(ConditionVariableThreadTree *tree, uintptr_t address) {
MESOSPHERE_ASSERT(m_waiting_lock_info == nullptr);
m_condvar_tree = tree; m_condvar_tree = tree;
m_condvar_key = address; m_condvar_key = address;
} }
@@ -491,15 +586,17 @@ namespace ams::kern {
void AddWaiter(KThread *thread); void AddWaiter(KThread *thread);
void RemoveWaiter(KThread *thread); void RemoveWaiter(KThread *thread);
KThread *RemoveWaiterByKey(s32 *out_num_waiters, KProcessAddress key); KThread *RemoveWaiterByKey(bool *out_has_waiters, KProcessAddress key);
constexpr KProcessAddress GetAddressKey() const { return m_address_key; } constexpr KProcessAddress GetAddressKey() const { return m_address_key; }
constexpr u32 GetAddressKeyValue() const { return m_address_key_value; } constexpr u32 GetAddressKeyValue() const { return m_address_key_value; }
constexpr void SetAddressKey(KProcessAddress key) { m_address_key = key; } constexpr void SetAddressKey(KProcessAddress key) { MESOSPHERE_ASSERT(m_waiting_lock_info == nullptr); m_address_key = key; }
constexpr void SetAddressKey(KProcessAddress key, u32 val) { m_address_key = key; m_address_key_value = val; } constexpr void SetAddressKey(KProcessAddress key, u32 val) { MESOSPHERE_ASSERT(m_waiting_lock_info == nullptr); m_address_key = key; m_address_key_value = val; }
constexpr void SetLockOwner(KThread *owner) { m_lock_owner = owner; } constexpr void SetWaitingLockInfo(LockWithPriorityInheritanceInfo *lock) { m_waiting_lock_info = lock; }
constexpr KThread *GetLockOwner() const { return m_lock_owner; } constexpr LockWithPriorityInheritanceInfo *GetWaitingLockInfo() { return m_waiting_lock_info; }
constexpr KThread *GetLockOwner() const { return m_waiting_lock_info != nullptr ? m_waiting_lock_info->GetOwner() : nullptr; }
constexpr void ClearWaitQueue() { m_wait_queue = nullptr; } constexpr void ClearWaitQueue() { m_wait_queue = nullptr; }
@@ -529,8 +626,6 @@ namespace ams::kern {
constexpr u32 *GetLightSessionData() const { return m_light_ipc_data; } constexpr u32 *GetLightSessionData() const { return m_light_ipc_data; }
constexpr void SetLightSessionData(u32 *data) { m_light_ipc_data = data; } constexpr void SetLightSessionData(u32 *data) { m_light_ipc_data = data; }
bool HasWaiters() const { return !m_waiter_list.empty(); }
constexpr s64 GetLastScheduledTick() const { return m_last_scheduled_tick; } constexpr s64 GetLastScheduledTick() const { return m_last_scheduled_tick; }
constexpr void SetLastScheduledTick(s64 tick) { m_last_scheduled_tick = tick; } constexpr void SetLastScheduledTick(s64 tick) { m_last_scheduled_tick = tick; }

View File

@@ -120,10 +120,6 @@ namespace ams::kern {
return m_address == rhs; return m_address == rhs;
} }
constexpr ALWAYS_INLINE bool operator!=(uintptr_t rhs) const {
return m_address != rhs;
}
/* Allow getting the address explicitly, for use in accessors. */ /* Allow getting the address explicitly, for use in accessors. */
constexpr ALWAYS_INLINE uintptr_t GetValue() const { constexpr ALWAYS_INLINE uintptr_t GetValue() const {
return m_address; return m_address;

View File

@@ -63,7 +63,7 @@ namespace ams::kern {
static constexpr size_t ApplicationMemoryBlockSlabHeapSize = 20000; static constexpr size_t ApplicationMemoryBlockSlabHeapSize = 20000;
static constexpr size_t SystemMemoryBlockSlabHeapSize = 10000; static constexpr size_t SystemMemoryBlockSlabHeapSize = 10000;
static constexpr size_t BlockInfoSlabHeapSize = 4000; static constexpr size_t BlockInfoSlabHeapSize = 4000;
static constexpr size_t ReservedDynamicPageCount = 70; static constexpr size_t ReservedDynamicPageCount = 64;
private: private:
static State s_state; static State s_state;
static KResourceLimit s_system_resource_limit; static KResourceLimit s_system_resource_limit;
@@ -78,6 +78,8 @@ namespace ams::kern {
static KMemoryBlockSlabManager s_sys_memory_block_manager; static KMemoryBlockSlabManager s_sys_memory_block_manager;
static KBlockInfoManager s_app_block_info_manager; static KBlockInfoManager s_app_block_info_manager;
static KBlockInfoManager s_sys_block_info_manager; static KBlockInfoManager s_sys_block_info_manager;
static KSystemResource s_app_system_resource;
static KSystemResource s_sys_system_resource;
static KSupervisorPageTable s_supervisor_page_table; static KSupervisorPageTable s_supervisor_page_table;
static KUnsafeMemory s_unsafe_memory; static KUnsafeMemory s_unsafe_memory;
static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count]; static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
@@ -129,28 +131,12 @@ namespace ams::kern {
return s_memory_manager; return s_memory_manager;
} }
static ALWAYS_INLINE KMemoryBlockSlabManager &GetApplicationMemoryBlockManager() { static ALWAYS_INLINE KSystemResource &GetApplicationSystemResource() {
return s_app_memory_block_manager; return s_app_system_resource;
} }
static ALWAYS_INLINE KMemoryBlockSlabManager &GetSystemMemoryBlockManager() { static ALWAYS_INLINE KSystemResource &GetSystemSystemResource() {
return s_sys_memory_block_manager; return s_sys_system_resource;
}
static ALWAYS_INLINE KBlockInfoManager &GetApplicationBlockInfoManager() {
return s_app_block_info_manager;
}
static ALWAYS_INLINE KBlockInfoManager &GetSystemBlockInfoManager() {
return s_sys_block_info_manager;
}
static ALWAYS_INLINE KPageTableManager &GetApplicationPageTableManager() {
return s_app_page_table_manager;
}
static ALWAYS_INLINE KPageTableManager &GetSystemPageTableManager() {
return s_sys_page_table_manager;
} }
static ALWAYS_INLINE KSupervisorPageTable &GetKernelPageTable() { static ALWAYS_INLINE KSupervisorPageTable &GetKernelPageTable() {

View File

@@ -64,11 +64,13 @@ namespace ams::kern {
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); } static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
}; };
template<typename Derived, typename Base, bool SupportDynamicExpansion = false> requires std::derived_from<Base, KAutoObjectWithList> template<typename Derived, typename Base, bool SupportDynamicExpansion> requires std::derived_from<Base, KAutoObject>
class KAutoObjectWithSlabHeapAndContainer : public Base { class KAutoObjectWithSlabHeapBase : public Base {
private:
template<typename, typename, bool> friend class KAutoObjectWithSlabHeap;
template<typename, typename, bool> friend class KAutoObjectWithSlabHeapAndContainer;
private: private:
static constinit inline KSlabHeap<Derived, SupportDynamicExpansion> s_slab_heap; static constinit inline KSlabHeap<Derived, SupportDynamicExpansion> s_slab_heap;
static constinit inline KAutoObjectWithListContainer<Derived> s_container;
private: private:
static ALWAYS_INLINE Derived *Allocate() { static ALWAYS_INLINE Derived *Allocate() {
return s_slab_heap.Allocate(); return s_slab_heap.Allocate();
@@ -77,12 +79,6 @@ namespace ams::kern {
static ALWAYS_INLINE void Free(Derived *obj) { static ALWAYS_INLINE void Free(Derived *obj) {
s_slab_heap.Free(obj); s_slab_heap.Free(obj);
} }
public:
class ListAccessor : public KAutoObjectWithListContainer<Derived>::ListAccessor {
public:
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer<Derived>::ListAccessor(s_container) { /* ... */ }
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
};
private: private:
static ALWAYS_INLINE bool IsInitialized(const Derived *obj) { static ALWAYS_INLINE bool IsInitialized(const Derived *obj) {
if constexpr (requires { { obj->IsInitialized() } -> std::same_as<bool>; }) { if constexpr (requires { { obj->IsInitialized() } -> std::same_as<bool>; }) {
@@ -100,9 +96,9 @@ namespace ams::kern {
} }
} }
public: public:
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ } constexpr explicit KAutoObjectWithSlabHeapBase(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ } explicit KAutoObjectWithSlabHeapBase() { /* ... */ }
/* NOTE: IsInitialized() and GetPostDestroyArgument() are virtual functions declared in this class, */ /* NOTE: IsInitialized() and GetPostDestroyArgument() are virtual functions declared in this class, */
/* in Nintendo's kernel. We fully devirtualize them, as Destroy() is the only user of them. */ /* in Nintendo's kernel. We fully devirtualize them, as Destroy() is the only user of them. */
@@ -110,14 +106,14 @@ namespace ams::kern {
virtual void Destroy() override final { virtual void Destroy() override final {
Derived * const derived = static_cast<Derived *>(this); Derived * const derived = static_cast<Derived *>(this);
if (IsInitialized(derived)) { if (KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::IsInitialized(derived)) {
s_container.Unregister(derived); Derived::PreFinalize(derived);
const uintptr_t arg = GetPostDestroyArgument(derived); const uintptr_t arg = KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::GetPostDestroyArgument(derived);
derived->Finalize(); derived->Finalize();
Free(derived); KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::Free(derived);
Derived::PostDestroy(arg); Derived::PostDestroy(arg);
} else { } else {
Free(derived); KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::Free(derived);
} }
} }
@@ -127,7 +123,6 @@ namespace ams::kern {
public: public:
static void InitializeSlabHeap(void *memory, size_t memory_size) { static void InitializeSlabHeap(void *memory, size_t memory_size) {
s_slab_heap.Initialize(memory, memory_size); s_slab_heap.Initialize(memory, memory_size);
s_container.Initialize();
} }
static Derived *Create() { static Derived *Create() {
@@ -150,10 +145,6 @@ namespace ams::kern {
return obj; return obj;
} }
static void Register(Derived *obj) {
return s_container.Register(obj);
}
static size_t GetObjectSize() { return s_slab_heap.GetObjectSize(); } static size_t GetObjectSize() { return s_slab_heap.GetObjectSize(); }
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); } static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); } static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
@@ -162,4 +153,43 @@ namespace ams::kern {
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); } static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
}; };
template<typename Derived, typename Base, bool SupportDynamicExpansion = false>
class KAutoObjectWithSlabHeap : public KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion> {
public:
constexpr explicit KAutoObjectWithSlabHeap(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeap() { /* ... */ }
static ALWAYS_INLINE void PreFinalize(Derived *) { /* ... */ }
};
template<typename Derived, typename Base, bool SupportDynamicExpansion = false>
class KAutoObjectWithSlabHeapAndContainer : public KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion> {
static_assert(std::derived_from<Base, KAutoObjectWithList>);
private:
static constinit inline KAutoObjectWithListContainer<Derived> s_container;
public:
class ListAccessor : public KAutoObjectWithListContainer<Derived>::ListAccessor {
public:
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer<Derived>::ListAccessor(s_container) { /* ... */ }
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
};
public:
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
public:
static void InitializeSlabHeap(void *memory, size_t memory_size) {
KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::InitializeSlabHeap(memory, memory_size);
s_container.Initialize();
}
static void Register(Derived *obj) {
return s_container.Register(obj);
}
static ALWAYS_INLINE void PreFinalize(Derived *obj) { s_container.Unregister(obj); }
};
} }

View File

@@ -38,6 +38,25 @@ namespace ams::kern::arch::arm64::cpu {
ALWAYS_INLINE ~KScopedCoreMigrationDisable() { GetCurrentThread().EnableCoreMigration(); } ALWAYS_INLINE ~KScopedCoreMigrationDisable() { GetCurrentThread().EnableCoreMigration(); }
}; };
class KScopedCacheMaintenance {
private:
bool m_active;
public:
ALWAYS_INLINE KScopedCacheMaintenance() {
__asm__ __volatile__("" ::: "memory");
if (m_active = !GetCurrentThread().IsInCacheMaintenanceOperation(); m_active) {
GetCurrentThread().SetInCacheMaintenanceOperation();
}
}
ALWAYS_INLINE ~KScopedCacheMaintenance() {
if (m_active) {
GetCurrentThread().ClearInCacheMaintenanceOperation();
}
__asm__ __volatile__("" ::: "memory");
}
};
/* Nintendo registers a handler for a SGI on thread termination, but does not handle anything. */ /* Nintendo registers a handler for a SGI on thread termination, but does not handle anything. */
/* This is sufficient, because post-interrupt scheduling is all they really intend to occur. */ /* This is sufficient, because post-interrupt scheduling is all they really intend to occur. */
class KThreadTerminationInterruptHandler : public KInterruptHandler { class KThreadTerminationInterruptHandler : public KInterruptHandler {
@@ -432,9 +451,7 @@ namespace ams::kern::arch::arm64::cpu {
Result InvalidateDataCache(void *addr, size_t size) { Result InvalidateDataCache(void *addr, size_t size) {
/* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */ /* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */
__asm__ __volatile__("" ::: "memory"); KScopedCacheMaintenance cm;
GetCurrentThread().SetInCacheMaintenanceOperation();
ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); };
const uintptr_t start = reinterpret_cast<uintptr_t>(addr); const uintptr_t start = reinterpret_cast<uintptr_t>(addr);
const uintptr_t end = start + size; const uintptr_t end = start + size;
@@ -460,9 +477,7 @@ namespace ams::kern::arch::arm64::cpu {
Result StoreDataCache(const void *addr, size_t size) { Result StoreDataCache(const void *addr, size_t size) {
/* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */ /* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */
__asm__ __volatile__("" ::: "memory"); KScopedCacheMaintenance cm;
GetCurrentThread().SetInCacheMaintenanceOperation();
ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); };
const uintptr_t start = util::AlignDown(reinterpret_cast<uintptr_t>(addr), DataCacheLineSize); const uintptr_t start = util::AlignDown(reinterpret_cast<uintptr_t>(addr), DataCacheLineSize);
const uintptr_t end = util::AlignUp( reinterpret_cast<uintptr_t>(addr) + size, DataCacheLineSize); const uintptr_t end = util::AlignUp( reinterpret_cast<uintptr_t>(addr) + size, DataCacheLineSize);
@@ -472,9 +487,7 @@ namespace ams::kern::arch::arm64::cpu {
Result FlushDataCache(const void *addr, size_t size) { Result FlushDataCache(const void *addr, size_t size) {
/* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */ /* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */
__asm__ __volatile__("" ::: "memory"); KScopedCacheMaintenance cm;
GetCurrentThread().SetInCacheMaintenanceOperation();
ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); };
const uintptr_t start = util::AlignDown(reinterpret_cast<uintptr_t>(addr), DataCacheLineSize); const uintptr_t start = util::AlignDown(reinterpret_cast<uintptr_t>(addr), DataCacheLineSize);
const uintptr_t end = util::AlignUp( reinterpret_cast<uintptr_t>(addr) + size, DataCacheLineSize); const uintptr_t end = util::AlignUp( reinterpret_cast<uintptr_t>(addr) + size, DataCacheLineSize);

View File

@@ -25,8 +25,6 @@ namespace ams::kern::arch::arm64 {
namespace { namespace {
constexpr inline u32 El0PsrMask = 0xFF0FFE20;
enum EsrEc : u32 { enum EsrEc : u32 {
EsrEc_Unknown = 0b000000, EsrEc_Unknown = 0b000000,
EsrEc_WaitForInterruptOrEvent = 0b000001, EsrEc_WaitForInterruptOrEvent = 0b000001,
@@ -134,7 +132,7 @@ namespace ams::kern::arch::arm64 {
info->sp = context->sp; info->sp = context->sp;
info->lr = context->x[30]; info->lr = context->x[30];
info->pc = context->pc; info->pc = context->pc;
info->pstate = (context->psr & El0PsrMask); info->pstate = (context->psr & cpu::El0Aarch64PsrMask);
info->afsr0 = afsr0; info->afsr0 = afsr0;
info->afsr1 = afsr1; info->afsr1 = afsr1;
info->esr = esr; info->esr = esr;
@@ -151,7 +149,7 @@ namespace ams::kern::arch::arm64 {
info->pc = context->pc; info->pc = context->pc;
info->flags = 1; info->flags = 1;
info->status_64.pstate = (context->psr & El0PsrMask); info->status_64.pstate = (context->psr & cpu::El0Aarch32PsrMask);
info->status_64.afsr0 = afsr0; info->status_64.afsr0 = afsr0;
info->status_64.afsr1 = afsr1; info->status_64.afsr1 = afsr1;
info->status_64.esr = esr; info->status_64.esr = esr;
@@ -231,73 +229,71 @@ namespace ams::kern::arch::arm64 {
{ {
/* Collect additional information based on the ec. */ /* Collect additional information based on the ec. */
ams::svc::DebugException exception; uintptr_t params[3] = {};
uintptr_t param2 = 0;
uintptr_t param3 = 0;
switch (ec) { switch (ec) {
case EsrEc_Unknown: case EsrEc_Unknown:
case EsrEc_IllegalExecution: case EsrEc_IllegalExecution:
case EsrEc_BkptInstruction: case EsrEc_BkptInstruction:
case EsrEc_BrkInstruction: case EsrEc_BrkInstruction:
{ {
exception = ams::svc::DebugException_UndefinedInstruction; params[0] = ams::svc::DebugException_UndefinedInstruction;
param2 = far; params[1] = far;
param3 = data; params[2] = data;
} }
break; break;
case EsrEc_PcAlignmentFault: case EsrEc_PcAlignmentFault:
case EsrEc_SpAlignmentFault: case EsrEc_SpAlignmentFault:
{ {
exception = ams::svc::DebugException_AlignmentFault; params[0] = ams::svc::DebugException_AlignmentFault;
param2 = far; params[1] = far;
} }
break; break;
case EsrEc_Svc32: case EsrEc_Svc32:
case EsrEc_Svc64: case EsrEc_Svc64:
{ {
exception = ams::svc::DebugException_UndefinedSystemCall; params[0] = ams::svc::DebugException_UndefinedSystemCall;
param2 = far; params[1] = far;
param3 = (esr & 0xFF); params[2] = (esr & 0xFF);
} }
break; break;
case EsrEc_BreakPointEl0: case EsrEc_BreakPointEl0:
case EsrEc_SoftwareStepEl0: case EsrEc_SoftwareStepEl0:
{ {
exception = ams::svc::DebugException_BreakPoint; params[0] = ams::svc::DebugException_BreakPoint;
param2 = far; params[1] = far;
param3 = ams::svc::BreakPointType_HardwareInstruction; params[2] = ams::svc::BreakPointType_HardwareInstruction;
} }
break; break;
case EsrEc_WatchPointEl0: case EsrEc_WatchPointEl0:
{ {
exception = ams::svc::DebugException_BreakPoint; params[0] = ams::svc::DebugException_BreakPoint;
param2 = far; params[1] = far;
param3 = ams::svc::BreakPointType_HardwareData; params[2] = ams::svc::BreakPointType_HardwareData;
} }
break; break;
case EsrEc_SErrorInterrupt: case EsrEc_SErrorInterrupt:
{ {
exception = ams::svc::DebugException_MemorySystemError; params[0] = ams::svc::DebugException_MemorySystemError;
param2 = far; params[1] = far;
} }
break; break;
case EsrEc_InstructionAbortEl0: case EsrEc_InstructionAbortEl0:
{ {
exception = ams::svc::DebugException_InstructionAbort; params[0] = ams::svc::DebugException_InstructionAbort;
param2 = far; params[1] = far;
} }
break; break;
case EsrEc_DataAbortEl0: case EsrEc_DataAbortEl0:
default: default:
{ {
exception = ams::svc::DebugException_DataAbort; params[0] = ams::svc::DebugException_DataAbort;
param2 = far; params[1] = far;
} }
break; break;
} }
/* Process the debug event. */ /* Process the debug event. */
Result result = KDebug::OnDebugEvent(ams::svc::DebugEvent_Exception, exception, param2, param3); Result result = KDebug::OnDebugEvent(ams::svc::DebugEvent_Exception, params, util::size(params));
/* If we should stop processing the exception, do so. */ /* If we should stop processing the exception, do so. */
if (svc::ResultStopProcessingException::Includes(result)) { if (svc::ResultStopProcessingException::Includes(result)) {
@@ -342,7 +338,7 @@ namespace ams::kern::arch::arm64 {
/* If the SVC is handled, handle it. */ /* If the SVC is handled, handle it. */
if (!svc::ResultNotHandled::Includes(result)) { if (!svc::ResultNotHandled::Includes(result)) {
/* If we successfully enter jit debug, stop processing the exception. */ /* If we successfully enter jit debug, stop processing the exception. */
if (cur_process.EnterJitDebug(ams::svc::DebugEvent_Exception, exception, param2, param3)) { if (cur_process.EnterJitDebug(ams::svc::DebugEvent_Exception, static_cast<ams::svc::DebugException>(params[0]), params[1], params[2])) {
return; return;
} }
} }
@@ -399,7 +395,7 @@ namespace ams::kern::arch::arm64 {
e_ctx->x[30] = info.info64.lr; e_ctx->x[30] = info.info64.lr;
e_ctx->sp = info.info64.sp; e_ctx->sp = info.info64.sp;
e_ctx->pc = info.info64.pc; e_ctx->pc = info.info64.pc;
e_ctx->psr = (info.info64.pstate & El0PsrMask) | (e_ctx->psr & ~El0PsrMask); e_ctx->psr = (info.info64.pstate & cpu::El0Aarch64PsrMask) | (e_ctx->psr & ~cpu::El0Aarch64PsrMask);
} else { } else {
for (size_t i = 0; i < util::size(info.info32.r); ++i) { for (size_t i = 0; i < util::size(info.info32.r); ++i) {
e_ctx->x[i] = info.info32.r[i]; e_ctx->x[i] = info.info32.r[i];
@@ -407,7 +403,7 @@ namespace ams::kern::arch::arm64 {
e_ctx->x[14] = info.info32.lr; e_ctx->x[14] = info.info32.lr;
e_ctx->x[13] = info.info32.sp; e_ctx->x[13] = info.info32.sp;
e_ctx->pc = info.info32.pc; e_ctx->pc = info.info32.pc;
e_ctx->psr = (info.info32.status_64.pstate & El0PsrMask) | (e_ctx->psr & ~El0PsrMask); e_ctx->psr = (info.info32.status_64.pstate & cpu::El0Aarch32PsrMask) | (e_ctx->psr & ~cpu::El0Aarch32PsrMask);
} }
/* Note that PC was adjusted. */ /* Note that PC was adjusted. */
@@ -422,58 +418,56 @@ namespace ams::kern::arch::arm64 {
GetCurrentThread().RestoreDebugParams(std::addressof(far), std::addressof(esr), std::addressof(data)); GetCurrentThread().RestoreDebugParams(std::addressof(far), std::addressof(esr), std::addressof(data));
/* Collect additional information based on the ec. */ /* Collect additional information based on the ec. */
ams::svc::DebugException exception; uintptr_t params[3] = {};
uintptr_t param2 = 0;
uintptr_t param3 = 0;
switch ((esr >> 26) & 0x3F) { switch ((esr >> 26) & 0x3F) {
case EsrEc_Unknown: case EsrEc_Unknown:
case EsrEc_IllegalExecution: case EsrEc_IllegalExecution:
case EsrEc_BkptInstruction: case EsrEc_BkptInstruction:
case EsrEc_BrkInstruction: case EsrEc_BrkInstruction:
{ {
exception = ams::svc::DebugException_UndefinedInstruction; params[0] = ams::svc::DebugException_UndefinedInstruction;
param2 = far; params[1] = far;
param3 = data; params[2] = data;
} }
break; break;
case EsrEc_PcAlignmentFault: case EsrEc_PcAlignmentFault:
case EsrEc_SpAlignmentFault: case EsrEc_SpAlignmentFault:
{ {
exception = ams::svc::DebugException_AlignmentFault; params[0] = ams::svc::DebugException_AlignmentFault;
param2 = far; params[1] = far;
} }
break; break;
case EsrEc_Svc32: case EsrEc_Svc32:
case EsrEc_Svc64: case EsrEc_Svc64:
{ {
exception = ams::svc::DebugException_UndefinedSystemCall; params[0] = ams::svc::DebugException_UndefinedSystemCall;
param2 = far; params[1] = far;
param3 = (esr & 0xFF); params[2] = (esr & 0xFF);
} }
break; break;
case EsrEc_SErrorInterrupt: case EsrEc_SErrorInterrupt:
{ {
exception = ams::svc::DebugException_MemorySystemError; params[0] = ams::svc::DebugException_MemorySystemError;
param2 = far; params[1] = far;
} }
break; break;
case EsrEc_InstructionAbortEl0: case EsrEc_InstructionAbortEl0:
{ {
exception = ams::svc::DebugException_InstructionAbort; params[0] = ams::svc::DebugException_InstructionAbort;
param2 = far; params[1] = far;
} }
break; break;
case EsrEc_DataAbortEl0: case EsrEc_DataAbortEl0:
default: default:
{ {
exception = ams::svc::DebugException_DataAbort; params[0] = ams::svc::DebugException_DataAbort;
param2 = far; params[1] = far;
} }
break; break;
} }
/* Process the debug event. */ /* Process the debug event. */
Result result = KDebug::OnDebugEvent(ams::svc::DebugEvent_Exception, exception, param2, param3); Result result = KDebug::OnDebugEvent(ams::svc::DebugEvent_Exception, params, util::size(params));
/* If the SVC is handled, handle it. */ /* If the SVC is handled, handle it. */
if (!svc::ResultNotHandled::Includes(result)) { if (!svc::ResultNotHandled::Includes(result)) {
@@ -483,7 +477,7 @@ namespace ams::kern::arch::arm64 {
} }
/* If we successfully enter jit debug, restore. */ /* If we successfully enter jit debug, restore. */
if (cur_process.EnterJitDebug(ams::svc::DebugEvent_Exception, exception, param2, param3)) { if (cur_process.EnterJitDebug(ams::svc::DebugEvent_Exception, static_cast<ams::svc::DebugException>(params[0]), params[1], params[2])) {
svc::RestoreContext(reinterpret_cast<uintptr_t>(e_ctx)); svc::RestoreContext(reinterpret_cast<uintptr_t>(e_ctx));
} }
} }

View File

@@ -37,8 +37,6 @@ namespace ams::kern::arch::arm64 {
static_assert(ForbiddenWatchPointFlagsMask == 0xFFFFFFFF00F0E006ul); static_assert(ForbiddenWatchPointFlagsMask == 0xFFFFFFFF00F0E006ul);
constexpr inline u32 El0PsrMask = 0xFF0FFE20;
} }
uintptr_t KDebug::GetProgramCounter(const KThread &thread) { uintptr_t KDebug::GetProgramCounter(const KThread &thread) {
@@ -104,7 +102,7 @@ namespace ams::kern::arch::arm64 {
out->lr = e_ctx->x[30]; out->lr = e_ctx->x[30];
out->sp = e_ctx->sp; out->sp = e_ctx->sp;
out->pc = e_ctx->pc; out->pc = e_ctx->pc;
out->pstate = (e_ctx->psr & El0PsrMask); out->pstate = (e_ctx->psr & cpu::El0Aarch64PsrMask);
/* Adjust PC if we should. */ /* Adjust PC if we should. */
if (e_ctx->write == 0 && thread->IsCallingSvc()) { if (e_ctx->write == 0 && thread->IsCallingSvc()) {
@@ -119,7 +117,7 @@ namespace ams::kern::arch::arm64 {
out->lr = 0; out->lr = 0;
out->sp = 0; out->sp = 0;
out->pc = e_ctx->pc; out->pc = e_ctx->pc;
out->pstate = (e_ctx->psr & El0PsrMask); out->pstate = (e_ctx->psr & cpu::El0Aarch32PsrMask);
/* Adjust PC if we should. */ /* Adjust PC if we should. */
if (e_ctx->write == 0 && thread->IsCallingSvc()) { if (e_ctx->write == 0 && thread->IsCallingSvc()) {
@@ -166,7 +164,7 @@ namespace ams::kern::arch::arm64 {
e_ctx->x[30] = ctx.lr; e_ctx->x[30] = ctx.lr;
e_ctx->sp = ctx.sp; e_ctx->sp = ctx.sp;
e_ctx->pc = ctx.pc; e_ctx->pc = ctx.pc;
e_ctx->psr = ((ctx.pstate & El0PsrMask) | (e_ctx->psr & ~El0PsrMask)); e_ctx->psr = ((ctx.pstate & cpu::El0Aarch64PsrMask) | (e_ctx->psr & ~cpu::El0Aarch64PsrMask));
e_ctx->tpidr = ctx.tpidr; e_ctx->tpidr = ctx.tpidr;
} else { } else {
e_ctx->x[13] = static_cast<u32>(ctx.r[13]); e_ctx->x[13] = static_cast<u32>(ctx.r[13]);
@@ -174,7 +172,7 @@ namespace ams::kern::arch::arm64 {
e_ctx->x[30] = 0; e_ctx->x[30] = 0;
e_ctx->sp = 0; e_ctx->sp = 0;
e_ctx->pc = static_cast<u32>(ctx.pc); e_ctx->pc = static_cast<u32>(ctx.pc);
e_ctx->psr = ((ctx.pstate & El0PsrMask) | (e_ctx->psr & ~El0PsrMask)); e_ctx->psr = ((ctx.pstate & cpu::El0Aarch32PsrMask) | (e_ctx->psr & ~cpu::El0Aarch32PsrMask));
e_ctx->tpidr = ctx.tpidr; e_ctx->tpidr = ctx.tpidr;
} }
} }
@@ -251,7 +249,8 @@ namespace ams::kern::arch::arm64 {
} }
Result KDebug::BreakIfAttached(ams::svc::BreakReason break_reason, uintptr_t address, size_t size) { Result KDebug::BreakIfAttached(ams::svc::BreakReason break_reason, uintptr_t address, size_t size) {
R_RETURN(KDebugBase::OnDebugEvent(ams::svc::DebugEvent_Exception, ams::svc::DebugException_UserBreak, GetProgramCounter(GetCurrentThread()), break_reason, address, size)); const uintptr_t params[5] = { ams::svc::DebugException_UserBreak, GetProgramCounter(GetCurrentThread()), break_reason, address, size };
R_RETURN(KDebugBase::OnDebugEvent(ams::svc::DebugEvent_Exception, params, util::size(params)));
} }
#define MESOSPHERE_SET_HW_BREAK_POINT(ID, FLAGS, VALUE) \ #define MESOSPHERE_SET_HW_BREAK_POINT(ID, FLAGS, VALUE) \

View File

@@ -192,7 +192,7 @@ namespace ams::kern::arch::arm64 {
Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) { Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
/* Initialize basic fields. */ /* Initialize basic fields. */
m_asid = 0; m_asid = 0;
m_manager = std::addressof(Kernel::GetSystemPageTableManager()); m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer();
/* Allocate a page for ttbr. */ /* Allocate a page for ttbr. */
/* NOTE: It is a postcondition of page table manager allocation that the page is all-zero. */ /* NOTE: It is a postcondition of page table manager allocation that the page is all-zero. */
@@ -207,7 +207,7 @@ namespace ams::kern::arch::arm64 {
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager, KResourceLimit *resource_limit) { Result KPageTable::InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
/* The input ID isn't actually used. */ /* The input ID isn't actually used. */
MESOSPHERE_UNUSED(id); MESOSPHERE_UNUSED(id);
@@ -216,7 +216,7 @@ namespace ams::kern::arch::arm64 {
ON_RESULT_FAILURE { g_asid_manager.Release(m_asid); }; ON_RESULT_FAILURE { g_asid_manager.Release(m_asid); };
/* Set our manager. */ /* Set our manager. */
m_manager = pt_manager; m_manager = system_resource->GetPageTableManagerPointer();
/* Allocate a new table, and set our ttbr value. */ /* Allocate a new table, and set our ttbr value. */
const KVirtualAddress new_table = m_manager->Allocate(); const KVirtualAddress new_table = m_manager->Allocate();
@@ -228,7 +228,7 @@ namespace ams::kern::arch::arm64 {
const size_t as_width = GetAddressSpaceWidth(as_type); const size_t as_width = GetAddressSpaceWidth(as_type);
const KProcessAddress as_start = 0; const KProcessAddress as_start = 0;
const KProcessAddress as_end = (1ul << as_width); const KProcessAddress as_end = (1ul << as_width);
R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, mem_block_slab_manager, block_info_manager, resource_limit)); R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, system_resource, resource_limit));
/* Note that we've updated the table (since we created it). */ /* Note that we've updated the table (since we created it). */
this->NoteUpdated(); this->NoteUpdated();
@@ -348,7 +348,7 @@ namespace ams::kern::arch::arm64 {
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(virt_addr), PageSize)); MESOSPHERE_ASSERT(util::IsAligned(GetInteger(virt_addr), PageSize));
MESOSPHERE_ASSERT(this->ContainsPages(virt_addr, num_pages)); MESOSPHERE_ASSERT(this->ContainsPages(virt_addr, num_pages));
if (operation == OperationType_Map) { if (operation == OperationType_Map || operation == OperationType_MapFirst) {
MESOSPHERE_ABORT_UNLESS(is_pa_valid); MESOSPHERE_ABORT_UNLESS(is_pa_valid);
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(phys_addr), PageSize)); MESOSPHERE_ASSERT(util::IsAligned(GetInteger(phys_addr), PageSize));
} else { } else {
@@ -357,16 +357,32 @@ namespace ams::kern::arch::arm64 {
if (operation == OperationType_Unmap) { if (operation == OperationType_Unmap) {
R_RETURN(this->Unmap(virt_addr, num_pages, page_list, false, reuse_ll)); R_RETURN(this->Unmap(virt_addr, num_pages, page_list, false, reuse_ll));
} else if (operation == OperationType_Separate) {
const size_t size = num_pages * PageSize;
R_TRY(this->SeparatePages(virt_addr, std::min(util::GetAlignment(GetInteger(virt_addr)), size), page_list, reuse_ll));
ON_RESULT_FAILURE { this->MergePages(virt_addr, page_list); };
if (num_pages > 1) {
const auto end_page = virt_addr + size;
const auto last_page = end_page - PageSize;
R_TRY(this->SeparatePages(last_page, std::min(util::GetAlignment(GetInteger(end_page)), size), page_list, reuse_ll));
}
R_SUCCEED();
} else { } else {
auto entry_template = this->GetEntryTemplate(properties); auto entry_template = this->GetEntryTemplate(properties);
switch (operation) { switch (operation) {
case OperationType_Map: case OperationType_Map:
R_RETURN(this->MapContiguous(virt_addr, phys_addr, num_pages, entry_template, properties.disable_merge_attributes == DisableMergeAttribute_DisableHead, page_list, reuse_ll)); case OperationType_MapFirst:
R_RETURN(this->MapContiguous(virt_addr, phys_addr, num_pages, entry_template, properties.disable_merge_attributes == DisableMergeAttribute_DisableHead, operation != OperationType_MapFirst, page_list, reuse_ll));
case OperationType_ChangePermissions: case OperationType_ChangePermissions:
R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, false, page_list, reuse_ll)); R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, false, false, page_list, reuse_ll));
case OperationType_ChangePermissionsAndRefresh: case OperationType_ChangePermissionsAndRefresh:
R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, true, page_list, reuse_ll)); R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, true, false, page_list, reuse_ll));
case OperationType_ChangePermissionsAndRefreshAndFlush:
R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, true, true, page_list, reuse_ll));
MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
} }
} }
@@ -740,7 +756,7 @@ namespace ams::kern::arch::arm64 {
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll) { Result KPageTable::MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, bool not_first, PageLinkedList *page_list, bool reuse_ll) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
/* Cache initial addresses for use on cleanup. */ /* Cache initial addresses for use on cleanup. */
@@ -811,7 +827,11 @@ namespace ams::kern::arch::arm64 {
/* Open references to the pages, if we should. */ /* Open references to the pages, if we should. */
if (IsHeapPhysicalAddress(orig_phys_addr)) { if (IsHeapPhysicalAddress(orig_phys_addr)) {
Kernel::GetMemoryManager().Open(orig_phys_addr, num_pages); if (not_first) {
Kernel::GetMemoryManager().Open(orig_phys_addr, num_pages);
} else {
Kernel::GetMemoryManager().OpenFirst(orig_phys_addr, num_pages);
}
} }
R_SUCCEED(); R_SUCCEED();
@@ -1215,7 +1235,7 @@ namespace ams::kern::arch::arm64 {
R_RETURN(this->SeparatePagesImpl(virt_addr, block_size, page_list, reuse_ll)); R_RETURN(this->SeparatePagesImpl(virt_addr, block_size, page_list, reuse_ll));
} }
Result KPageTable::ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll) { Result KPageTable::ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, bool flush_mapping, PageLinkedList *page_list, bool reuse_ll) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
/* Separate pages before we change permissions. */ /* Separate pages before we change permissions. */
@@ -1433,8 +1453,8 @@ namespace ams::kern::arch::arm64 {
KScopedSchedulerLock sl; KScopedSchedulerLock sl;
} }
/* Finally, apply the changes as directed, flushing the mappings before they're applied. */ /* Finally, apply the changes as directed, flushing the mappings before they're applied (if we should). */
ApplyEntryTemplate(entry_template, ApplyOption_FlushDataCache); ApplyEntryTemplate(entry_template, flush_mapping ? ApplyOption_FlushDataCache : ApplyOption_None);
} }
/* We've succeeded, now perform what coalescing we can. */ /* We've succeeded, now perform what coalescing we can. */

View File

@@ -353,12 +353,12 @@ namespace ams::kern::arch::arm64 {
l1_entry->IsPrivilegedExecuteNever(), l1_entry->IsPrivilegedExecuteNever(),
l1_entry->IsContiguous(), l1_entry->IsContiguous(),
!l1_entry->IsGlobal(), !l1_entry->IsGlobal(),
static_cast<int>(l1_entry->GetAccessFlag()), static_cast<int>(l1_entry->GetAccessFlagInteger()),
static_cast<unsigned int>(l1_entry->GetShareable()), static_cast<unsigned int>(l1_entry->GetShareableInteger()),
l1_entry->IsReadOnly(), l1_entry->IsReadOnly(),
l1_entry->IsUserAccessible(), l1_entry->IsUserAccessible(),
l1_entry->IsNonSecure(), l1_entry->IsNonSecure(),
static_cast<int>(l1_entry->GetPageAttribute()), static_cast<int>(l1_entry->GetPageAttributeInteger()),
l1_entry->IsHeadMergeDisabled(), l1_entry->IsHeadMergeDisabled(),
l1_entry->IsHeadAndBodyMergeDisabled(), l1_entry->IsHeadAndBodyMergeDisabled(),
l1_entry->IsTailMergeDisabled()); l1_entry->IsTailMergeDisabled());
@@ -398,12 +398,12 @@ namespace ams::kern::arch::arm64 {
l2_entry->IsPrivilegedExecuteNever(), l2_entry->IsPrivilegedExecuteNever(),
l2_entry->IsContiguous(), l2_entry->IsContiguous(),
!l2_entry->IsGlobal(), !l2_entry->IsGlobal(),
static_cast<int>(l2_entry->GetAccessFlag()), static_cast<int>(l2_entry->GetAccessFlagInteger()),
static_cast<unsigned int>(l2_entry->GetShareable()), static_cast<unsigned int>(l2_entry->GetShareableInteger()),
l2_entry->IsReadOnly(), l2_entry->IsReadOnly(),
l2_entry->IsUserAccessible(), l2_entry->IsUserAccessible(),
l2_entry->IsNonSecure(), l2_entry->IsNonSecure(),
static_cast<int>(l2_entry->GetPageAttribute()), static_cast<int>(l2_entry->GetPageAttributeInteger()),
l2_entry->IsHeadMergeDisabled(), l2_entry->IsHeadMergeDisabled(),
l2_entry->IsHeadAndBodyMergeDisabled(), l2_entry->IsHeadAndBodyMergeDisabled(),
l2_entry->IsTailMergeDisabled()); l2_entry->IsTailMergeDisabled());
@@ -443,12 +443,12 @@ namespace ams::kern::arch::arm64 {
l3_entry->IsPrivilegedExecuteNever(), l3_entry->IsPrivilegedExecuteNever(),
l3_entry->IsContiguous(), l3_entry->IsContiguous(),
!l3_entry->IsGlobal(), !l3_entry->IsGlobal(),
static_cast<int>(l3_entry->GetAccessFlag()), static_cast<int>(l3_entry->GetAccessFlagInteger()),
static_cast<unsigned int>(l3_entry->GetShareable()), static_cast<unsigned int>(l3_entry->GetShareableInteger()),
l3_entry->IsReadOnly(), l3_entry->IsReadOnly(),
l3_entry->IsUserAccessible(), l3_entry->IsUserAccessible(),
l3_entry->IsNonSecure(), l3_entry->IsNonSecure(),
static_cast<int>(l3_entry->GetPageAttribute()), static_cast<int>(l3_entry->GetPageAttributeInteger()),
l3_entry->IsHeadMergeDisabled(), l3_entry->IsHeadMergeDisabled(),
l3_entry->IsHeadAndBodyMergeDisabled(), l3_entry->IsHeadAndBodyMergeDisabled(),
l3_entry->IsTailMergeDisabled()); l3_entry->IsTailMergeDisabled());

View File

@@ -26,7 +26,9 @@ namespace ams::kern::arch::arm64 {
/* Send KDebug event for this thread's creation. */ /* Send KDebug event for this thread's creation. */
{ {
KScopedInterruptEnable ei; KScopedInterruptEnable ei;
KDebug::OnDebugEvent(ams::svc::DebugEvent_CreateThread, GetCurrentThread().GetId(), GetInteger(GetCurrentThread().GetThreadLocalRegionAddress()));
const uintptr_t params[2] = { GetCurrentThread().GetId(), GetInteger(GetCurrentThread().GetThreadLocalRegionAddress()) };
KDebug::OnDebugEvent(ams::svc::DebugEvent_CreateThread, params, util::size(params));
} }
/* Handle any pending dpc. */ /* Handle any pending dpc. */
@@ -40,8 +42,6 @@ namespace ams::kern::arch::arm64 {
namespace { namespace {
constexpr inline u32 El0PsrMask = 0xFF0FFE20;
ALWAYS_INLINE bool IsFpuEnabled() { ALWAYS_INLINE bool IsFpuEnabled() {
return cpu::ArchitecturalFeatureAccessControlRegisterAccessor().IsFpEnabled(); return cpu::ArchitecturalFeatureAccessControlRegisterAccessor().IsFpEnabled();
} }
@@ -96,8 +96,8 @@ namespace ams::kern::arch::arm64 {
/* SP */ /* SP */
/* | */ /* | */
/* v */ /* v */
/* | u64 argument | u64 entrypoint | KThread::StackParameters (size 0x130) | */ /* | u64 argument | u64 entrypoint | KThread::StackParameters (size 0x140) | */
static_assert(sizeof(KThread::StackParameters) == 0x130); static_assert(sizeof(KThread::StackParameters) == 0x140);
u64 *stack = GetPointer<u64>(sp); u64 *stack = GetPointer<u64>(sp);
*(--stack) = GetInteger(pc); *(--stack) = GetInteger(pc);
@@ -191,7 +191,7 @@ namespace ams::kern::arch::arm64 {
out->lr = e_ctx->x[30]; out->lr = e_ctx->x[30];
out->sp = e_ctx->sp; out->sp = e_ctx->sp;
out->pc = e_ctx->pc; out->pc = e_ctx->pc;
out->pstate = e_ctx->psr & El0PsrMask; out->pstate = e_ctx->psr & cpu::El0Aarch64PsrMask;
/* Get the thread's general purpose registers. */ /* Get the thread's general purpose registers. */
if (thread->IsCallingSvc()) { if (thread->IsCallingSvc()) {
@@ -227,7 +227,7 @@ namespace ams::kern::arch::arm64 {
} else { } else {
/* Set special registers. */ /* Set special registers. */
out->pc = static_cast<u32>(e_ctx->pc); out->pc = static_cast<u32>(e_ctx->pc);
out->pstate = e_ctx->psr & El0PsrMask; out->pstate = e_ctx->psr & cpu::El0Aarch32PsrMask;
/* Get the thread's general purpose registers. */ /* Get the thread's general purpose registers. */
for (size_t i = 0; i < 15; ++i) { for (size_t i = 0; i < 15; ++i) {

View File

@@ -596,8 +596,11 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess17ReadIoMemory32BitEPvPKvm:
/* Save our return address. */ /* Save our return address. */
mov x8, x30 mov x8, x30
/* Prepare return address for read failure. */
adr x10, 4f
1: /* Set our return address so that on read failure we continue as though we read -1. */ 1: /* Set our return address so that on read failure we continue as though we read -1. */
adr x30, 4f mov x30, x10
/* Read the word from io. */ /* Read the word from io. */
ldtr w9, [x5] ldtr w9, [x5]
@@ -643,8 +646,11 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess17ReadIoMemory16BitEPvPKvm:
/* Save our return address. */ /* Save our return address. */
mov x8, x30 mov x8, x30
/* Prepare return address for read failure. */
adr x10, 4f
1: /* Set our return address so that on read failure we continue as though we read -1. */ 1: /* Set our return address so that on read failure we continue as though we read -1. */
adr x30, 4f mov x30, x10
/* Read the word from io. */ /* Read the word from io. */
ldtrh w9, [x5] ldtrh w9, [x5]
@@ -690,8 +696,11 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess16ReadIoMemory8BitEPvPKvm:
/* Save our return address. */ /* Save our return address. */
mov x8, x30 mov x8, x30
/* Prepare return address for read failure. */
adr x10, 4f
1: /* Set our return address so that on read failure we continue as though we read -1. */ 1: /* Set our return address so that on read failure we continue as though we read -1. */
adr x30, 4f mov x30, x10
/* Read the word from io. */ /* Read the word from io. */
ldtrb w9, [x5] ldtrb w9, [x5]
@@ -737,11 +746,14 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess18WriteIoMemory32BitEPvPKvm:
/* Save our return address. */ /* Save our return address. */
mov x8, x30 mov x8, x30
/* Prepare return address for failure. */
adr x10, 2f
1: /* Read the word from normal memory. */ 1: /* Read the word from normal memory. */
ldtr w9, [x5] ldtr w9, [x5]
/* Set our return address so that on read failure we continue. */ /* Set our return address so that on failure we continue. */
adr x30, 2f mov x30, x10
/* Write the word to io. */ /* Write the word to io. */
sttr w9, [x5] sttr w9, [x5]
@@ -779,11 +791,14 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess18WriteIoMemory16BitEPvPKvm:
/* Save our return address. */ /* Save our return address. */
mov x8, x30 mov x8, x30
/* Prepare return address for failure. */
adr x10, 2f
1: /* Read the word from normal memory. */ 1: /* Read the word from normal memory. */
ldtrh w9, [x5] ldtrh w9, [x5]
/* Set our return address so that on read failure we continue. */ /* Set our return address so that on failure we continue. */
adr x30, 2f mov x30, x10
/* Write the word to io. */ /* Write the word to io. */
sttrh w9, [x5] sttrh w9, [x5]
@@ -821,11 +836,14 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess17WriteIoMemory8BitEPvPKvm:
/* Save our return address. */ /* Save our return address. */
mov x8, x30 mov x8, x30
/* Prepare return address for failure. */
adr x10, 2f
1: /* Read the word from normal memory. */ 1: /* Read the word from normal memory. */
ldtrb w9, [x5] ldtrb w9, [x5]
/* Set our return address so that on read failure we continue. */ /* Set our return address so that on failure we continue. */
adr x30, 2f mov x30, x10
/* Write the word to io. */ /* Write the word to io. */
sttrb w9, [x5] sttrb w9, [x5]

View File

@@ -86,9 +86,10 @@ _ZN3ams4kern3svc14RestoreContextEm:
/* Get our exception flags. */ /* Get our exception flags. */
ldrb w9, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)] ldrb w9, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)]
/* Clear in-svc and needs-fpu-restore flags. */ /* Clear in-svc, in-user-exception, and needs-fpu-restore flags. */
and w10, w9, #(~(THREAD_EXCEPTION_FLAG_IS_FPU_CONTEXT_RESTORE_NEEDED)) and w10, w9, #(~(THREAD_EXCEPTION_FLAG_IS_FPU_CONTEXT_RESTORE_NEEDED))
and w10, w10, #(~(THREAD_EXCEPTION_FLAG_IS_CALLING_SVC)) and w10, w10, #(~(THREAD_EXCEPTION_FLAG_IS_CALLING_SVC))
and w10, w10, #(~(THREAD_EXCEPTION_FLAG_IS_IN_USERMODE_EXCEPTION_HANDLER))
strb w10, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)] strb w10, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)]
/* If we don't need to restore the fpu, skip restoring it. */ /* If we don't need to restore the fpu, skip restoring it. */

View File

@@ -651,11 +651,13 @@ namespace ams::kern::board::nintendo::nx {
g_memory_controller_address = KMemoryLayout::GetDevicePhysicalAddress(KMemoryRegionType_MemoryController); g_memory_controller_address = KMemoryLayout::GetDevicePhysicalAddress(KMemoryRegionType_MemoryController);
/* Allocate a page to use as a reserved/no device table. */ /* Allocate a page to use as a reserved/no device table. */
const KVirtualAddress table_virt_addr = Kernel::GetSystemPageTableManager().Allocate(); auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
const KVirtualAddress table_virt_addr = ptm.Allocate();
MESOSPHERE_ABORT_UNLESS(table_virt_addr != Null<KVirtualAddress>); MESOSPHERE_ABORT_UNLESS(table_virt_addr != Null<KVirtualAddress>);
const KPhysicalAddress table_phys_addr = GetPageTablePhysicalAddress(table_virt_addr); const KPhysicalAddress table_phys_addr = GetPageTablePhysicalAddress(table_virt_addr);
MESOSPHERE_ASSERT(IsValidPhysicalAddress(table_phys_addr)); MESOSPHERE_ASSERT(IsValidPhysicalAddress(table_phys_addr));
Kernel::GetSystemPageTableManager().Open(table_virt_addr, 1); 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. */ /* 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. */ /* NOTE: Nintendo does not check the result of StoreDataCache. */
@@ -779,7 +781,7 @@ namespace ams::kern::board::nintendo::nx {
const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize; const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize;
/* Get the page table manager. */ /* Get the page table manager. */
auto &ptm = Kernel::GetSystemPageTableManager(); auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
/* Clear the tables. */ /* Clear the tables. */
static_assert(TableCount == (1ul << DeviceVirtualAddressBits) / DeviceRegionSize); static_assert(TableCount == (1ul << DeviceVirtualAddressBits) / DeviceRegionSize);
@@ -839,7 +841,7 @@ namespace ams::kern::board::nintendo::nx {
void KDevicePageTable::Finalize() { void KDevicePageTable::Finalize() {
/* Get the page table manager. */ /* Get the page table manager. */
auto &ptm = Kernel::GetSystemPageTableManager(); auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
/* Detach from all devices. */ /* Detach from all devices. */
{ {
@@ -1014,7 +1016,7 @@ namespace ams::kern::board::nintendo::nx {
/* Get the memory manager and page table manager. */ /* Get the memory manager and page table manager. */
KMemoryManager &mm = Kernel::GetMemoryManager(); KMemoryManager &mm = Kernel::GetMemoryManager();
KPageTableManager &ptm = Kernel::GetSystemPageTableManager(); KPageTableManager &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
/* Cache permissions. */ /* Cache permissions. */
const bool read = (device_perm & ams::svc::MemoryPermission_Read) != 0; const bool read = (device_perm & ams::svc::MemoryPermission_Read) != 0;
@@ -1116,6 +1118,7 @@ namespace ams::kern::board::nintendo::nx {
} }
Result KDevicePageTable::MapImpl(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) { Result KDevicePageTable::MapImpl(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) {
/* Ensure that the region we're mapping to is free. */ /* Ensure that the region we're mapping to is free. */
R_UNLESS(this->IsFree(device_address, size), svc::ResultInvalidCurrentMemory()); R_UNLESS(this->IsFree(device_address, size), svc::ResultInvalidCurrentMemory());
@@ -1130,17 +1133,17 @@ namespace ams::kern::board::nintendo::nx {
size_t cur_size; size_t cur_size;
{ {
/* Get the current contiguous range. */ /* Get the current contiguous range. */
KPageTableBase::MemoryRange contig_range = { .address = Null<KPhysicalAddress>, .size = 0 }; KPageTableBase::MemoryRange contig_range;
R_TRY(page_table->OpenMemoryRangeForMapDeviceAddressSpace(std::addressof(contig_range), process_address + mapped_size, size - mapped_size, ConvertToKMemoryPermission(device_perm), is_aligned)); R_TRY(page_table->OpenMemoryRangeForMapDeviceAddressSpace(std::addressof(contig_range), process_address + mapped_size, size - mapped_size, ConvertToKMemoryPermission(device_perm), is_aligned));
/* Ensure we close the range when we're done. */ /* Ensure we close the range when we're done. */
ON_SCOPE_EXIT { contig_range.Close(); }; ON_SCOPE_EXIT { contig_range.Close(); };
/* Get the current size. */ /* Get the current size. */
cur_size = contig_range.size; cur_size = contig_range.GetSize();
/* Map the device page. */ /* Map the device page. */
R_TRY(this->MapDevicePage(contig_range.address, contig_range.size, cur_addr, device_perm)); R_TRY(this->MapDevicePage(contig_range.GetAddress(), cur_size, cur_addr, device_perm));
} }
/* Advance. */ /* Advance. */
@@ -1158,10 +1161,10 @@ namespace ams::kern::board::nintendo::nx {
/* Get the memory manager and page table manager. */ /* Get the memory manager and page table manager. */
KMemoryManager &mm = Kernel::GetMemoryManager(); KMemoryManager &mm = Kernel::GetMemoryManager();
KPageTableManager &ptm = Kernel::GetSystemPageTableManager(); KPageTableManager &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
/* Make a page group for the pages we're closing. */ /* Make a page group for the pages we're closing. */
KPageGroup pg(std::addressof(Kernel::GetSystemBlockInfoManager())); KPageGroup pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
/* Walk the directory. */ /* Walk the directory. */
u64 remaining = size; u64 remaining = size;
@@ -1285,7 +1288,7 @@ namespace ams::kern::board::nintendo::nx {
MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0); MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0);
/* We need to traverse the ranges that make up our mapping, to make sure they're all good. Start by getting a contiguous range. */ /* We need to traverse the ranges that make up our mapping, to make sure they're all good. Start by getting a contiguous range. */
KPageTableBase::MemoryRange contig_range = { .address = Null<KPhysicalAddress>, .size = 0 }; KPageTableBase::MemoryRange contig_range;
if (R_FAILED(page_table->OpenMemoryRangeForUnmapDeviceAddressSpace(std::addressof(contig_range), process_address, size))) { if (R_FAILED(page_table->OpenMemoryRangeForUnmapDeviceAddressSpace(std::addressof(contig_range), process_address, size))) {
return false; return false;
} }
@@ -1297,8 +1300,8 @@ namespace ams::kern::board::nintendo::nx {
/* Walk the directory. */ /* Walk the directory. */
KProcessAddress cur_process_address = process_address; KProcessAddress cur_process_address = process_address;
size_t remaining_size = size; size_t remaining_size = size;
KPhysicalAddress cur_phys_address = contig_range.address; KPhysicalAddress cur_phys_address = contig_range.GetAddress();
size_t remaining_in_range = contig_range.size; size_t remaining_in_range = contig_range.GetSize();
bool first = true; bool first = true;
u32 first_attr = 0; u32 first_attr = 0;
while (remaining_size > 0) { while (remaining_size > 0) {
@@ -1344,8 +1347,8 @@ namespace ams::kern::board::nintendo::nx {
} }
range_open = true; range_open = true;
cur_phys_address = contig_range.address; cur_phys_address = contig_range.GetAddress();
remaining_in_range = contig_range.size; remaining_in_range = contig_range.GetSize();
} }
/* Check that the physical address is expected. */ /* Check that the physical address is expected. */
@@ -1387,8 +1390,8 @@ namespace ams::kern::board::nintendo::nx {
} }
range_open = true; range_open = true;
cur_phys_address = contig_range.address; cur_phys_address = contig_range.GetAddress();
remaining_in_range = contig_range.size; remaining_in_range = contig_range.GetSize();
} }
/* Check that the physical address is expected, and there's enough in the range. */ /* Check that the physical address is expected, and there's enough in the range. */
@@ -1414,11 +1417,15 @@ namespace ams::kern::board::nintendo::nx {
return true; return true;
} }
Result KDevicePageTable::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) { Result KDevicePageTable::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool is_io) {
/* Validate address/size. */ /* Validate address/size. */
MESOSPHERE_ASSERT((device_address & ~DeviceVirtualAddressMask) == 0); MESOSPHERE_ASSERT((device_address & ~DeviceVirtualAddressMask) == 0);
MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0); MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0);
/* IO is not supported on NX board. */
MESOSPHERE_ASSERT(!is_io);
MESOSPHERE_UNUSED(is_io);
/* Map the pages. */ /* Map the pages. */
R_RETURN(this->MapImpl(page_table, process_address, size, device_address, device_perm, is_aligned)); R_RETURN(this->MapImpl(page_table, process_address, size, device_address, device_perm, is_aligned));
} }

View File

@@ -18,6 +18,12 @@
#include "kern_secure_monitor.hpp" #include "kern_secure_monitor.hpp"
#include "kern_lps_driver.hpp" #include "kern_lps_driver.hpp"
namespace ams::kern::init {
void StartOtherCore(const ams::kern::init::KInitArguments *init_args);
}
namespace ams::kern::board::nintendo::nx { namespace ams::kern::board::nintendo::nx {
namespace { namespace {
@@ -67,15 +73,10 @@ namespace ams::kern::board::nintendo::nx {
constinit KLightLock g_request_lock; constinit KLightLock g_request_lock;
constinit KLightLock g_cv_lock; constinit KLightLock g_cv_lock;
constinit KLightConditionVariable g_cv{util::ConstantInitialize}; constinit KLightConditionVariable g_cv{util::ConstantInitialize};
constinit KPhysicalAddress g_sleep_buffer_phys_addrs[cpu::NumCores];
alignas(1_KB) constinit u64 g_sleep_buffers[cpu::NumCores][1_KB / sizeof(u64)]; alignas(1_KB) constinit u64 g_sleep_buffers[cpu::NumCores][1_KB / sizeof(u64)];
constinit ams::kern::init::KInitArguments g_sleep_init_arguments[cpu::NumCores];
constinit SavedSystemRegisters g_sleep_system_registers[cpu::NumCores] = {}; constinit SavedSystemRegisters g_sleep_system_registers[cpu::NumCores] = {};
void PowerOnCpu(int core_id, KPhysicalAddress entry_phys_addr, u64 context_id) {
/* Request the secure monitor power on the core. */
::ams::kern::arch::arm64::smc::CpuOn<smc::SmcId_Supervisor, true>(cpu::MultiprocessorAffinityRegisterAccessor().GetCpuOnArgument() | core_id, GetInteger(entry_phys_addr), context_id);
}
void WaitOtherCpuPowerOff() { void WaitOtherCpuPowerOff() {
constexpr u64 PmcPhysicalAddress = 0x7000E400; constexpr u64 PmcPhysicalAddress = 0x7000E400;
constexpr u32 PWRGATE_STATUS_CE123_MASK = ((1u << 3) - 1) << 9; constexpr u32 PWRGATE_STATUS_CE123_MASK = ((1u << 3) - 1) << 9;
@@ -473,18 +474,20 @@ namespace ams::kern::board::nintendo::nx {
} }
} }
void KSleepManager::ProcessRequests(uintptr_t buffer) { void KSleepManager::ProcessRequests(uintptr_t sleep_buffer) {
const auto target_fw = GetTargetFirmware(); const auto target_fw = GetTargetFirmware();
const s32 core_id = GetCurrentCoreId(); const s32 core_id = GetCurrentCoreId();
KPhysicalAddress resume_entry_phys_addr = Null<KPhysicalAddress>;
ams::kern::init::KInitArguments * const init_args = g_sleep_init_arguments + core_id;
KPhysicalAddress start_core_phys_addr = Null<KPhysicalAddress>;
KPhysicalAddress init_args_phys_addr = Null<KPhysicalAddress>;
/* Get the physical addresses we'll need. */ /* Get the physical addresses we'll need. */
{ {
MESOSPHERE_ABORT_UNLESS(Kernel::GetKernelPageTable().GetPhysicalAddress(std::addressof(g_sleep_buffer_phys_addrs[core_id]), KProcessAddress(buffer))); MESOSPHERE_ABORT_UNLESS(Kernel::GetKernelPageTable().GetPhysicalAddress(std::addressof(start_core_phys_addr), KProcessAddress(&::ams::kern::init::StartOtherCore)));
MESOSPHERE_ABORT_UNLESS(Kernel::GetKernelPageTable().GetPhysicalAddress(std::addressof(resume_entry_phys_addr), KProcessAddress(&::ams::kern::board::nintendo::nx::KSleepManager::ResumeEntry))); MESOSPHERE_ABORT_UNLESS(Kernel::GetKernelPageTable().GetPhysicalAddress(std::addressof(init_args_phys_addr), KProcessAddress(init_args)));
} }
const KPhysicalAddress sleep_buffer_phys_addr = g_sleep_buffer_phys_addrs[core_id];
const u64 target_core_mask = (1ul << core_id); const u64 target_core_mask = (1ul << core_id);
const bool use_legacy_lps_driver = target_fw < TargetFirmware_2_0_0; const bool use_legacy_lps_driver = target_fw < TargetFirmware_2_0_0;
@@ -547,15 +550,29 @@ namespace ams::kern::board::nintendo::nx {
/* Save the interrupt manager's state. */ /* Save the interrupt manager's state. */
Kernel::GetInterruptManager().Save(core_id); Kernel::GetInterruptManager().Save(core_id);
/* Setup the initial arguments. */
{
init_args->ttbr0 = cpu::GetTtbr0El1();
init_args->ttbr1 = cpu::GetTtbr1El1();
init_args->tcr = cpu::GetTcrEl1();
init_args->mair = cpu::GetMairEl1();
init_args->cpuactlr = cpu::GetCpuActlrEl1();
init_args->cpuectlr = cpu::GetCpuEctlrEl1();
init_args->sctlr = cpu::GetSctlrEl1();
init_args->sp = 0;
init_args->entrypoint = reinterpret_cast<uintptr_t>(::ams::kern::board::nintendo::nx::KSleepManager::ResumeEntry);
init_args->argument = sleep_buffer;
}
/* Ensure that all cores get to this point before continuing. */ /* Ensure that all cores get to this point before continuing. */
cpu::SynchronizeAllCores(); cpu::SynchronizeAllCores();
/* Log that the core is going to sleep. */ /* Log that the core is going to sleep. */
MESOSPHERE_LOG("Core[%d]: Going to sleep, buffer = %010lx\n", core_id, GetInteger(sleep_buffer_phys_addr)); MESOSPHERE_LOG("Core[%d]: Going to sleep, buffer = %010lx\n", core_id, sleep_buffer);
/* If we're on a core other than zero, we can just invoke the sleep handler. */ /* If we're on a core other than zero, we can just invoke the sleep handler. */
if (core_id != 0) { if (core_id != 0) {
CpuSleepHandler(GetInteger(sleep_buffer_phys_addr), GetInteger(resume_entry_phys_addr)); CpuSleepHandler(sleep_buffer, GetInteger(start_core_phys_addr), GetInteger(init_args_phys_addr));
} else { } else {
/* Wait for all other cores to be powered off. */ /* Wait for all other cores to be powered off. */
WaitOtherCpuPowerOff(); WaitOtherCpuPowerOff();
@@ -574,9 +591,9 @@ namespace ams::kern::board::nintendo::nx {
/* Invoke the sleep handler. */ /* Invoke the sleep handler. */
if (!use_legacy_lps_driver) { if (!use_legacy_lps_driver) {
/* When not using the legacy driver, invoke directly. */ /* When not using the legacy driver, invoke directly. */
CpuSleepHandler(GetInteger(sleep_buffer_phys_addr), GetInteger(resume_entry_phys_addr)); CpuSleepHandler(sleep_buffer, GetInteger(start_core_phys_addr), GetInteger(init_args_phys_addr));
} else { } else {
lps::InvokeCpuSleepHandler(GetInteger(sleep_buffer_phys_addr), GetInteger(resume_entry_phys_addr)); lps::InvokeCpuSleepHandler(sleep_buffer, GetInteger(start_core_phys_addr), GetInteger(init_args_phys_addr));
} }
/* Restore the debug log state. */ /* Restore the debug log state. */
@@ -586,8 +603,10 @@ namespace ams::kern::board::nintendo::nx {
MESOSPHERE_LOG("Exiting SC7\n"); MESOSPHERE_LOG("Exiting SC7\n");
/* Wake up the other cores. */ /* Wake up the other cores. */
cpu::MultiprocessorAffinityRegisterAccessor mpidr;
const auto arg = mpidr.GetCpuOnArgument();
for (s32 i = 1; i < static_cast<s32>(cpu::NumCores); ++i) { for (s32 i = 1; i < static_cast<s32>(cpu::NumCores); ++i) {
PowerOnCpu(i, resume_entry_phys_addr, GetInteger(g_sleep_buffer_phys_addrs[i])); KSystemControl::Init::TurnOnCpu(arg | i, g_sleep_init_arguments + i);
} }
} }

View File

@@ -22,14 +22,12 @@ namespace ams::kern::board::nintendo::nx {
private: private:
static void ResumeEntry(uintptr_t arg); static void ResumeEntry(uintptr_t arg);
static void InvalidateDataCacheForResumeEntry(uintptr_t level);
static void ProcessRequests(uintptr_t buffer); static void ProcessRequests(uintptr_t buffer);
public: public:
static void Initialize(); static void Initialize();
static void SleepSystem(); static void SleepSystem();
public: public:
static void CpuSleepHandler(uintptr_t arg, uintptr_t entry); static void CpuSleepHandler(uintptr_t arg, uintptr_t entry, uintptr_t entry_args);
}; };

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