Compare commits

..

78 Commits
0.10.3 ... erpt

Author SHA1 Message Date
Michael Scire
8e1cf7a7e0 erpt: amend logic for culling orphan attachments 2020-04-12 18:39:03 -07:00
Michael Scire
6b3bf10e46 fatal: update for latest bindings 2020-04-12 18:30:15 -07:00
Michael Scire
16a25309d2 erpt: reimplement the sysmodule 2020-04-11 21:40:14 -07:00
Michael Scire
eca5ac01b8 erpt: include all known types/categories in autogen 2020-04-10 03:33:30 -07:00
Michael Scire
50ea19e7a2 erpt: identify flags in autogen 2020-04-08 10:32:53 -07:00
Michael Scire
823a1f3ea3 erpt: tweak autogen 2020-04-08 10:09:56 -07:00
Michael Scire
b73895df0a util: add bitflagset 2020-04-08 08:39:36 -07:00
Michael Scire
5062329979 erpt: add ids (and autogeneration tool) 2020-04-08 07:17:42 -07:00
Michael Scire
065485b971 os: refactor/rewrite entire namespace. 2020-04-08 02:21:35 -07:00
Michael Scire
6193283f03 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "da6eac98"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "da6eac98"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-04-06 17:45:00 -07:00
Michael Scire
eb48e7cc59 buildsystem: fix building 2020-04-06 17:44:14 -07:00
Michael Scire
d98490d339 fs: Implement AesXtsStorage 2020-04-06 05:44:33 -07:00
Michael Scire
b2e86f5a1b fs: correct error result in AesCtrStorage 2020-04-06 04:56:49 -07:00
Michael Scire
0e9974e7b3 fs: add AesCtrStorage 2020-04-06 03:58:52 -07:00
Michael Scire
496be5ecd4 fs: implement PooledBuffer 2020-04-06 03:15:38 -07:00
Michael Scire
50a91b1d6e fs: implement system heap 2020-04-06 03:15:33 -07:00
Michael Scire
f872be67eb git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "18396d1a"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "18396d1a"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-04-05 23:26:06 -07:00
Michael Scire
e04679f05a crypto: add aes (ecb, ctr, xts) 2020-04-05 23:25:28 -07:00
Michael Scire
8d1ada2a1b fssystem: add RomFsFileSystem 2020-04-04 02:37:21 -07:00
Adubbz
a50d6a2696 NCM client implementation (#858)
* ncm: Implement InstallTaskDataBase and FileInstallTaskData

* ncm: minor bugfixes

* ncm: Implemented MemoryInstallTaskData

* ncm: more std

* ncm: begin implementing install task base

* ncm: move protected funcs

* ncm: fix recursive include

* ncm: more install task progress

* ncm install task: implement IncrementProgress and update UpdateThroughputMeasurement

* ncm: more work

* ncm client: more progress

* ncm client: more progress

* ncm client: finish implementing GetContentMetaInfoList

* ncm client: more progress

* ncm client: finished InstallTaskBase

* ncm client: implement PackageInstallTaskBase

* ncm client: fixes

* ncm: improve accuracy

* ncm client: implement PackageInstallTask

* ncm client: implement PackageSystemUpdateTask

* ncm client: minor name tweaks

* ncm client: implement SubmissionPackageInstallTask

* ncm client: add missing this to SubmissionPackageInstallTask

* ncm client: add missing nullptr check to SubmissionPackageInstallTask destructor

* ncm client: SubmissionPackageInstallTask fixes

* ncm: fix forward declarations

* ncm client: added simplified funcs

* ncm: cleanup client code

* ncm: fix bug introduced by cleanup

* ncm: fix typo

* ncm: implement correct ReadVariationContentMetaInfoList behavior

* ncm: correct InstallContentMetaWriter ctor

* ncm: correct conversion of content meta header types

Co-authored-by: Michael Scire <SciresM@gmail.com>
2020-04-03 22:40:46 -07:00
Michael Scire
76d72fa946 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "62f5667b"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "62f5667b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-04-02 00:29:14 -07:00
Michael Scire
8b19fdfd51 sf: fix OutArray/InArray constructors to behave as expected 2020-04-02 00:28:39 -07:00
Michael Scire
612d846132 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "0f46474d"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "0f46474d"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-31 22:43:12 -07:00
Michael Scire
816ce605d3 fs: add an extension common name generator for sd card 2020-03-31 22:42:02 -07:00
SciresM
07c95662b1 nim: add DestroySystemUpdateTask/ListSystemUpdateTask (#863) 2020-03-31 12:50:55 -07:00
Michael Scire
2b930d21fd git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "de221b5d"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "de221b5d"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-30 21:41:49 -07:00
Michael Scire
0b52596087 fix CONCATENATE 2020-03-30 21:40:48 -07:00
Michael Scire
e9134d8044 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "63d5df84"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "63d5df84"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-30 20:41:45 -07:00
Michael Scire
33d6dfb6b3 updater: improve api 2020-03-30 20:39:56 -07:00
bunnei
6096fa0e45 KPageHeap: Fix a typo in initialization block alignment. (#862) 2020-03-30 19:27:02 -07:00
Michael Scire
058f265bd6 lmem: fix memory block header placement error 2020-03-30 00:56:57 -07:00
Michael Scire
bd4c608b08 ncm: use static memory pools for different allocations 2020-03-29 17:20:25 -07:00
Michael Scire
7fc1e86bf5 stratosphere: fix building with latest libnx 2020-03-29 15:24:40 -07:00
SciresM
87ec045a98 mem: implement most of StandardAllocator (#860)
This was tested using `https://github.com/node-dot-cpp/alloc-test` plus a few other by-hand tests.

It seems to work for the case we care about (sysmodules without thread cache-ing).

External users are advised to build with assertions on and contact SciresM if you find issues.

This is a lot of code to have gotten right in one go, and it was written mostly after midnight while sick, so there are probably un-noticed issues.
2020-03-29 14:43:16 -07:00
Michael Scire
7502e2174f git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "6f77a6bf"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "6f77a6bf"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-27 17:00:36 -07:00
Michael Scire
0545eb18c0 fs: add MountImageDirectory 2020-03-27 16:59:27 -07:00
Adubbz
0c161a4c1b fs: implement FileHandleStorage (#857)
* fs: implement FileHandleStorage

* fs: merge FileHandleStorage into file_storage TU

Co-authored-by: Michael Scire <SciresM@gmail.com>
2020-03-27 11:45:02 -07:00
Adubbz
3d518759da fssystem: Implement PartitionFileSystemCore (#856)
* fssystem: implement PartitionFileSystemMetaCore

* fssystem: PartitionFileSystemMetaCore cleanup

* fs: add IFile::DryWrite, update results

* fssystem: implement PartitionFileSystemCore

* fssystem: cleanup PartitionFileSystemCore

* fssystem: implement Sha256PartitionFileSystem

Co-authored-by: Michael Scire <SciresM@gmail.com>
2020-03-27 03:40:52 -07:00
Michael Scire
0af2758fde fs.mitm: use new namespace types for saves 2020-03-24 17:50:36 -07:00
Michael Scire
9bb5af9823 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "30f3e4c3"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "30f3e4c3"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-20 17:06:23 -07:00
Michael Scire
82eab9c8d0 Add Span<T>. 2020-03-20 17:04:01 -07:00
Michael Scire
3cca3801ca fs: fix bugs with external code filesystems 2020-03-20 11:47:19 -07:00
Michael Scire
03408f404a git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "07630f73"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "07630f73"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-18 20:06:10 -07:00
Michael Scire
92e7a3ca08 fs: add MountDeviceSaveData 2020-03-18 20:05:39 -07:00
Michael Scire
b27c7552d2 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "38fc51c6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "38fc51c6"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-18 16:20:29 -07:00
Michael Scire
426257d4ae ams: bump version to 0.10.5 in prep for release later tonight 2020-03-18 16:19:59 -07:00
Michael Scire
7d34d599bb git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "07684b2c"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "07684b2c"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-18 00:15:32 -07:00
Michael Scire
067fe2d10f stratosphere: fix building with latest libnx 2020-03-18 00:14:34 -07:00
Michael Scire
4759c2f92c svc: add ipc accessor boilerplate 2020-03-18 00:09:51 -07:00
Michael Scire
ca26d8ce27 kern: Implement SvcManageNamedPort 2020-03-18 00:09:51 -07:00
Michael Scire
6c52cc3e26 memset: use neon-less impl, reformat other asm 2020-03-18 00:09:50 -07:00
Michael Scire
e42d3a3abf libmesosphere: use ARM-software/optimized-routines for memcpy/memset/memcmp 2020-03-18 00:09:50 -07:00
Michael Scire
884844bc23 svc: revert codegen changes 2020-03-18 00:09:50 -07:00
Michael Scire
f556db8c89 svc: make autogen asm register-clobber aware 2020-03-18 00:09:50 -07:00
Michael Scire
96d15b28c6 kern: implement CallSecureMonitor, some of GetInfo/GetSystemInfo 2020-03-18 00:09:50 -07:00
Michael Scire
37f7afb426 ams.mitm: greatly reduce memory requirements to build romfs 2020-03-18 00:07:19 -07:00
Michael Scire
7dd4e76c1d os: add rngmanager 2020-03-16 13:08:20 -07:00
Michael Scire
daa0deb1bf Add architecture-specific guard for get tick 2020-03-16 01:05:30 -07:00
Michael Scire
43bd733f0a os: implement Tick api, make build with -Werror 2020-03-16 01:02:55 -07:00
Michael Scire
70367e3e7c crypto: add Sha256Context 2020-03-11 03:26:55 -07:00
Michael Scire
45f8343659 kern: tweak KHandleTable impl 2020-03-10 04:54:53 -07:00
Michael Scire
e8dfe04701 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "a4ce1172"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "a4ce1172"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-03-09 18:04:11 -07:00
Michael Scire
95d5375158 ams: bump version to 0.10.4 2020-03-09 18:03:11 -07:00
hexkyz
b735bc53c4 stratosphere-ldr: fix code mount name 2020-03-09 21:53:40 +00:00
hexkyz
b4856a2d07 exo/fusee/sept: fix uart pinmuxing (thanks @CTCaer and @TuxSH) 2020-03-09 19:38:56 +00:00
hexkyz
ed4491a24f fusee/sept: fix volatile usage and simplify logic in gpio code (thanks @TuxSH) 2020-03-09 19:33:39 +00:00
Michael Scire
93004be59e ams: finish stdio -> fs bindings for stratosphere 2020-03-09 03:58:02 -07:00
Michael Scire
237b513408 loader: refactor to use fs bindings 2020-03-09 03:10:12 -07:00
Michael Scire
4c5e980e07 ams: dump tls in fatal error context 2020-03-08 17:01:53 -07:00
Michael Scire
08d9de6907 ldr: optimize memory usage for tracking system programs 2020-03-08 16:54:32 -07:00
Michael Scire
6eee3f5fe7 stratosphere-except-ldr: use fs bindings (this temporarily breaks loader) 2020-03-08 16:33:49 -07:00
Michael Scire
4eb3109c93 fusee: update fss0 header 2020-03-08 11:50:38 -07:00
Michael Scire
f7fb689412 fatal: use fs bindings 2020-03-08 04:50:47 -07:00
Michael Scire
2181adb82b creport: minor reformatting/fixes 2020-03-08 03:08:39 -07:00
Michael Scire
40c6733de3 creport: use fs bindings 2020-03-08 01:45:12 -08:00
Michael Scire
c703be86fc stratosphere template: allow for per-module defines 2020-03-08 01:39:16 -08:00
Michael Scire
f3732c72dc fusee: embed opt-in NCM kip 2020-03-08 00:21:01 -08:00
Adubbz
c7026b9094 Implement the NCM sysmodule (closes #91)
* Implement NCM

* Modernize ncm_main

* Remove unnecessary smExit

* Give access to svcCallSecureMonitor

* Stack size bump

* Fix incorrect setup for NandUser's content storage entry

* Fix a potential data abort when flushing the placeholder accessor cache

* Fix HasFile and HasDirectory

* Use r+b, not w+b

* Misc fixes

* errno begone

* Fixed more stdio error handling

* More main fixes

* Various command improvements

* Make dispatch tables great again

* Fix logic inversion

* Fixed content path generation

* Bump heap size, fix CleanupAllPlaceHolder

* Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes

* Fixed placeholder/content deletion

* Fixed incorrect content manager destruction

* Prevent automatic placeholder creation on open

* Fixed List implementation. Also lots of debug logging.

* Removed debug code

* Added a scope guard for WritePlaceHolder

* Manually prevent placeholder/content appending

* Revert "Removed debug code"

This reverts commit d6ff261fcc.

* Always cache placeholder file. Switch to ftell for preventing appending

* Universally use EnsureEnabled

* Abstract away file writing logic

* Misc cleanup

* Refactor placeholder cacheing

* Remove debug code (again)

* Revert "Remove debug code (again)"

This reverts commit 168447d80e.

* Misc changes

* Fixed file modes

* Fixed ContentId/PlaceHolderId alignment

* Improved type safety

* Fixed reinitialization

* Fixed doubleup on path creation

* Remove debug code

* Fixed 1.0.0 booting

* Correct amount of add on content

* Correct main thread stack size

* lr: Introducing registered data

* Reorder stratosphere Makefile

* Move results to libstrat

* lr: Cleanup lr_redirection

* lr: lr_manager tweaks

* lr: Imrpoved path handling and adjust ResolveAddOnContentPath order

* lr: Organise types

* Add eof newlines

* lr: Eliminate unnecessary vars

* lr: Unnecessary vars 2 electric boogaloo

* lr: Various helpers

* lr: RegisteredLocationResolver helpers

* ncm: Move ncm_types to libstrat

* ncm: Misc cleanup

* Implement NCM

* Modernize ncm_main

* Remove unnecessary smExit

* Give access to svcCallSecureMonitor

* Stack size bump

* Fix incorrect setup for NandUser's content storage entry

* Fix a potential data abort when flushing the placeholder accessor cache

* Fix HasFile and HasDirectory

* Use r+b, not w+b

* Misc fixes

* errno begone

* Fixed more stdio error handling

* More main fixes

* Various command improvements

* Make dispatch tables great again

* Fix logic inversion

* Fixed content path generation

* Bump heap size, fix CleanupAllPlaceHolder

* Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes

* Fixed placeholder/content deletion

* Fixed incorrect content manager destruction

* Prevent automatic placeholder creation on open

* Fixed List implementation. Also lots of debug logging.

* Removed debug code

* Added a scope guard for WritePlaceHolder

* Manually prevent placeholder/content appending

* Revert "Removed debug code"

This reverts commit d6ff261fcc.

* Always cache placeholder file. Switch to ftell for preventing appending

* Universally use EnsureEnabled

* Abstract away file writing logic

* Misc cleanup

* Refactor placeholder cacheing

* Remove debug code (again)

* Revert "Remove debug code (again)"

This reverts commit 168447d80e.

* Misc changes

* Fixed file modes

* Fixed ContentId/PlaceHolderId alignment

* Improved type safety

* Fixed reinitialization

* Fixed doubleup on path creation

* Remove debug code

* Fixed 1.0.0 booting

* Correct amount of add on content

* Correct main thread stack size

* lr: Introducing registered data

* Reorder stratosphere Makefile

* Move results to libstrat

* lr: Cleanup lr_redirection

* lr: lr_manager tweaks

* lr: Imrpoved path handling and adjust ResolveAddOnContentPath order

* lr: Organise types

* Add eof newlines

* lr: Eliminate unnecessary vars

* lr: Unnecessary vars 2 electric boogaloo

* lr: Various helpers

* lr: RegisteredLocationResolver helpers

* ncm: Move ncm_types to libstrat

* ncm: Misc cleanup

* Updated AddOnContentLocationResolver and RegisteredLocationResolver to 9.0.0

* Finished updating lr to 9.0.0

* Updated NCM to 9.0.0

* Fix libstrat includes

* Fixed application launching

* title_id_2 -> owner_tid

* Updated to new-ipc

* Change to using pure virtuals

* Title Id -> Program Id

* Fixed compilation against master

* std::scoped_lock<> -> std::scoped_lock

* Adopted R_UNLESS and R_CONVERT

* Prefix namespace to Results

* Adopt std::numeric_limits

* Fixed incorrect error handling in ReadFile

* Adopted AMS_ABORT_UNLESS

* Adopt util::GenerateUuid()

* Syntax improvements

* ncm_types: Address review

* Address more review comments

* Updated copyrights

* Address more feedback

* More feedback addressed

* More changes

* Move dispatch tables out of interface files

* Addressed remaining comments

* lr: move into libstratosphere

* ncm: Fix logic inversion

* lr: Add comments

* lr: Remove whitespace

* ncm: Start addressing feedback

* ncm: Cleanup InitializeContentManager

* lr: support client-side usage

* lr_service -> lr_api

* ncm: Begin refactoring content manager

* ncm: More content manager improvements

* ncm: Content manager mount improvements

* ldr: use lr bindings

* lr bindings usage: minor fixes

* ncm/lr: Pointer placement

* ncm: placeholder accessor cleanup

* ncm: minor fixes

* ncm: refactor rights cache

* ncm: content meta database cleanup

* ncm: move content meta database impl out of interface file

* ncm: Use const ContentMetaKey &

* ncm: fix other non-const ContentMetaKey references

* ncm: content meta database cleanup

* ncm: content storage fixes for 2.0.0

* ncm: add missing end of file newlines

* ncm: implement ContentMetaReader

* ncm: client-side api

* ncm: trim trailing spaces

* ncm: FS_MAX_PATH-1 -> fs::EntryNameLengthMax

* ncm: Use PathString and Path

* fs: implement accessor wrappers for ncm

* fs: implement user fs wrappers

* fs: add MountSdCard

* ncm: move to content manager impl

* ncm: fix up main

* kvdb: use fs::

* fs: Add wrappers needed for ncm

* ncm: use fs bindings, other refactoring

* ncm: minor fixes

* fsa: fix ReadFile without size output

* fs: add substorage, rom path tool

* ncm: fix dangling fsdev usage

* fs: fix bug in Commit

* fs: fixed incorrect mode check

* fs: implement Mount(System)Data

* ncm: don't delete hos

* results: add R_SUCCEED_IF

* ams-except-ncm: use R_SUCCEED_IF

* ncm: added comments

* ncm: fix api definitions

* ncm: use R_SUCCEED_IF

* pm: think of the savings

* ncm: employ kernel strats

* ncm: Nintendo has 5 MiB of heap. Give ourselves 4 to be safe, pending analysis

* ncm: refactor IDs, split types header into many headers

* ams.mitm: use fs bindings instead of stdio

* fs: SystemData uses SystemDataId

* ncm: improve meta-db accuracy

* ncm: inline getlatestkey

* fs: improve UnsupportedOperation results

* fs: modernize mount utils

* ams: misc fixes for merge-errors

* fs: improve unsupportedoperation results

* git subrepo pull emummc

subrepo:
  subdir:   "emummc"
  merged:   "d12dd546"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "d12dd546"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"

* util: add boundedmap

* ncm: minor style fixes

* ncm: don't unmount if mounting fails

* lr: bug fixes

* ncm: implement ncm.for-initialize + ncm.for-safemode

* lr: ncm::ProgramId::Invalid -> ncm::InvalidProgramId

* ncm: fix open directory mode on 1.0.0

* ncm: fix fs use, implement more of < 4.0.0 for-initialize/safemode

* ncm: implement packagedcontent -> content for building metadb

* ncm: fix save data flag management

* ncm: address some review suggestions (thanks @leoetlino!)

* updater: use fs bindings

* fs: implement MountCode

* fs: prefer make_unique to operator new

* ncm: implement remaining ContentMetaDatabaseBuilder functionality

Co-authored-by: Michael Scire <SciresM@gmail.com>
2020-03-08 00:06:23 -08:00
760 changed files with 54896 additions and 4929 deletions

1
.gitignore vendored
View File

@@ -64,6 +64,7 @@ dkms.conf
# Distribution files
*.tgz
*.zip
*.bz2
# IDA binaries
*.id0

View File

@@ -18,3 +18,5 @@ enable_user_pmu_access = 0
[stratosphere]
; To force-enable nogc, add nogc = 1
; To force-disable nogc, add nogc = 0
; To opt in to using Atmosphere's NCM reimplementation, add enable_ncm = 1

View File

@@ -1,4 +1,38 @@
# Changelog
## 0.10.5
+ Changes were made to the way fs.mitm builds images when providing a layeredfs romfs.
+ Building romfs metadata previously had a memory cost of about ~4-5x the file table size.
+ This caused games that have particularly enormous file metadata tables (> 4 MB) to exhaust fs.mitm's 16 MB memory pool.
+ The code that creates romfs images was thus changed to be significantly more memory efficient, again.
+ Memory requirements have been lowered from ~4x file table size to ~2x file table size + 0.5 MB.
+ There is a slight speed penalty to this, but testing on Football Manager 2020 only took an extra ~1.5 seconds for the game to boot with many modded files.
+ This shouldn't be noticeable thanks to the async changes made in 0.10.2.
+ If you encounter a game that exhausts ams.mitm's memory (crashing it) when loading layeredfs mods, please contact SciresM.
+ Romfs building can be made even more memory efficient, but unless games show up with even more absurdly huge file tables it seems not worth the speed trade-off.
+ A bug was fixed that caused Atmosphere's fatal error context to not dump TLS for certain processes.
+ General system stability improvements to enhance the user's experience.
## 0.10.4
+ With major thanks to @Adubbz for his work, the NCM system module has now been re-implemented.
+ This was a major stepping stone towards the goal of having implementations everything in the Switch's package1/package2 firmware.
+ This also lays the groundwork for libstratosphere providing bindings for changing the installed version of the Switch's OS.
+ **Please Note**: The NCM implementation will initially be opt-in.
+ The Atmosphere team is confident in our NCM implementation (and we have tested it on every firmware version).
+ That said, this is our first system module that manages NAND savegames -- and caution is a habit.
+ We do not anticipate any issues that didn't come up in testing, so this is just our being particularly careful.
+ Users interested in opting in to using our implementation should set `stratosphere!ncm_enabled = 1` in BCT.ini.
+ In the unlikely event that any issues are encountered, please report them to @SciresM.
+ The NCM implementation will stop being opt-in in a future update, after thorough testing has been done in practice.
+ A bug was fixed in emummc that caused Nintendo path to be corrupted on 1.0.0.
+ This manifested as the emummc folder being created inside the virtual NAND instead of the SD card.
+ It's unlikely there are any negative consequences to this in practice.
+ If you want to be truly sure, you can re-clone sysmmc before updating a 1.0.0 emummc to latest firmware.
+ Stratosphere system modules now use new Nintendo-style FS bindings instead of stdio.
+ This saves a modest amount of memory due to leaner code, and greatly increases the accuracy of several components.
+ These bindings will make it easier for other system modules using libstratosphere to interact with the filesystem.
+ This also lays the groundwork for changes necessary to support per-emummc Atmosphere folders in a future update.
+ Atmosphere's fatal error context now dumps 0x100 of TLS.
+ This will make it much easier to fix bugs when an error report is dumped for whatever caused the crash.
+ General system stability improvements to enhance the user's experience.
## 0.10.3
+ Support was added for 9.2.0.
+ Support was added for redirecting manual html content for games.

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/m4xw/emuMMC
branch = develop
commit = bd81a674a946c30b566e1732a95c18f19b701558
parent = 6ee525201ccef107c61d81ba73c891e3eb5f0215
commit = d12dd5464422029a1e5601916517ec3f1c81d8d0
parent = 259a1a7513236a1de4d373bc6cb99032ede2c626
method = rebase
cmdver = 0.4.0
cmdver = 0.4.1

View File

@@ -1,21 +1,21 @@
# emuMMC
*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
**1.0.0 - 9.1.0**
## Features
* Arbitrary SDMMC backend selection
* Arbitrary SDMMC backend selection
**This allows loading eMMC from SD or even SD from eMMC**
* On the fly hooking / patching, fully self-infesting
* On the fly hooking / patching, fully self-infesting
**Only one payload required for all versions!**
* File-based SDMMC backend support (from SD)
* File-based SDMMC backend support (from SD)
**This allows loading eMMC images from hekate-backups (split or not)**
* SDMMC device based sector offset (*currently eMMC only*)
* SDMMC device based sector offset (*currently eMMC only*)
**Raw partition support for eMMC from SD with less performance overhead**
* Full support for `/Nintendo` folder redirection to a arbitrary path
* Full support for `/Nintendo` folder redirection to a arbitrary path
**No 8 char length restriction!**
* exosphere based context configuration
* exosphere based context configuration
**This includes full support for multiple emuMMC images**
## Compiling

View File

@@ -48,10 +48,8 @@
// Nintendo Paths
#define FS_OFFSET_100_NINTENDO_PATHS \
{ \
{.opcode_reg = 9, .adrp_offset = 0x00032C58, .add_rel_offset = 4}, \
{.opcode_reg = 8, .adrp_offset = 0x00032C60, .add_rel_offset = 4}, \
{.opcode_reg = 9, .adrp_offset = 0x00032F3C, .add_rel_offset = 4}, \
{.opcode_reg = 8, .adrp_offset = 0x00032F44, .add_rel_offset = 4}, \
{.opcode_reg = 8, .adrp_offset = 0x00032C58, .add_rel_offset = 8}, \
{.opcode_reg = 9, .adrp_offset = 0x00032F40, .add_rel_offset = 8}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}

View File

@@ -48,6 +48,9 @@ extern char __argdata__;
// TODO
static char nintendo_path[0x80] = "Nintendo";
// 1.0.0 requires special path handling because it has separate album and contents paths.
#define FS_100_ALBUM_PATH 0
#define FS_100_CONTENTS_PATH 1
static char nintendo_path_album_100[0x100] = "/Nintendo/Album";
static char nintendo_path_contents_100[0x100] = "/Nintendo/Contents";
@@ -275,23 +278,18 @@ void setup_nintendo_paths(void)
// 1.0.0 needs special handling because it uses two paths.
// Do album path
{
int path_len = snprintf(nintendo_path_album_100, sizeof(nintendo_path_album_100), "/%s/Album", nintendo_path);
snprintf(nintendo_path_album_100, sizeof(nintendo_path_album_100), "/%s/Album", nintendo_path);
intptr_t nintendo_album_path_location = (intptr_t)&nintendo_path_album_100;
intptr_t album_path_location = nintendo_album_path_location + path_len - 6; // "/Album"
uintptr_t fs_n_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[0].adrp_offset);
uintptr_t fs_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[1].adrp_offset);
write_adrp_add(fs_offsets->nintendo_paths[0].opcode_reg, fs_n_adrp_opcode_location, fs_offsets->nintendo_paths[0].add_rel_offset, nintendo_album_path_location);
write_adrp_add(fs_offsets->nintendo_paths[1].opcode_reg, fs_adrp_opcode_location, fs_offsets->nintendo_paths[1].add_rel_offset, album_path_location);
uintptr_t fs_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[FS_100_ALBUM_PATH].adrp_offset);
write_adrp_add(fs_offsets->nintendo_paths[FS_100_ALBUM_PATH].opcode_reg, fs_adrp_opcode_location, fs_offsets->nintendo_paths[FS_100_ALBUM_PATH].add_rel_offset, nintendo_album_path_location);
}
// Do contents path
{
int path_len = snprintf(nintendo_path_contents_100, sizeof(nintendo_path_contents_100), "/%s/Contents", nintendo_path);
snprintf(nintendo_path_contents_100, sizeof(nintendo_path_contents_100), "/%s/Contents", nintendo_path);
intptr_t nintendo_contents_path_location = (intptr_t)&nintendo_path_contents_100;
intptr_t contents_path_location = nintendo_contents_path_location + path_len - 9; // "/Contents"
uintptr_t fs_n_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[2].adrp_offset);
uintptr_t fs_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[3].adrp_offset);
write_adrp_add(fs_offsets->nintendo_paths[2].opcode_reg, fs_n_adrp_opcode_location, fs_offsets->nintendo_paths[2].add_rel_offset, nintendo_contents_path_location);
write_adrp_add(fs_offsets->nintendo_paths[3].opcode_reg, fs_adrp_opcode_location, fs_offsets->nintendo_paths[3].add_rel_offset, contents_path_location);
uintptr_t fs_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[FS_100_CONTENTS_PATH].adrp_offset);
write_adrp_add(fs_offsets->nintendo_paths[FS_100_CONTENTS_PATH].opcode_reg, fs_adrp_opcode_location, fs_offsets->nintendo_paths[FS_100_CONTENTS_PATH].add_rel_offset, nintendo_contents_path_location);
}
}
}

View File

@@ -21,12 +21,12 @@
static inline void uart_wait_cycles(uint32_t baud, uint32_t num)
{
wait((num * 1000000 + 16 * baud - 1) / (16 * baud));
udelay((num * 1000000 + 16 * baud - 1) / (16 * baud));
}
static inline void uart_wait_syms(uint32_t baud, uint32_t num)
{
wait((num * 1000000 + baud - 1) / baud);
udelay((num * 1000000 + baud - 1) / baud);
}
void uart_config(UartDevice dev) {
@@ -34,28 +34,28 @@ void uart_config(UartDevice dev) {
switch (dev) {
case UART_A:
pinmux->uart1_tx = 0;
pinmux->uart1_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart1_rts = 0;
pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart1_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart1_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_UP | PINMUX_SELECT_FUNCTION0);
pinmux->uart1_rts = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
break;
case UART_B:
pinmux->uart2_tx = 0;
pinmux->uart2_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart2_rts = 0;
pinmux->uart2_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart2_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart2_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart2_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart2_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
break;
case UART_C:
pinmux->uart3_tx = 0;
pinmux->uart3_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart3_rts = 0;
pinmux->uart3_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart3_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart3_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart3_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart3_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
break;
case UART_D:
pinmux->uart4_tx = 0;
pinmux->uart4_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart4_rts = 0;
pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart4_tx = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart4_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart4_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
break;
case UART_E:
/* Unused. */

View File

@@ -21,66 +21,58 @@
#include "gpio.h"
#include "utils.h"
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) {
/* Set GPIO's value. */
static void gpio_register_set(uint32_t pin, bool do_set, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
uint32_t bank_number = (pin >> GPIO_BANK_SHIFT);
return &gpio->bank[bank_number];
}
static volatile uint32_t gpio_get_port(uint32_t pin) {
return ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
}
static volatile uint32_t gpio_get_mask(uint32_t pin) {
uint32_t pin_number = (pin & GPIO_PIN_MASK);
return (1 << pin_number);
}
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) {
/* Retrieve the register set that corresponds to the given pin and offset. */
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
uint32_t *cluster = (uint32_t *)cluster_addr;
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = gpio_get_port(pin);
uint32_t mask = gpio_get_mask(pin);
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Set or clear the bit, as appropriate. */
if (should_be_set)
if (do_set)
cluster[port] |= mask;
else
cluster[port] &= ~mask;
/* Dummy read. */
(void)cluster[port];
cluster[port];
}
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) {
/* Get GPIO's value. */
static bool gpio_register_get(uint32_t pin, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
/* Retrieve the register set that corresponds to the given pin and offset. */
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
uint32_t *cluster = (uint32_t *)cluster_addr;
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = gpio_get_port(pin);
uint32_t mask = gpio_get_mask(pin);
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Convert the given value to a boolean. */
return !!(cluster[port] & mask);
}
/* Configure GPIO's mode. */
void gpio_configure_mode(uint32_t pin, uint32_t mode) {
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
gpio_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
}
/* Configure GPIO's direction. */
void gpio_configure_direction(uint32_t pin, uint32_t dir) {
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
gpio_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
}
/* Write to GPIO. */
void gpio_write(uint32_t pin, uint32_t value) {
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
gpio_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
}
/* Read from GPIO. */
uint32_t gpio_read(uint32_t pin) {
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
return gpio_register_get(pin, offsetof(tegra_gpio_bank_t, in));
}

View File

@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "panic.h"
#include "di.h"
@@ -51,8 +51,10 @@ static const char *get_error_desc_str(uint32_t error_desc) {
static void _check_and_display_atmosphere_fatal_error(void) {
/* Check for valid magic. */
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0) {
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_1 &&
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0)
{
return;
}
@@ -69,10 +71,10 @@ static void _check_and_display_atmosphere_fatal_error(void) {
/* Turn on the backlight after initializing the lfb */
/* to avoid flickering. */
display_backlight(true);
/* Override the global logging level. */
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
/* Copy fatal error context to the stack. */
atmosphere_fatal_error_ctx ctx = *(ATMOSPHERE_FATAL_ERROR_CONTEXT);
@@ -103,7 +105,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
void check_and_display_panic(void) {
/* Handle a panic sent via a stratosphere module. */
_check_and_display_atmosphere_fatal_error();
/* We also handle our own panics. */
bool has_panic = ((APBDEV_PMC_RST_STATUS_0 != 0) || (g_panic_code != 0));
uint32_t code = (g_panic_code == 0) ? APBDEV_PMC_SCRATCH200_0 : g_panic_code;
@@ -152,10 +154,10 @@ void check_and_display_panic(void) {
/* Initialize the display. */
display_init();
/* Fill the screen. */
display_color_screen(color);
/* Wait for button and reboot. */
wait_for_button_and_reboot();
} else {

View File

@@ -13,7 +13,7 @@
* 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 FUSEE_PANIC_H
#define FUSEE_PANIC_H
@@ -30,6 +30,7 @@
#define AMS_FATAL_ERROR_MAX_STACKTRACE 0x20
#define AMS_FATAL_ERROR_MAX_STACKDUMP 0x100
#define AMS_FATAL_ERROR_TLS_SIZE 0x100
/* Atmosphere reboot-to-fatal-error. */
typedef struct {
@@ -57,10 +58,13 @@ typedef struct {
uint64_t stack_dump_size;
uint64_t stack_trace[AMS_FATAL_ERROR_MAX_STACKTRACE];
uint8_t stack_dump[AMS_FATAL_ERROR_MAX_STACKDUMP];
uint8_t tls[AMS_FATAL_ERROR_TLS_SIZE];
} atmosphere_fatal_error_ctx;
/* "AFE2" */
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x32454641
/* "AFE1" */
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x31454641
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_1 0x31454641
/* "AFE0" */
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0 0x30454641

View File

@@ -34,28 +34,28 @@ void uart_config(UartDevice dev) {
switch (dev) {
case UART_A:
pinmux->uart1_tx = 0;
pinmux->uart1_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart1_rts = 0;
pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart1_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart1_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_UP | PINMUX_SELECT_FUNCTION0);
pinmux->uart1_rts = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
break;
case UART_B:
pinmux->uart2_tx = 0;
pinmux->uart2_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart2_rts = 0;
pinmux->uart2_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart2_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart2_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart2_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart2_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
break;
case UART_C:
pinmux->uart3_tx = 0;
pinmux->uart3_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart3_rts = 0;
pinmux->uart3_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart3_tx = (0 | 0 | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart3_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
pinmux->uart3_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart3_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_NONE | PINMUX_SELECT_FUNCTION0);
break;
case UART_D:
pinmux->uart4_tx = 0;
pinmux->uart4_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
pinmux->uart4_rts = 0;
pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
pinmux->uart4_tx = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart4_rx = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart4_rts = (0 | 0 | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_TRISTATE | PINMUX_PULL_DOWN | PINMUX_SELECT_FUNCTION0);
break;
case UART_E:
/* Unused. */

View File

@@ -84,7 +84,7 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/spl $(AMS)/stratosphere/ams_mitm
export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/ncm $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/spl $(AMS)/stratosphere/ams_mitm
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \
@@ -96,7 +96,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
KIPFILES := loader.kip ncm.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp \
sept-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \
@@ -221,12 +221,12 @@ sept_secondary_01.enc.o sept_secondary_01_enc.h: sept-secondary_01.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
sept_secondary_dev_00.enc.o sept_secondary_dev_00_enc.h: sept-secondary_dev_00.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
sept_secondary_dev_01.enc.o sept_secondary_dev_01_enc.h: sept-secondary_dev_01.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)

View File

@@ -230,6 +230,8 @@ SECTIONS
PROVIDE(__loader_kip_size__ = loader_kip_end - loader_kip);
PROVIDE(__lp0fw_bin_start__ = lp0fw_bin - __start__);
PROVIDE(__lp0fw_bin_size__ = lp0fw_bin_end - lp0fw_bin);
PROVIDE(__ncm_kip_start__ = ncm_kip - __start__);
PROVIDE(__ncm_kip_size__ = ncm_kip_end - ncm_kip);
PROVIDE(__pm_kip_start__ = pm_kip - __start__);
PROVIDE(__pm_kip_size__ = pm_kip_end - pm_kip);
PROVIDE(__rebootstub_bin_start__ = rebootstub_bin - __start__);

View File

@@ -21,66 +21,58 @@
#include "gpio.h"
#include "utils.h"
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) {
/* Set GPIO's value. */
static void gpio_register_set(uint32_t pin, bool do_set, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
uint32_t bank_number = (pin >> GPIO_BANK_SHIFT);
return &gpio->bank[bank_number];
}
static volatile uint32_t gpio_get_port(uint32_t pin) {
return ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
}
static volatile uint32_t gpio_get_mask(uint32_t pin) {
uint32_t pin_number = (pin & GPIO_PIN_MASK);
return (1 << pin_number);
}
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) {
/* Retrieve the register set that corresponds to the given pin and offset. */
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
uint32_t *cluster = (uint32_t *)cluster_addr;
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = gpio_get_port(pin);
uint32_t mask = gpio_get_mask(pin);
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Set or clear the bit, as appropriate. */
if (should_be_set)
if (do_set)
cluster[port] |= mask;
else
cluster[port] &= ~mask;
/* Dummy read. */
(void)cluster[port];
cluster[port];
}
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) {
/* Get GPIO's value. */
static bool gpio_register_get(uint32_t pin, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
/* Retrieve the register set that corresponds to the given pin and offset. */
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
uint32_t *cluster = (uint32_t *)cluster_addr;
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = gpio_get_port(pin);
uint32_t mask = gpio_get_mask(pin);
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Convert the given value to a boolean. */
return !!(cluster[port] & mask);
}
/* Configure GPIO's mode. */
void gpio_configure_mode(uint32_t pin, uint32_t mode) {
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
gpio_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
}
/* Configure GPIO's direction. */
void gpio_configure_direction(uint32_t pin, uint32_t dir) {
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
gpio_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
}
/* Write to GPIO. */
void gpio_write(uint32_t pin, uint32_t value) {
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
gpio_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
}
/* Read from GPIO. */
uint32_t gpio_read(uint32_t pin) {
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
return gpio_register_get(pin, offsetof(tegra_gpio_bank_t, in));
}

View File

@@ -184,6 +184,12 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
strat_cfg->has_nogc_config = true;
sscanf(value, "%d", &tmp);
strat_cfg->enable_nogc = tmp != 0;
} else if (strcmp(name, STRATOSPHERE_ENABLE_NCM_KEY) == 0) {
sscanf(value, "%d", &tmp);
strat_cfg->ncm_enabled = tmp != 0;
if (strat_cfg->ncm_enabled) {
stratosphere_enable_ncm();
}
} else {
return 0;
}

View File

@@ -97,11 +97,18 @@ _metadata:
#define CONTENT_TYPE_KLD 9
#define CONTENT_TYPE_KRN 10
#define CONTENT_FLAG_NONE (0 << 0)
#define CONTENT_FLAG0_EXPERIMENTAL (1 << 0)
_content_headers:
/* ams_mitm content header */
.word __ams_mitm_kip_start__
.word __ams_mitm_kip_size__
.word CONTENT_TYPE_KIP
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "ams_mitm"
.align 5
@@ -109,7 +116,10 @@ _content_headers:
/* boot content header */
.word __boot_kip_start__
.word __boot_kip_size__
.word CONTENT_TYPE_KIP
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "boot"
.align 5
@@ -117,7 +127,10 @@ _content_headers:
/* exosphere content header */
.word __exosphere_bin_start__
.word __exosphere_bin_size__
.word CONTENT_TYPE_EXO
.byte CONTENT_TYPE_EXO
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "exosphere"
.align 5
@@ -125,7 +138,10 @@ _content_headers:
/* fusee_primary content header */
.word __fusee_primary_bin_start__
.word __fusee_primary_bin_size__
.word CONTENT_TYPE_FSP
.byte CONTENT_TYPE_FSP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "fusee_primary"
.align 5
@@ -133,15 +149,21 @@ _content_headers:
/* loader content header */
.word __loader_kip_start__
.word __loader_kip_size__
.word CONTENT_TYPE_KIP
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "loader"
.asciz "Loader"
.align 5
/* lp0fw content header */
.word __lp0fw_bin_start__
.word __lp0fw_bin_size__
.word CONTENT_TYPE_WBT
.byte CONTENT_TYPE_WBT
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "lp0fw"
.align 5
@@ -149,15 +171,21 @@ _content_headers:
/* pm content header */
.word __pm_kip_start__
.word __pm_kip_size__
.word CONTENT_TYPE_KIP
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "pm"
.asciz "ProcessManager"
.align 5
/* rebootstub content header */
.word __rebootstub_bin_start__
.word __rebootstub_bin_size__
.word CONTENT_TYPE_RBT
.byte CONTENT_TYPE_RBT
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "rebootstub"
.align 5
@@ -165,7 +193,10 @@ _content_headers:
/* sept_primary content header */
.word __sept_primary_bin_start__
.word __sept_primary_bin_size__
.word CONTENT_TYPE_SP1
.byte CONTENT_TYPE_SP1
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "sept_primary"
.align 5
@@ -173,7 +204,10 @@ _content_headers:
/* sept_secondary 00 content header */
.word __sept_secondary_00_enc_start__
.word __sept_secondary_00_enc_size__
.word CONTENT_TYPE_SP2
.byte CONTENT_TYPE_SP2
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "septsecondary00"
.align 5
@@ -181,7 +215,10 @@ _content_headers:
/* sept_secondary 01 content header */
.word __sept_secondary_01_enc_start__
.word __sept_secondary_01_enc_size__
.word CONTENT_TYPE_SP2
.byte CONTENT_TYPE_SP2
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "septsecondary01"
.align 5
@@ -189,7 +226,10 @@ _content_headers:
/* sm content header */
.word __sm_kip_start__
.word __sm_kip_size__
.word CONTENT_TYPE_KIP
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "sm"
.align 5
@@ -197,15 +237,32 @@ _content_headers:
/* spl content header */
.word __spl_kip_start__
.word __spl_kip_size__
.word CONTENT_TYPE_KIP
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "spl"
.align 5
/* ncm content header */
.word __ncm_kip_start__
.word __ncm_kip_size__
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG0_EXPERIMENTAL
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "NCM"
.align 5
/* emummc content header */
.word __emummc_kip_start__
.word __emummc_kip_size__
.word CONTENT_TYPE_EMC
.byte CONTENT_TYPE_EMC
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "emummc"
.align 5
@@ -213,7 +270,10 @@ _content_headers:
/* kernel_ldr content header */
.word __kernel_ldr_bin_start__
.word __kernel_ldr_bin_size__
.word CONTENT_TYPE_KLD
.byte CONTENT_TYPE_KLD
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "kernel_ldr"
.align 5
@@ -221,7 +281,10 @@ _content_headers:
/* splash_screen content header */
.word __splash_screen_bmp_start__
.word __splash_screen_bmp_size__
.word CONTENT_TYPE_BMP
.byte CONTENT_TYPE_BMP
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "splash_screen"
.align 5

View File

@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -30,6 +30,7 @@
#define u8 uint8_t
#define u32 uint32_t
#include "loader_kip.h"
#include "ncm_kip.h"
#include "pm_kip.h"
#include "sm_kip.h"
#include "ams_mitm_kip.h"
@@ -47,9 +48,10 @@ static bool g_stratosphere_pm_enabled = true;
static bool g_stratosphere_ams_mitm_enabled = true;
static bool g_stratosphere_spl_enabled = true;
static bool g_stratosphere_boot_enabled = true;
static bool g_stratosphere_ncm_enabled = false;
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ams_mitm_kip[];
extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, spl_kip_size, boot_kip_size, ams_mitm_kip_size;
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, spl_kip_size, boot_kip_size, ncm_kip_size, ams_mitm_kip_size;
static emummc_fs_ver_t g_fs_ver = FS_VER_1_0_0;
@@ -57,6 +59,19 @@ emummc_fs_ver_t stratosphere_get_fs_version(void) {
return g_fs_ver;
}
void stratosphere_enable_ncm(void) {
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
/* and does not think it likely there is any possibility of undesirable behavior */
/* when using the NCM reimplementation. However, because NCM manages critical save games */
/* the implementation will default to off for some time, until the code has been thoroughly */
/* tested in practice. */
/* PLEASE NOTE: The default behavior will be NCM on in a future atmosphere release, */
/* and this opt-in functionality will be removed at that time. */
g_stratosphere_ncm_enabled = true;
}
/* GCC doesn't consider the size as const... we have to write it ourselves. */
ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
@@ -68,38 +83,43 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
}
size_t size = sizeof(ini1_header_t);
/* Calculate our processes' sizes. */
if (g_stratosphere_loader_enabled) {
size += loader_kip_size;
num_processes++;
}
if (g_stratosphere_pm_enabled) {
size += pm_kip_size;
num_processes++;
}
if (g_stratosphere_sm_enabled) {
size += sm_kip_size;
num_processes++;
}
if (g_stratosphere_spl_enabled) {
size += spl_kip_size;
num_processes++;
}
if (g_stratosphere_ams_mitm_enabled) {
size += ams_mitm_kip_size;
num_processes++;
}
if (g_stratosphere_ncm_enabled) {
size += ncm_kip_size;
num_processes++;
}
if (g_stratosphere_boot_enabled) {
size += boot_kip_size;
num_processes++;
}
g_stratosphere_ini1 = (ini1_header_t *)malloc(size);
if (g_stratosphere_ini1 == NULL) {
@@ -134,6 +154,11 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
data += spl_kip_size;
}
if (g_stratosphere_ncm_enabled) {
memcpy(data, ncm_kip, ncm_kip_size);
data += ncm_kip_size;
}
if (g_stratosphere_ams_mitm_enabled) {
memcpy(data, ams_mitm_kip, ams_mitm_kip_size);
data += ams_mitm_kip_size;
@@ -143,7 +168,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
memcpy(data, boot_kip, boot_kip_size);
data += boot_kip_size;
}
return g_stratosphere_ini1;
}
@@ -160,26 +185,26 @@ void stratosphere_free_ini1(void) {
static void try_add_sd_kip(ini1_header_t *ini1, const char *kip_path) {
size_t file_size = get_file_size(kip_path);
if (ini1->size + file_size > PACKAGE2_SIZE_MAX) {
fatal_error("Failed to load %s: INI1 would be too large!\n", kip_path);
}
kip1_header_t kip_header;
if (read_from_file(&kip_header, sizeof(kip_header), kip_path) != sizeof(kip_header) || kip_header.magic != MAGIC_KIP1) {
return;
}
size_t kip_size = kip1_get_size_from_header(&kip_header);
if (kip_size > file_size) {
fatal_error("Failed to load %s: KIP size is corrupt!\n", kip_path);
}
if (read_from_file(ini1->kip_data + ini1->size - sizeof(ini1_header_t), kip_size, kip_path) != kip_size) {
/* TODO: is this error fatal? */
return;
}
ini1->size += kip_size;
ini1->num_processes++;
}
@@ -189,24 +214,24 @@ static kip1_header_t *inject_emummc_kip(kip1_header_t *fs_kip, kip1_header_t *em
size_t fs_kip_size, emummc_kip_size;
fs_kip = kip1_uncompress(fs_kip, &fs_kip_size);
emummc_kip = kip1_uncompress(emummc_kip, &emummc_kip_size);
/* Allocate kip. */
kip1_header_t *injected_kip = calloc(1, fs_kip_size + emummc_kip_size);
if (injected_kip == NULL) {
fatal_error("Failed to allocate memory for emummc kip injection!");
}
memcpy(injected_kip, fs_kip, sizeof(*fs_kip));
const size_t fs_contents_size = kip1_get_size_from_header(fs_kip) - sizeof(kip1_header_t);
const size_t emummc_data_size = emummc_kip->section_headers[3].out_offset + emummc_kip->section_headers[3].out_size;
if (emummc_data_size & 0xFFF) {
fatal_error("Invalid emummc kip!");
}
/* Copy over capabilities. */
memcpy(injected_kip->capabilities, emummc_kip->capabilities, sizeof(emummc_kip->capabilities));
/* Add extra cap for 1.0.0 */
if (stratosphere_get_fs_version() == FS_VER_1_0_0) {
for (size_t i = 0; i < 0x20; i++) {
@@ -217,14 +242,14 @@ static kip1_header_t *inject_emummc_kip(kip1_header_t *fs_kip, kip1_header_t *em
}
}
}
/* Update sections. */
injected_kip->section_headers[0].out_size += emummc_data_size;
injected_kip->section_headers[0].compressed_size += emummc_data_size;
for (size_t i = 1; i < 4; i++) {
injected_kip->section_headers[i].out_offset += emummc_data_size;
}
/* Copy data. */
{
size_t ofs = 0;
@@ -234,22 +259,22 @@ static kip1_header_t *inject_emummc_kip(kip1_header_t *fs_kip, kip1_header_t *em
}
}
memcpy(injected_kip->data + emummc_data_size, fs_kip->data, fs_contents_size);
return injected_kip;
}
ini1_header_t *stratosphere_get_sd_files_ini1(void) {
ini1_header_t *stratosphere_get_sd_files_ini1(void) {
if (g_sd_files_ini1 != NULL) {
return g_sd_files_ini1;
}
/* Allocate space. */
g_sd_files_ini1 = (ini1_header_t *)malloc(PACKAGE2_SIZE_MAX);
g_sd_files_ini1->magic = MAGIC_INI1;
g_sd_files_ini1->size = sizeof(ini1_header_t);
g_sd_files_ini1->num_processes = 0;
g_sd_files_ini1->_0xC = 0;
/* Load all kips from /atmosphere/kips/<*>.kip or /atmosphere/kips/<*>/<*>.kip. */
DIR *kips_dir = opendir("atmosphere/kips");
struct dirent *ent;
@@ -258,15 +283,15 @@ ini1_header_t *stratosphere_get_sd_files_ini1(void) {
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
continue;
}
char kip_path[0x301] = {0};
snprintf(kip_path, 0x300, "atmosphere/kips/%s", ent->d_name);
struct stat kip_stat;
if (stat(kip_path, &kip_stat) == -1) {
continue;
}
if ((kip_stat.st_mode & S_IFMT) == S_IFREG) {
/* If file, add to ini1. */
try_add_sd_kip(g_sd_files_ini1, kip_path);
@@ -279,15 +304,15 @@ ini1_header_t *stratosphere_get_sd_files_ini1(void) {
if (strcmp(sub_ent->d_name, ".") == 0 || strcmp(sub_ent->d_name, "..") == 0) {
continue;
}
/* Reuse kip path variable. */
memset(kip_path, 0, sizeof(kip_path));
snprintf(kip_path, 0x300, "atmosphere/kips/%s/%s", ent->d_name, sub_ent->d_name);
if (stat(kip_path, &kip_stat) == -1) {
continue;
}
if ((kip_stat.st_mode & S_IFMT) == S_IFREG) {
/* If file, add to ini1. */
try_add_sd_kip(g_sd_files_ini1, kip_path);
@@ -299,7 +324,7 @@ ini1_header_t *stratosphere_get_sd_files_ini1(void) {
}
closedir(kips_dir);
}
return g_sd_files_ini1;
}
@@ -344,7 +369,7 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis, vo
}
offset += kip1_get_size_from_header(current_kip);
bool already_loaded = false;
for (uint32_t j = 0; j < merged->num_processes; j++) {
if (process_list[j] == current_kip->title_id) {
@@ -355,20 +380,20 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis, vo
if (already_loaded) {
continue;
}
print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loading KIP %08x%08x...\n", (uint32_t)(current_kip->title_id >> 32), (uint32_t)current_kip->title_id);
size_t current_kip_size = kip1_get_size_from_header(current_kip);
if (current_kip_size > remaining_size) {
fatal_error("Not enough space for all the KIP1s!\n");
}
kip1_header_t *patched_kip = apply_kip_ips_patches(current_kip, current_kip_size, &g_fs_ver);
if (current_kip->title_id == FS_TITLE_ID && emummc != NULL) {
patched_kip = inject_emummc_kip(patched_kip != NULL ? patched_kip : current_kip, (kip1_header_t *)emummc);
}
if (patched_kip != NULL) {
size_t patched_kip_size = kip1_get_size_from_header(patched_kip);
if (patched_kip_size > remaining_size) {
@@ -377,9 +402,9 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis, vo
memcpy(current_dst_kip, patched_kip, patched_kip_size);
remaining_size -= patched_kip_size;
current_dst_kip += patched_kip_size;
free(patched_kip);
} else {
} else {
memcpy(current_dst_kip, current_kip, current_kip_size);
remaining_size -= current_kip_size;
current_dst_kip += current_kip_size;

View File

@@ -13,7 +13,7 @@
* 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 FUSEE_STRATOSPHERE_H
#define FUSEE_STRATOSPHERE_H
@@ -30,6 +30,8 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware);
ini1_header_t *stratosphere_get_sd_files_ini1(void);
void stratosphere_free_ini1(void);
void stratosphere_enable_ncm(void);
emummc_fs_ver_t stratosphere_get_fs_version(void);
ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_inis, void *emummc, size_t emummc_size);
@@ -37,8 +39,10 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_in
typedef struct {
bool has_nogc_config;
bool enable_nogc;
bool ncm_enabled;
} stratosphere_cfg_t;
#define STRATOSPHERE_NOGC_KEY "nogc"
#define STRATOSPHERE_ENABLE_NCM_KEY "enable_ncm"
#endif

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = 83aa6133ee2eb43287f8fc373d309a0c99337429
parent = fd34e2342a66b2aa3062ea7cecaf9728f12ef21a
commit = da6eac986d7f67ca3dcc3a8df0c191ffbea4686f
parent = eb48e7cc5943bd594b3166cb888d3dadb0474107
method = merge
cmdver = 0.4.1

View File

@@ -5,7 +5,7 @@ endif
include $(DEVKITPRO)/devkitA64/base_rules
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM64
export ATMOSPHERE_SETTINGS += -march=armv8-a -mtp=soft
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mtp=soft
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@@ -15,11 +15,11 @@ include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
export DEFINES = $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
export SETTINGS = $(ATMOSPHERE_SETTINGS) -O2
export CFLAGS = $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export CXXFLAGS = $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
export ASFLAGS = $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,__cxa_throw \
@@ -36,17 +36,17 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
export LDFLAGS := -specs=$(DEVKITPRO)/libnx/switch.specs $(SETTINGS) $(CXXWRAPS) -Wl,-Map,$(notdir $*.map)
export LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs $(SETTINGS) $(CXXWRAPS) -Wl,-Map,$(notdir $*.map)
export LIBS := -lstratosphere -lnx
export LIBS = -lstratosphere -lnx
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
export LIBDIRS := $(PORTLIBS) $(LIBNX) $(ATMOSPHERE_LIBRARIES_DIR)/libvapours $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere
export LIBDIRS = $(PORTLIBS) $(LIBNX) $(ATMOSPHERE_LIBRARIES_DIR)/libvapours $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere
#---------------------------------------------------------------------------------
# stratosphere sysmodules may (but usually do not) have an exefs source dir
#---------------------------------------------------------------------------------
export EXEFS_SRC := exefs_src
export EXEFS_SRC = exefs_src

View File

@@ -6,7 +6,8 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
#PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
PRECOMPILED_HEADERS :=
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Werror -fno-non-call-exceptions

View File

@@ -84,6 +84,10 @@ namespace ams::kern::arch::arm64 {
return this->page_table.UnmapPages(addr, num_pages, state);
}
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) {
return this->page_table.MakeAndOpenPageGroup(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
}
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
return this->page_table.GetPhysicalAddress(out, address);
}
@@ -96,12 +100,23 @@ namespace ams::kern::arch::arm64 {
KProcessAddress GetAliasRegionStart() const { return this->page_table.GetAliasRegionStart(); }
KProcessAddress GetStackRegionStart() const { return this->page_table.GetStackRegionStart(); }
KProcessAddress GetKernelMapRegionStart() const { return this->page_table.GetKernelMapRegionStart(); }
KProcessAddress GetAliasCodeRegionStart() const { return this->page_table.GetAliasCodeRegionStart(); }
size_t GetAddressSpaceSize() const { return this->page_table.GetAddressSpaceSize(); }
size_t GetHeapRegionSize() const { return this->page_table.GetHeapRegionSize(); }
size_t GetAliasRegionSize() const { return this->page_table.GetAliasRegionSize(); }
size_t GetStackRegionSize() const { return this->page_table.GetStackRegionSize(); }
size_t GetKernelMapRegionSize() const { return this->page_table.GetKernelMapRegionSize(); }
size_t GetAliasCodeRegionSize() const { return this->page_table.GetAliasCodeRegionSize(); }
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress address) const {
/* TODO: Better way to convert address type? */
return this->page_table.GetHeapPhysicalAddress(address);
}
KBlockInfoManager *GetBlockInfoManager() {
return this->page_table.GetBlockInfoManager();
}
};
}

View File

@@ -63,6 +63,9 @@ namespace ams::kern::board::nintendo::nx {
/* Power management. */
static void SleepSystem();
static NORETURN void StopSystem();
/* User access. */
static void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
};
}

View File

@@ -222,6 +222,8 @@ namespace ams::kern {
KScopedAutoObject(o).Swap(*this);
}
constexpr ALWAYS_INLINE T *GetPointerUnsafe() { return this->obj; }
constexpr ALWAYS_INLINE bool IsNull() const { return this->obj == nullptr; }
constexpr ALWAYS_INLINE bool IsNotNull() const { return this->obj != nullptr; }
};

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2018-2020 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_synchronization_object.hpp>
namespace ams::kern {
class KPort;
class KClientPort final : public KSynchronizationObject {
MESOSPHERE_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject);
private:
std::atomic<s32> num_sessions;
std::atomic<s32> peak_sessions;
s32 max_sessions;
KPort *parent;
public:
constexpr KClientPort() : num_sessions(), peak_sessions(), max_sessions(), parent() { /* ... */ }
virtual ~KClientPort() { /* ... */ }
void Initialize(KPort *parent, s32 max_sessions);
constexpr const KPort *GetParent() const { return this->parent; }
bool IsLight() const;
/* Overridden virtual functions. */
virtual void Destroy() override;
virtual bool IsSignaled() const override;
/* TODO: More of KClientPort. */
};
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018-2020 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_synchronization_object.hpp>
namespace ams::kern {
class KSession;
class KClientSession final : public KAutoObjectWithSlabHeapAndContainer<KClientSession, KAutoObjectWithList> {
MESOSPHERE_AUTOOBJECT_TRAITS(KClientSession, KAutoObject);
private:
KSession *parent;
public:
constexpr KClientSession() : parent() { /* ... */ }
virtual ~KClientSession() { /* ... */ }
void Initialize(KSession *parent) {
/* Set member variables. */
this->parent = parent;
}
static void PostDestroy(uintptr_t arg) { /* ... */ }
constexpr const KSession *GetParent() const { return this->parent; }
/* TODO: More of KClientSession. */
};
}

View File

@@ -130,11 +130,11 @@ namespace ams::kern {
MESOSPHERE_ASSERT_THIS();
/* Handle pseudo-handles. */
if constexpr (std::is_same<T, KProcess>::value) {
if constexpr (std::is_base_of<T, KProcess>::value) {
if (handle == ams::svc::PseudoHandle::CurrentProcess) {
return GetCurrentProcessPointer();
}
} else if constexpr (std::is_same<T, KThread>::value) {
} else if constexpr (std::is_base_of<T, KThread>::value) {
if (handle == ams::svc::PseudoHandle::CurrentThread) {
return GetCurrentThreadPointer();
}
@@ -156,11 +156,11 @@ namespace ams::kern {
static_assert(!std::is_base_of<KInterruptEvent, T>::value);
/* Handle pseudo-handles. */
if constexpr (std::is_same<T, KProcess>::value) {
if constexpr (std::is_base_of<T, KProcess>::value) {
if (handle == ams::svc::PseudoHandle::CurrentProcess) {
return GetCurrentProcessPointer();
}
} else if constexpr (std::is_same<T, KThread>::value) {
} else if constexpr (std::is_base_of<T, KThread>::value) {
if (handle == ams::svc::PseudoHandle::CurrentThread) {
return GetCurrentThreadPointer();
}
@@ -201,7 +201,7 @@ namespace ams::kern {
template<typename T>
ALWAYS_INLINE void Register(ams::svc::Handle handle, T *obj) {
static_assert(std::is_base_of<KAutoObject, T>::value);
return this->Add(handle, obj, obj->GetTypeObj().GetClassToken());
return this->Register(handle, obj, obj->GetTypeObj().GetClassToken());
}
private:
NOINLINE Result Add(ams::svc::Handle *out_handle, KAutoObject *obj, u16 type);
@@ -278,7 +278,7 @@ namespace ams::kern {
return entry;
}
constexpr NOINLINE KAutoObject *GetObjectImpl(ams::svc::Handle handle) const {
constexpr ALWAYS_INLINE KAutoObject *GetObjectImpl(ams::svc::Handle handle) const {
MESOSPHERE_ASSERT_THIS();
/* Handles must not have reserved bits set. */
@@ -293,7 +293,7 @@ namespace ams::kern {
}
}
constexpr NOINLINE KAutoObject *GetObjectByIndexImpl(ams::svc::Handle *out_handle, size_t index) const {
constexpr ALWAYS_INLINE KAutoObject *GetObjectByIndexImpl(ams::svc::Handle *out_handle, size_t index) const {
MESOSPHERE_ASSERT_THIS();
/* Index must be in bounds. */
@@ -310,6 +310,49 @@ namespace ams::kern {
*out_handle = EncodeHandle(index, entry->GetLinearId());
return entry->GetObject();
}
template<typename T>
ALWAYS_INLINE bool GetMultipleObjects(T **out, const ams::svc::Handle *handles, size_t num_handles) const {
/* Try to convert and open all the handles. */
size_t num_opened;
{
/* Lock the table. */
KScopedDisableDispatch dd;
KScopedSpinLock lk(this->lock);
for (num_opened = 0; num_opened < num_handles; num_opened++) {
/* Get the current handle. */
const auto cur_handle = handles[num_opened];
/* Get the object for the current handle. */
KAutoObject *cur_object = this->GetObjectImpl(cur_handle);
if (AMS_UNLIKELY(cur_object == nullptr)) {
break;
}
/* Cast the current object to the desired type. */
T *cur_t = cur_object->DynamicCast<T*>();
if (AMS_UNLIKELY(cur_t == nullptr)) {
break;
}
/* Open a reference to the current object. */
cur_t->Open();
out[num_opened] = cur_t;
}
}
/* If we converted every object, succeed. */
if (AMS_LIKELY(num_opened == num_handles)) {
return true;
}
/* If we didn't convert entry object, close the ones we opened. */
for (size_t i = 0; i < num_opened; i++) {
out[i]->Close();
}
return false;
}
};
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018-2020 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_synchronization_object.hpp>
namespace ams::kern {
class KLightSession;
class KLightClientSession final : public KAutoObjectWithSlabHeapAndContainer<KLightClientSession, KAutoObjectWithList> {
MESOSPHERE_AUTOOBJECT_TRAITS(KLightClientSession, KAutoObject);
private:
KLightSession *parent;
public:
constexpr KLightClientSession() : parent() { /* ... */ }
virtual ~KLightClientSession() { /* ... */ }
void Initialize(KLightSession *parent) {
/* Set member variables. */
this->parent = parent;
}
static void PostDestroy(uintptr_t arg) { /* ... */ }
constexpr const KLightSession *GetParent() const { return this->parent; }
/* TODO: More of KLightClientSession. */
};
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018-2020 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_synchronization_object.hpp>
#include <mesosphere/kern_k_thread.hpp>
#include <mesosphere/kern_k_thread_queue.hpp>
namespace ams::kern {
class KLightSession;
class KLightServerSession final : public KAutoObjectWithSlabHeapAndContainer<KLightServerSession, KAutoObjectWithList>, public util::IntrusiveListBaseNode<KLightServerSession> {
MESOSPHERE_AUTOOBJECT_TRAITS(KLightServerSession, KAutoObject);
private:
KLightSession *parent;
KThreadQueue request_queue;
KThreadQueue server_queue;
KThread *current_request;
KThread *server_thread;
public:
constexpr KLightServerSession() : parent(), request_queue(), server_queue(), current_request(), server_thread() { /* ... */ }
virtual ~KLightServerSession() { /* ... */ }
void Initialize(KLightSession *parent);
static void PostDestroy(uintptr_t arg) { /* ... */ }
constexpr const KLightSession *GetParent() const { return this->parent; }
/* TODO: More of KLightServerSession. */
};
}

View File

@@ -16,14 +16,52 @@
#pragma once
#include <mesosphere/kern_common.hpp>
#include <mesosphere/kern_k_synchronization_object.hpp>
#include <mesosphere/kern_k_light_server_session.hpp>
#include <mesosphere/kern_k_light_client_session.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
namespace ams::kern {
class KClientPort;
class KProcess;
class KLightSession final : public KAutoObjectWithSlabHeapAndContainer<KLightSession, KAutoObjectWithList> {
MESOSPHERE_AUTOOBJECT_TRAITS(KLightSession, KAutoObject);
private:
enum class State : u8 {
Invalid = 0,
Normal = 1,
ClientClosed = 2,
ServerClosed = 3,
};
private:
KLightServerSession server;
KLightClientSession client;
State state;
KClientPort *port;
uintptr_t name;
KProcess *process;
bool initialized;
public:
constexpr KLightSession()
: server(), client(), state(State::Invalid), port(), name(), process(), initialized()
{
/* ... */
}
virtual ~KLightSession() { /* ... */ }
virtual bool IsInitialized() const override { return this->initialized; }
virtual uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(this->process); }
static void PostDestroy(uintptr_t arg);
/* TODO: This is a placeholder definition. */
KLightClientSession &GetClientSession() { return this->client; }
KLightServerSession &GetServerSession() { return this->server; }
const KLightClientSession &GetClientSession() const { return this->client; }
const KLightServerSession &GetServerSession() const { return this->server; }
};
}

View File

@@ -23,7 +23,39 @@ namespace ams::kern {
class KObjectName : public KSlabAllocated<KObjectName>, public util::IntrusiveListBaseNode<KObjectName> {
public:
/* TODO: This is a placeholder definition. */
static constexpr size_t NameLengthMax = 12;
using List = util::IntrusiveListBaseTraits<KObjectName>::ListType;
private:
char name[NameLengthMax];
KAutoObject *object;
public:
constexpr KObjectName() : name(), object() { /* ... */ }
public:
static Result NewFromName(KAutoObject *obj, const char *name);
static Result Delete(KAutoObject *obj, const char *name);
static KScopedAutoObject<KAutoObject> Find(const char *name);
template<typename Derived>
static Result Delete(const char *name) {
/* Find the object. */
KScopedAutoObject obj = Find(name);
R_UNLESS(obj.IsNotNull(), svc::ResultNotFound());
/* Cast the object to the desired type. */
Derived *derived = obj->DynamicCast<Derived *>();
R_UNLESS(derived != nullptr, svc::ResultNotFound());
return Delete(obj.GetPointerUnsafe(), name);
}
private:
static KScopedAutoObject<KAutoObject> FindImpl(const char *name);
void Initialize(KAutoObject *obj, const char *name);
bool MatchesName(const char *name) const;
KAutoObject *GetObject() const { return this->object; }
};
}

View File

@@ -239,7 +239,7 @@ namespace ams::kern {
/* Align up the address. */
KVirtualAddress end = addr + size;
const size_t align = (this->next_block_shift != 0) ? (u64(1) << this->next_block_shift) : (this->block_shift);
const size_t align = (this->next_block_shift != 0) ? (u64(1) << this->next_block_shift) : (u64(1) << this->block_shift);
addr = util::AlignDown(GetInteger(addr), align);
end = util::AlignUp(GetInteger(end), align);

View File

@@ -191,8 +191,6 @@ namespace ams::kern {
KPageTableImpl &GetImpl() { return this->impl; }
const KPageTableImpl &GetImpl() const { return this->impl; }
KBlockInfoManager *GetBlockInfoManager() const { return this->block_info_manager; }
bool IsLockedByCurrentThread() const { return this->general_lock.IsLockedByCurrentThread(); }
bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) {
@@ -245,6 +243,8 @@ namespace ams::kern {
return this->GetImpl().GetPhysicalAddress(out, virt_addr);
}
KBlockInfoManager *GetBlockInfoManager() const { return this->block_info_manager; }
Result SetMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
Result SetProcessMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
Result SetHeapSize(KProcessAddress *out, size_t size);
@@ -270,18 +270,22 @@ namespace ams::kern {
Result MapPageGroup(KProcessAddress *out_addr, const KPageGroup &pg, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm);
Result MapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state, KMemoryPermission perm);
Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state);
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr);
public:
KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; }
KProcessAddress GetHeapRegionStart() const { return this->heap_region_start; }
KProcessAddress GetAliasRegionStart() const { return this->alias_region_start; }
KProcessAddress GetStackRegionStart() const { return this->stack_region_start; }
KProcessAddress GetKernelMapRegionStart() const { return this->kernel_map_region_start; }
KProcessAddress GetAliasCodeRegionStart() const { return this->alias_code_region_start; }
size_t GetAddressSpaceSize() const { return this->address_space_end - this->address_space_start; }
size_t GetHeapRegionSize() const { return this->heap_region_end - this->heap_region_start; }
size_t GetAliasRegionSize() const { return this->alias_region_end - this->alias_region_start; }
size_t GetStackRegionSize() const { return this->stack_region_end - this->stack_region_start; }
size_t GetKernelMapRegionSize() const { return this->kernel_map_region_end - this->kernel_map_region_start; }
size_t GetAliasCodeRegionSize() const { return this->alias_code_region_end - this->alias_code_region_start; }
public:
static ALWAYS_INLINE KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress addr) {
return KMemoryLayout::GetLinearVirtualAddress(addr);

View File

@@ -16,14 +16,46 @@
#pragma once
#include <mesosphere/kern_common.hpp>
#include <mesosphere/kern_k_synchronization_object.hpp>
#include <mesosphere/kern_k_client_port.hpp>
#include <mesosphere/kern_k_server_port.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
namespace ams::kern {
class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjectWithList> {
MESOSPHERE_AUTOOBJECT_TRAITS(KPort, KAutoObject);
private:
enum class State : u8 {
Invalid = 0,
Normal = 1,
ClientClosed = 2,
ServerClosed = 3,
};
private:
KServerPort server;
KClientPort client;
uintptr_t name;
State state;
bool is_light;
public:
/* TODO: This is a placeholder definition. */
constexpr KPort() : server(), client(), name(), state(State::Invalid), is_light() { /* ... */ }
virtual ~KPort() { /* ... */ }
static void PostDestroy(uintptr_t arg) { /* ... */ }
void Initialize(s32 max_sessions, bool is_light, uintptr_t name);
void OnClientClosed();
void OnServerClosed();
uintptr_t GetName() const { return this->name; }
bool IsLight() const { return this->is_light; }
/* TODO: More of KPort */
KClientPort &GetClientPort() { return this->client; }
KServerPort &GetServerPort() { return this->server; }
const KClientPort &GetClientPort() const { return this->client; }
const KServerPort &GetServerPort() const { return this->server; }
};
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018-2020 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_synchronization_object.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
namespace ams::kern {
class KPort;
class KServerSession;
class KLightServerSession;
class KServerPort final : public KSynchronizationObject {
MESOSPHERE_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject);
private:
using SessionList = util::IntrusiveListBaseTraits<KServerSession>::ListType;
using LightSessionList = util::IntrusiveListBaseTraits<KLightServerSession>::ListType;
private:
SessionList session_list;
LightSessionList light_session_list;
KPort *parent;
public:
constexpr KServerPort() : session_list(), light_session_list(), parent() { /* ... */ }
virtual ~KServerPort() { /* ... */ }
void Initialize(KPort *parent);
constexpr const KPort *GetParent() const { return this->parent; }
bool IsLight() const;
/* Overridden virtual functions. */
virtual void Destroy() override;
virtual bool IsSignaled() const override;
/* TODO: More of KClientPort. */
private:
void CleanupSessions();
/* TODO: This is a placeholder definition. */
};
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2018-2020 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_synchronization_object.hpp>
#include <mesosphere/kern_k_session_request.hpp>
#include <mesosphere/kern_k_light_lock.hpp>
namespace ams::kern {
class KSession;
class KServerSession final : public KSynchronizationObject, public util::IntrusiveListBaseNode<KServerSession> {
MESOSPHERE_AUTOOBJECT_TRAITS(KServerSession, KSynchronizationObject);
private:
using RequestList = util::IntrusiveListBaseTraits<KSessionRequest>::ListType;
private:
KSession *parent;
RequestList request_list;
KSessionRequest *current_request;
KLightLock lock;
public:
constexpr KServerSession() : parent(), request_list(), current_request(), lock() { /* ... */ }
virtual ~KServerSession() { /* ... */ }
void Initialize(KSession *parent);
constexpr const KSession *GetParent() const { return this->parent; }
virtual bool IsSignaled() const override { MESOSPHERE_UNIMPLEMENTED(); }
/* TODO: More of KServerSession. */
};
}

View File

@@ -16,14 +16,52 @@
#pragma once
#include <mesosphere/kern_common.hpp>
#include <mesosphere/kern_k_synchronization_object.hpp>
#include <mesosphere/kern_k_server_session.hpp>
#include <mesosphere/kern_k_client_session.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
namespace ams::kern {
class KClientPort;
class KProcess;
class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> {
MESOSPHERE_AUTOOBJECT_TRAITS(KSession, KAutoObject);
private:
enum class State : u8 {
Invalid = 0,
Normal = 1,
ClientClosed = 2,
ServerClosed = 3,
};
private:
KServerSession server;
KClientSession client;
State state;
KClientPort *port;
uintptr_t name;
KProcess *process;
bool initialized;
public:
constexpr KSession()
: server(), client(), state(State::Invalid), port(), name(), process(), initialized()
{
/* ... */
}
virtual ~KSession() { /* ... */ }
virtual bool IsInitialized() const override { return this->initialized; }
virtual uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(this->process); }
static void PostDestroy(uintptr_t arg);
/* TODO: This is a placeholder definition. */
KClientSession &GetClientSession() { return this->client; }
KServerSession &GetServerSession() { return this->server; }
const KClientSession &GetClientSession() const { return this->client; }
const KServerSession &GetServerSession() const { return this->server; }
};
}

View File

@@ -32,7 +32,7 @@ namespace ams::kern {
#define MESOSPHERE_UNUSED(...) ::ams::kern::UnusedImpl(__VA_ARGS__)
#ifdef MESOSPHERE_ENABLE_DEBUG_PRINT
#define MESOSPHERE_PANIC(...) do { ::ams::kern::Panic(__FILE__, __LINE__, __VA_ARGS__); } while(0)
#define MESOSPHERE_PANIC(...) do { ::ams::kern::Panic(__FILE__, __LINE__, ## __VA_ARGS__); } while(0)
#else
#define MESOSPHERE_PANIC(...) do { MESOSPHERE_UNUSED(__VA_ARGS__); ::ams::kern::Panic(); } while(0)
#endif

View File

@@ -150,6 +150,15 @@ namespace ams::kern::arch::arm64 {
HandleUserException(context, esr, far, afsr0, afsr1, data);
}
} else {
MESOSPHERE_LOG("Unhandled Exception in Supervisor Mode\n");
MESOSPHERE_LOG("Current Process = %s\n", GetCurrentProcess().GetName());
for (size_t i = 0; i < 31; i++) {
MESOSPHERE_LOG("X[%02zu] = %016lx\n", i, context->x[i]);
}
MESOSPHERE_LOG("PC = %016lx\n", context->pc);
MESOSPHERE_LOG("SP = %016lx\n", context->sp);
MESOSPHERE_PANIC("Unhandled Exception in Supervisor Mode\n");
}

View File

@@ -262,8 +262,8 @@ namespace ams::kern::arch::arm64 {
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
/* If auto-cleared, we can succeed immediately. */
R_UNLESS(entry.manually_cleared, ResultSuccess());
R_UNLESS(entry.needs_clear, ResultSuccess());
R_SUCCEED_IF(!entry.manually_cleared);
R_SUCCEED_IF(!entry.needs_clear);
/* Clear and enable. */
entry.needs_clear = false;
@@ -277,8 +277,8 @@ namespace ams::kern::arch::arm64 {
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
/* If auto-cleared, we can succeed immediately. */
R_UNLESS(entry.manually_cleared, ResultSuccess());
R_UNLESS(entry.needs_clear, ResultSuccess());
R_SUCCEED_IF(!entry.manually_cleared);
R_SUCCEED_IF(!entry.needs_clear);
/* Clear and set priority. */
entry.needs_clear = false;

View File

@@ -832,7 +832,7 @@ namespace ams::kern::arch::arm64 {
L1PageTableEntry *l1_entry = impl.GetL1Entry(virt_addr);
if (l1_entry->IsBlock()) {
/* If our block size is too big, don't bother. */
R_UNLESS(block_size < L1BlockSize, ResultSuccess());
R_SUCCEED_IF(block_size >= L1BlockSize);
/* Get the addresses we're working with. */
const KProcessAddress block_virt_addr = util::AlignDown(GetInteger(virt_addr), L1BlockSize);
@@ -859,10 +859,10 @@ namespace ams::kern::arch::arm64 {
}
/* If we don't have an l1 table, we're done. */
R_UNLESS(l1_entry->IsTable(), ResultSuccess());
R_SUCCEED_IF(!l1_entry->IsTable());
/* We want to separate L2 contiguous blocks into L2 blocks, so check that our size permits that. */
R_UNLESS(block_size < L2ContiguousBlockSize, ResultSuccess());
R_SUCCEED_IF(block_size >= L2ContiguousBlockSize);
L2PageTableEntry *l2_entry = impl.GetL2Entry(l1_entry, virt_addr);
if (l2_entry->IsBlock()) {
@@ -878,7 +878,7 @@ namespace ams::kern::arch::arm64 {
}
/* We want to separate L2 blocks into L3 contiguous blocks, so check that our size permits that. */
R_UNLESS(block_size < L2BlockSize, ResultSuccess());
R_SUCCEED_IF(block_size >= L2BlockSize);
/* Get the addresses we're working with. */
const KProcessAddress block_virt_addr = util::AlignDown(GetInteger(virt_addr), L2BlockSize);
@@ -905,10 +905,10 @@ namespace ams::kern::arch::arm64 {
}
/* If we don't have an L3 table, we're done. */
R_UNLESS(l2_entry->IsTable(), ResultSuccess());
R_SUCCEED_IF(!l2_entry->IsTable());
/* We want to separate L3 contiguous blocks into L2 blocks, so check that our size permits that. */
R_UNLESS(block_size < L3ContiguousBlockSize, ResultSuccess());
R_SUCCEED_IF(block_size >= L3ContiguousBlockSize);
/* If we're contiguous, try to separate. */
L3PageTableEntry *l3_entry = impl.GetL3Entry(l2_entry, virt_addr);

View File

@@ -257,7 +257,7 @@ namespace ams::kern::board::nintendo::nx {
const WordType clear_bit = (this->state[i] + 1) ^ (this->state[i]);
this->state[i] |= clear_bit;
out[num_reserved++] = static_cast<u8>(BitsPerWord * i + BitsPerWord - 1 - ClearLeadingZero(clear_bit));
R_UNLESS(num_reserved != num_desired, ResultSuccess());
R_SUCCEED_IF(num_reserved == num_desired);
}
}

View File

@@ -327,4 +327,53 @@ namespace ams::kern::board::nintendo::nx {
while (true) { /* ... */ }
}
/* User access. */
void KSystemControl::CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args) {
/* Get the function id for the current call. */
u64 function_id = args->r[0];
MESOSPHERE_LOG("CallSecureMonitor(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx);\n", args->r[0], args->r[1], args->r[2], args->r[3], args->r[4], args->r[5], args->r[6], args->r[7]);
/* We'll need to map in pages if arguments are pointers. Prepare page groups to do so. */
auto &page_table = GetCurrentProcess().GetPageTable();
auto *bim = page_table.GetBlockInfoManager();
constexpr size_t MaxMappedRegisters = 7;
std::array<KPageGroup, MaxMappedRegisters> page_groups = { KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), };
for (size_t i = 0; i < MaxMappedRegisters; i++) {
const size_t reg_id = i + 1;
if (function_id & (1ul << (8 + reg_id))) {
/* Create and open a new page group for the address. */
KVirtualAddress virt_addr = args->r[reg_id];
if (R_SUCCEEDED(page_table.MakeAndOpenPageGroup(std::addressof(page_groups[i]), util::AlignDown(GetInteger(virt_addr), PageSize), 1, KMemoryState_None, KMemoryState_None, KMemoryPermission_UserReadWrite, KMemoryPermission_UserReadWrite, KMemoryAttribute_None, KMemoryAttribute_None))) {
/* Translate the virtual address to a physical address. */
const auto it = page_groups[i].begin();
MESOSPHERE_ASSERT(it != page_groups[i].end());
MESOSPHERE_ASSERT(it->GetNumPages() == 1);
KPhysicalAddress phys_addr = page_table.GetHeapPhysicalAddress(it->GetAddress());
args->r[reg_id] = GetInteger(phys_addr) | (GetInteger(virt_addr) & (PageSize - 1));
MESOSPHERE_LOG("Mapped arg %zu\n", reg_id);
} else {
/* If we couldn't map, we should clear the address. */
MESOSPHERE_LOG("Failed to map arg %zu\n", reg_id);
args->r[reg_id] = 0;
}
}
}
/* Invoke the secure monitor. */
smc::CallSecureMonitorFromUser(args);
MESOSPHERE_LOG("Secure Monitor Returned: (%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx);\n", args->r[0], args->r[1], args->r[2], args->r[3], args->r[4], args->r[5], args->r[6], args->r[7]);
/* Make sure that we close any pages that we opened. */
for (size_t i = 0; i < MaxMappedRegisters; i++) {
page_groups[i].Close();
}
}
}

View File

@@ -71,6 +71,42 @@ namespace ams::kern::board::nintendo::nx::smc {
args.x[7] = x7;
}
void CallUserSecureMonitorFunction(ams::svc::lp64::SecureMonitorArguments *args) {
/* Load arguments into registers. */
register u64 x0 asm("x0") = args->r[0];
register u64 x1 asm("x1") = args->r[1];
register u64 x2 asm("x2") = args->r[2];
register u64 x3 asm("x3") = args->r[3];
register u64 x4 asm("x4") = args->r[4];
register u64 x5 asm("x5") = args->r[5];
register u64 x6 asm("x6") = args->r[6];
register u64 x7 asm("x7") = args->r[7];
/* Actually make the call. */
{
/* Disable interrupts while making the call. */
KScopedInterruptDisable intr_disable;
__asm__ __volatile__("smc #0"
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
:
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
);
/* Restore the CoreLocalRegion into X18. */
cpu::SetCoreLocalRegionAddress(cpu::GetTpidrEl1());
}
/* Store arguments to output. */
args->r[0] = x0;
args->r[1] = x1;
args->r[2] = x2;
args->r[3] = x3;
args->r[4] = x4;
args->r[5] = x5;
args->r[6] = x6;
args->r[7] = x7;
}
void CallPrivilegedSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
/* Load arguments into registers. */
register u64 x0 asm("x0") = args.x[0];
@@ -188,4 +224,8 @@ namespace ams::kern::board::nintendo::nx::smc {
while (true) { /* ... */ }
}
void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args) {
CallUserSecureMonitorFunction(args);
}
}

View File

@@ -91,6 +91,8 @@ namespace ams::kern::board::nintendo::nx::smc {
void NORETURN Panic(u32 color);
void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
namespace init {
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);

View File

@@ -211,7 +211,9 @@ namespace ams::kern {
/* Validate this is a capability we can act on. */
const auto type = GetCapabilityType(cap);
R_UNLESS(type != CapabilityType::Invalid, svc::ResultInvalidArgument());
R_UNLESS(type != CapabilityType::Padding, ResultSuccess());
/* If the type is padding, we have no work to do. */
R_SUCCEED_IF(type == CapabilityType::Padding);
/* Check that we haven't already processed this capability. */
const auto flag = GetCapabilityFlag(type);

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern {
void KClientPort::Initialize(KPort *parent, s32 max_sessions) {
/* Set member variables. */
this->num_sessions = 0;
this->peak_sessions = 0;
this->parent = parent;
this->max_sessions = max_sessions;
}
bool KClientPort::IsLight() const {
return this->GetParent()->IsLight();
}
void KClientPort::Destroy() {
/* Note with our parent that we're closed. */
this->parent->OnClientClosed();
/* Close our reference to our parent. */
this->parent->Close();
}
bool KClientPort::IsSignaled() const {
/* TODO: Check preconditions later. */
MESOSPHERE_ASSERT_THIS();
return this->num_sessions < this->max_sessions;
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern {
namespace {
/* TODO: C++20 constinit */
KLightLock g_object_list_lock;
KObjectName::List g_object_list;
}
void KObjectName::Initialize(KAutoObject *obj, const char *name) {
/* Set member variables. */
this->object = obj;
std::strncpy(this->name, name, sizeof(this->name));
this->name[sizeof(this->name) - 1] = '\x00';
/* Open a reference to the object we hold. */
this->object->Open();
}
bool KObjectName::MatchesName(const char *name) const {
return std::strncmp(this->name, name, sizeof(this->name)) == 0;
}
Result KObjectName::NewFromName(KAutoObject *obj, const char *name) {
/* Create a new object name. */
KObjectName *new_name = KObjectName::Allocate();
R_UNLESS(new_name != nullptr, svc::ResultOutOfResource());
/* Initialize the new name. */
new_name->Initialize(obj, name);
/* Check if there's an existing name. */
{
/* Ensure we have exclusive access to the global list. */
KScopedLightLock lk(g_object_list_lock);
/* If the object doesn't exist, put it into the list. */
KScopedAutoObject existing_object = FindImpl(name);
if (existing_object.IsNull()) {
g_object_list.push_back(*new_name);
return ResultSuccess();
}
}
/* The object already exists, which is an error condition. Perform cleanup. */
obj->Close();
KObjectName::Free(new_name);
return svc::ResultInvalidState();
}
Result KObjectName::Delete(KAutoObject *obj, const char *compare_name) {
/* Ensure we have exclusive access to the global list. */
KScopedLightLock lk(g_object_list_lock);
/* Find a matching entry in the list, and delete it. */
for (auto &name : g_object_list) {
if (name.MatchesName(compare_name) && obj == name.GetObject()) {
/* We found a match, clean up its resources. */
obj->Close();
g_object_list.erase(g_object_list.iterator_to(name));
KObjectName::Free(std::addressof(name));
return ResultSuccess();
}
}
/* We didn't find the object in the list. */
return svc::ResultNotFound();
}
KScopedAutoObject<KAutoObject> KObjectName::Find(const char *name) {
/* Ensure we have exclusive access to the global list. */
KScopedLightLock lk(g_object_list_lock);
return FindImpl(name);
}
KScopedAutoObject<KAutoObject> KObjectName::FindImpl(const char *compare_name) {
/* Try to find a matching object in the global list. */
for (const auto &name : g_object_list) {
if (name.MatchesName(compare_name)) {
return name.GetObject();
}
}
/* There's no matching entry in the list. */
return nullptr;
}
}

View File

@@ -38,7 +38,7 @@ namespace ams::kern {
Result KPageGroup::AddBlock(KVirtualAddress addr, size_t num_pages) {
/* Succeed immediately if we're adding no pages. */
R_UNLESS(num_pages != 0, ResultSuccess());
R_SUCCEED_IF(num_pages == 0);
/* Check for overflow. */
MESOSPHERE_ASSERT(addr < addr + num_pages * PageSize);
@@ -46,7 +46,7 @@ namespace ams::kern {
/* Try to just append to the last block. */
if (!this->block_list.empty()) {
auto it = --(this->block_list.end());
R_UNLESS(!it->TryConcatenate(addr, num_pages), ResultSuccess());
R_SUCCEED_IF(it->TryConcatenate(addr, num_pages));
}
/* Allocate a new block. */

View File

@@ -1020,4 +1020,27 @@ namespace ams::kern {
return ResultSuccess();
}
Result KPageTableBase::MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) {
/* Ensure that the page group isn't null. */
AMS_ASSERT(out != nullptr);
/* Make sure that the region we're mapping is valid for the table. */
const size_t size = num_pages * PageSize;
R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory());
/* Lock the table. */
KScopedLightLock lk(this->general_lock);
/* Check if state allows us to create the group. */
R_TRY(this->CheckMemoryState(address, size, state_mask | KMemoryState_FlagReferenceCounted, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr));
/* Create a new page group for the region. */
R_TRY(this->MakePageGroup(*out, address, num_pages));
/* Open a new reference to the pages in the group. */
out->Open();
return ResultSuccess();
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern {
void KPort::Initialize(s32 max_sessions, bool is_light, uintptr_t name) {
/* Open a new reference count to the initialized port. */
this->Open();
/* Create and initialize our server/client pair. */
KAutoObject::Create(std::addressof(this->server));
KAutoObject::Create(std::addressof(this->client));
this->server.Initialize(this);
this->client.Initialize(this, max_sessions);
/* Set our member variables. */
this->is_light = is_light;
this->name = name;
this->state = State::Normal;
}
void KPort::OnClientClosed() {
MESOSPHERE_UNIMPLEMENTED();
}
void KPort::OnServerClosed() {
MESOSPHERE_UNIMPLEMENTED();
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern {
void KServerPort::Initialize(KPort *parent) {
/* Set member variables. */
this->parent = parent;
}
bool KServerPort::IsLight() const {
return this->GetParent()->IsLight();
}
void KServerPort::CleanupSessions() {
/* Ensure our preconditions are met. */
MESOSPHERE_ASSERT(this->IsLight() || this->session_list.empty());
MESOSPHERE_ASSERT(!this->IsLight() || this->light_session_list.empty());
/* Cleanup the session list. */
while (true) {
/* Get the last session in the list */
KServerSession *session = nullptr;
{
KScopedSchedulerLock sl;
while (!this->session_list.empty()) {
session = std::addressof(this->session_list.front());
this->session_list.pop_front();
}
}
/* Close the session. */
if (session != nullptr) {
session->Close();
} else {
break;
}
}
/* Cleanup the light session list. */
while (true) {
/* Get the last session in the list */
KLightServerSession *session = nullptr;
{
KScopedSchedulerLock sl;
while (!this->light_session_list.empty()) {
session = std::addressof(this->light_session_list.front());
this->light_session_list.pop_front();
}
}
/* Close the session. */
if (session != nullptr) {
session->Close();
} else {
break;
}
}
}
void KServerPort::Destroy() {
/* Note with our parent that we're closed. */
this->parent->OnClientClosed();
/* Perform necessary cleanup of our session lists. */
this->CleanupSessions();
/* Close our reference to our parent. */
this->parent->Close();
}
bool KServerPort::IsSignaled() const {
/* TODO: Check preconditions later. */
MESOSPHERE_ASSERT_THIS();
if (this->IsLight()) {
return !this->light_session_list.empty();
} else {
return this->session_list.empty();
}
}
}

View File

@@ -0,0 +1,31 @@
/*
* Macros for asm code.
*
* Copyright (c) 2019, Arm Limited.
* SPDX-License-Identifier: MIT
*/
#ifndef _ASMDEFS_H
#define _ASMDEFS_H
#define ENTRY_ALIGN(name, alignment) \
.global name; \
.type name,%function; \
.align alignment; \
name: \
.cfi_startproc;
#define ENTRY(name) ENTRY_ALIGN(name, 6)
#define ENTRY_ALIAS(name) \
.global name; \
.type name,%function; \
name:
#define END(name) \
.cfi_endproc; \
.size name, .-name;
#define L(l) .L ## l
#endif

View File

@@ -0,0 +1,133 @@
/* memcmp - compare memory
*
* Copyright (c) 2013, Arm Limited.
* SPDX-License-Identifier: MIT
*/
/* Assumptions:
*
* ARMv8-a, AArch64, unaligned accesses.
*/
#include "asmdefs.h"
/* Parameters and result. */
#define src1 x0
#define src2 x1
#define limit x2
#define result w0
/* Internal variables. */
#define data1 x3
#define data1w w3
#define data1h x4
#define data2 x5
#define data2w w5
#define data2h x6
#define tmp1 x7
#define tmp2 x8
ENTRY (memcmp)
subs limit, limit, 8
b.lo L(less8)
ldr data1, [src1], 8
ldr data2, [src2], 8
cmp data1, data2
b.ne L(return)
subs limit, limit, 8
b.gt L(more16)
ldr data1, [src1, limit]
ldr data2, [src2, limit]
b L(return)
L(more16):
ldr data1, [src1], 8
ldr data2, [src2], 8
cmp data1, data2
bne L(return)
/* Jump directly to comparing the last 16 bytes for 32 byte (or less)
strings. */
subs limit, limit, 16
b.ls L(last_bytes)
/* We overlap loads between 0-32 bytes at either side of SRC1 when we
try to align, so limit it only to strings larger than 128 bytes. */
cmp limit, 96
b.ls L(loop16)
/* Align src1 and adjust src2 with bytes not yet done. */
and tmp1, src1, 15
add limit, limit, tmp1
sub src1, src1, tmp1
sub src2, src2, tmp1
/* Loop performing 16 bytes per iteration using aligned src1.
Limit is pre-decremented by 16 and must be larger than zero.
Exit if <= 16 bytes left to do or if the data is not equal. */
.p2align 4
L(loop16):
ldp data1, data1h, [src1], 16
ldp data2, data2h, [src2], 16
subs limit, limit, 16
ccmp data1, data2, 0, hi
ccmp data1h, data2h, 0, eq
b.eq L(loop16)
cmp data1, data2
bne L(return)
mov data1, data1h
mov data2, data2h
cmp data1, data2
bne L(return)
/* Compare last 1-16 bytes using unaligned access. */
L(last_bytes):
add src1, src1, limit
add src2, src2, limit
ldp data1, data1h, [src1]
ldp data2, data2h, [src2]
cmp data1, data2
bne L(return)
mov data1, data1h
mov data2, data2h
cmp data1, data2
/* Compare data bytes and set return value to 0, -1 or 1. */
L(return):
#ifndef __AARCH64EB__
rev data1, data1
rev data2, data2
#endif
cmp data1, data2
L(ret_eq):
cset result, ne
cneg result, result, lo
ret
.p2align 4
/* Compare up to 8 bytes. Limit is [-8..-1]. */
L(less8):
adds limit, limit, 4
b.lo L(less4)
ldr data1w, [src1], 4
ldr data2w, [src2], 4
cmp data1w, data2w
b.ne L(return)
sub limit, limit, 4
L(less4):
adds limit, limit, 4
beq L(ret_eq)
L(byte_loop):
ldrb data1w, [src1], 1
ldrb data2w, [src2], 1
subs limit, limit, 1
ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
b.eq L(byte_loop)
sub result, data1w, data2w
ret
END (memcmp)

View File

@@ -0,0 +1,239 @@
/*
* memcpy - copy memory area
*
* Copyright (c) 2012-2020, Arm Limited.
* SPDX-License-Identifier: MIT
*/
/* Assumptions:
*
* ARMv8-a, AArch64, unaligned accesses.
*
*/
#include "asmdefs.h"
#define dstin x0
#define src x1
#define count x2
#define dst x3
#define srcend x4
#define dstend x5
#define A_l x6
#define A_lw w6
#define A_h x7
#define B_l x8
#define B_lw w8
#define B_h x9
#define C_l x10
#define C_lw w10
#define C_h x11
#define D_l x12
#define D_h x13
#define E_l x14
#define E_h x15
#define F_l x16
#define F_h x17
#define G_l count
#define G_h dst
#define H_l src
#define H_h srcend
#define tmp1 x14
/* This implementation handles overlaps and supports both memcpy and memmove
from a single entry point. It uses unaligned accesses and branchless
sequences to keep the code small, simple and improve performance.
Copies are split into 3 main cases: small copies of up to 32 bytes, medium
copies of up to 128 bytes, and large copies. The overhead of the overlap
check is negligible since it is only required for large copies.
Large copies use a software pipelined loop processing 64 bytes per iteration.
The destination pointer is 16-byte aligned to minimize unaligned accesses.
The loop tail is handled by always copying 64 bytes from the end.
*/
ENTRY (memcpy)
ENTRY_ALIAS (memmove)
add srcend, src, count
add dstend, dstin, count
cmp count, 128
b.hi L(copy_long)
cmp count, 32
b.hi L(copy32_128)
/* Small copies: 0..32 bytes. */
cmp count, 16
b.lo L(copy16)
ldp A_l, A_h, [src]
ldp D_l, D_h, [srcend, -16]
stp A_l, A_h, [dstin]
stp D_l, D_h, [dstend, -16]
ret
/* Copy 8-15 bytes. */
L(copy16):
tbz count, 3, L(copy8)
ldr A_l, [src]
ldr A_h, [srcend, -8]
str A_l, [dstin]
str A_h, [dstend, -8]
ret
.p2align 3
/* Copy 4-7 bytes. */
L(copy8):
tbz count, 2, L(copy4)
ldr A_lw, [src]
ldr B_lw, [srcend, -4]
str A_lw, [dstin]
str B_lw, [dstend, -4]
ret
/* Copy 0..3 bytes using a branchless sequence. */
L(copy4):
cbz count, L(copy0)
lsr tmp1, count, 1
ldrb A_lw, [src]
ldrb C_lw, [srcend, -1]
ldrb B_lw, [src, tmp1]
strb A_lw, [dstin]
strb B_lw, [dstin, tmp1]
strb C_lw, [dstend, -1]
L(copy0):
ret
.p2align 4
/* Medium copies: 33..128 bytes. */
L(copy32_128):
ldp A_l, A_h, [src]
ldp B_l, B_h, [src, 16]
ldp C_l, C_h, [srcend, -32]
ldp D_l, D_h, [srcend, -16]
cmp count, 64
b.hi L(copy128)
stp A_l, A_h, [dstin]
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstend, -32]
stp D_l, D_h, [dstend, -16]
ret
.p2align 4
/* Copy 65..128 bytes. */
L(copy128):
ldp E_l, E_h, [src, 32]
ldp F_l, F_h, [src, 48]
cmp count, 96
b.ls L(copy96)
ldp G_l, G_h, [srcend, -64]
ldp H_l, H_h, [srcend, -48]
stp G_l, G_h, [dstend, -64]
stp H_l, H_h, [dstend, -48]
L(copy96):
stp A_l, A_h, [dstin]
stp B_l, B_h, [dstin, 16]
stp E_l, E_h, [dstin, 32]
stp F_l, F_h, [dstin, 48]
stp C_l, C_h, [dstend, -32]
stp D_l, D_h, [dstend, -16]
ret
.p2align 4
/* Copy more than 128 bytes. */
L(copy_long):
/* Use backwards copy if there is an overlap. */
sub tmp1, dstin, src
cbz tmp1, L(copy0)
cmp tmp1, count
b.lo L(copy_long_backwards)
/* Copy 16 bytes and then align dst to 16-byte alignment. */
ldp D_l, D_h, [src]
and tmp1, dstin, 15
bic dst, dstin, 15
sub src, src, tmp1
add count, count, tmp1 /* Count is now 16 too large. */
ldp A_l, A_h, [src, 16]
stp D_l, D_h, [dstin]
ldp B_l, B_h, [src, 32]
ldp C_l, C_h, [src, 48]
ldp D_l, D_h, [src, 64]!
subs count, count, 128 + 16 /* Test and readjust count. */
b.ls L(copy64_from_end)
L(loop64):
stp A_l, A_h, [dst, 16]
ldp A_l, A_h, [src, 16]
stp B_l, B_h, [dst, 32]
ldp B_l, B_h, [src, 32]
stp C_l, C_h, [dst, 48]
ldp C_l, C_h, [src, 48]
stp D_l, D_h, [dst, 64]!
ldp D_l, D_h, [src, 64]!
subs count, count, 64
b.hi L(loop64)
/* Write the last iteration and copy 64 bytes from the end. */
L(copy64_from_end):
ldp E_l, E_h, [srcend, -64]
stp A_l, A_h, [dst, 16]
ldp A_l, A_h, [srcend, -48]
stp B_l, B_h, [dst, 32]
ldp B_l, B_h, [srcend, -32]
stp C_l, C_h, [dst, 48]
ldp C_l, C_h, [srcend, -16]
stp D_l, D_h, [dst, 64]
stp E_l, E_h, [dstend, -64]
stp A_l, A_h, [dstend, -48]
stp B_l, B_h, [dstend, -32]
stp C_l, C_h, [dstend, -16]
ret
.p2align 4
/* Large backwards copy for overlapping copies.
Copy 16 bytes and then align dst to 16-byte alignment. */
L(copy_long_backwards):
ldp D_l, D_h, [srcend, -16]
and tmp1, dstend, 15
sub srcend, srcend, tmp1
sub count, count, tmp1
ldp A_l, A_h, [srcend, -16]
stp D_l, D_h, [dstend, -16]
ldp B_l, B_h, [srcend, -32]
ldp C_l, C_h, [srcend, -48]
ldp D_l, D_h, [srcend, -64]!
sub dstend, dstend, tmp1
subs count, count, 128
b.ls L(copy64_from_start)
L(loop64_backwards):
stp A_l, A_h, [dstend, -16]
ldp A_l, A_h, [srcend, -16]
stp B_l, B_h, [dstend, -32]
ldp B_l, B_h, [srcend, -32]
stp C_l, C_h, [dstend, -48]
ldp C_l, C_h, [srcend, -48]
stp D_l, D_h, [dstend, -64]!
ldp D_l, D_h, [srcend, -64]!
subs count, count, 64
b.hi L(loop64_backwards)
/* Write the last iteration and copy 64 bytes from the start. */
L(copy64_from_start):
ldp G_l, G_h, [src, 48]
stp A_l, A_h, [dstend, -16]
ldp A_l, A_h, [src, 32]
stp B_l, B_h, [dstend, -32]
ldp B_l, B_h, [src, 16]
stp C_l, C_h, [dstend, -48]
ldp C_l, C_h, [src]
stp D_l, D_h, [dstend, -64]
stp G_l, G_h, [dstin, 48]
stp A_l, A_h, [dstin, 32]
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstin]
ret
END (memcpy)

View File

@@ -0,0 +1,170 @@
/*
* memset - fill memory with a constant byte
*
* Copyright (c) 2012-2020, Arm Limited.
* SPDX-License-Identifier: MIT
*/
/* Assumptions:
*
* ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
*
*/
#include "asmdefs.h"
#define DC_ZVA_THRESHOLD 512
#define dstin x0
#define val x1
#define valw w1
#define count x2
#define dst x3
#define dstend x4
#define zva_val x5
ENTRY (memset)
bfi valw, valw, 8, 8
bfi valw, valw, 16, 16
bfi val, val, 32, 32
add dstend, dstin, count
cmp count, 96
b.hi L(set_long)
cmp count, 16
b.hs L(set_medium)
/* Set 0..15 bytes. */
tbz count, 3, 1f
str val, [dstin]
str val, [dstend, -8]
ret
1: tbz count, 2, 2f
str valw, [dstin]
str valw, [dstend, -4]
ret
2: cbz count, 3f
strb valw, [dstin]
tbz count, 1, 3f
strh valw, [dstend, -2]
3: ret
/* Set 16..96 bytes. */
.p2align 4
L(set_medium):
stp val, val, [dstin]
tbnz count, 6, L(set96)
stp val, val, [dstend, -16]
tbz count, 5, 1f
stp val, val, [dstin, 16]
stp val, val, [dstend, -32]
1: ret
.p2align 4
/* Set 64..96 bytes. Write 64 bytes from the start and
32 bytes from the end. */
L(set96):
stp val, val, [dstin, 16]
stp val, val, [dstin, 32]
stp val, val, [dstin, 48]
stp val, val, [dstend, -32]
stp val, val, [dstend, -16]
ret
.p2align 4
L(set_long):
stp val, val, [dstin]
bic dst, dstin, 15
#if DC_ZVA_THRESHOLD
cmp count, DC_ZVA_THRESHOLD
ccmp val, 0, 0, cs
b.eq L(zva_64)
#endif
/* Small-size or non-zero memset does not use DC ZVA. */
sub count, dstend, dst
/*
* Adjust count and bias for loop. By substracting extra 1 from count,
* it is easy to use tbz instruction to check whether loop tailing
* count is less than 33 bytes, so as to bypass 2 unneccesary stps.
*/
sub count, count, 64+16+1
#if DC_ZVA_THRESHOLD
/* Align loop on 16-byte boundary, this might be friendly to i-cache. */
nop
#endif
1: stp val, val, [dst, 16]
stp val, val, [dst, 32]
stp val, val, [dst, 48]
stp val, val, [dst, 64]!
subs count, count, 64
b.hs 1b
tbz count, 5, 1f /* Remaining count is less than 33 bytes? */
stp val, val, [dst, 16]
stp val, val, [dst, 32]
1: stp val, val, [dstend, -32]
stp val, val, [dstend, -16]
ret
#if DC_ZVA_THRESHOLD
.p2align 4
L(zva_64):
stp val, val, [dst, 16]
stp val, val, [dst, 32]
stp val, val, [dst, 48]
bic dst, dst, 63
/*
* Previous memory writes might cross cache line boundary, and cause
* cache line partially dirty. Zeroing this kind of cache line using
* DC ZVA will incur extra cost, for it requires loading untouched
* part of the line from memory before zeoring.
*
* So, write the first 64 byte aligned block using stp to force
* fully dirty cache line.
*/
stp val, val, [dst, 64]
stp val, val, [dst, 80]
stp val, val, [dst, 96]
stp val, val, [dst, 112]
sub count, dstend, dst
/*
* Adjust count and bias for loop. By substracting extra 1 from count,
* it is easy to use tbz instruction to check whether loop tailing
* count is less than 33 bytes, so as to bypass 2 unneccesary stps.
*/
sub count, count, 128+64+64+1
add dst, dst, 128
nop
/* DC ZVA sets 64 bytes each time. */
1: dc zva, dst
add dst, dst, 64
subs count, count, 64
b.hs 1b
/*
* Write the last 64 byte aligned block using stp to force fully
* dirty cache line.
*/
stp val, val, [dst, 0]
stp val, val, [dst, 16]
stp val, val, [dst, 32]
stp val, val, [dst, 48]
tbz count, 5, 1f /* Remaining count is less than 33 bytes? */
stp val, val, [dst, 64]
stp val, val, [dst, 80]
1: stp val, val, [dstend, -32]
stp val, val, [dstend, -16]
ret
#endif
END (memset)

View File

@@ -61,6 +61,7 @@ QUICKREF
/*SUPPRESS 20*/
void *
//__inhibit_loop_to_libcall
__attribute__((weak))
memmove (void *dst_void,
const void *src_void,
size_t length)
@@ -169,6 +170,7 @@ QUICKREF
*/
void *
__attribute__((weak))
memcpy (void * dst0,
const void * __restrict src0,
size_t len0)
@@ -259,6 +261,7 @@ QUICKREF
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
void *
__attribute__((weak))
memset (void *m,
int c,
size_t n)
@@ -357,6 +360,7 @@ QUICKREF
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
int
__attribute__((weak))
memcmp (const void *m1,
const void *m2,
size_t n)
@@ -417,6 +421,228 @@ memcmp (const void *m1,
#endif /* not PREFER_SIZE_OVER_SPEED */
}
/*
FUNCTION
<<strncpy>>---counted copy string
INDEX
strncpy
SYNOPSIS
#include <string.h>
char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>,
size_t <[length]>);
DESCRIPTION
<<strncpy>> copies not more than <[length]> characters from the
the string pointed to by <[src]> (including the terminating
null character) to the array pointed to by <[dst]>. If the
string pointed to by <[src]> is shorter than <[length]>
characters, null characters are appended to the destination
array until a total of <[length]> characters have been
written.
RETURNS
This function returns the initial value of <[dst]>.
PORTABILITY
<<strncpy>> is ANSI C.
<<strncpy>> requires no supporting OS subroutines.
QUICKREF
strncpy ansi pure
*/
#include <string.h>
#include <limits.h>
/*SUPPRESS 560*/
/*SUPPRESS 530*/
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
#else
#if LONG_MAX == 9223372036854775807L
/* Nonzero if X (a long int) contains a NULL byte. */
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
#else
#error long int is not a 32bit or 64bit type.
#endif
#endif
#ifndef DETECTNULL
#error long int is not a 32bit or 64bit byte
#endif
#undef TOO_SMALL
#define TOO_SMALL(LEN) ((LEN) < sizeof (long))
char *
strncpy (char *__restrict dst0,
const char *__restrict src0,
size_t count)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
char *dscan;
const char *sscan;
dscan = dst0;
sscan = src0;
while (count > 0)
{
--count;
if ((*dscan++ = *sscan++) == '\0')
break;
}
while (count-- > 0)
*dscan++ = '\0';
return dst0;
#else
char *dst = dst0;
const char *src = src0;
long *aligned_dst;
const long *aligned_src;
/* If SRC and DEST is aligned and count large enough, then copy words. */
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
{
aligned_dst = (long*)dst;
aligned_src = (long*)src;
/* SRC and DEST are both "long int" aligned, try to do "long int"
sized copies. */
while (count >= sizeof (long int) && !DETECTNULL(*aligned_src))
{
count -= sizeof (long int);
*aligned_dst++ = *aligned_src++;
}
dst = (char*)aligned_dst;
src = (char*)aligned_src;
}
while (count > 0)
{
--count;
if ((*dst++ = *src++) == '\0')
break;
}
while (count-- > 0)
*dst++ = '\0';
return dst0;
#endif /* not PREFER_SIZE_OVER_SPEED */
}
/*
FUNCTION
<<strncmp>>---character string compare
INDEX
strncmp
SYNOPSIS
#include <string.h>
int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>);
DESCRIPTION
<<strncmp>> compares up to <[length]> characters
from the string at <[a]> to the string at <[b]>.
RETURNS
If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>,
<<strncmp>> returns a number greater than zero. If the two
strings are equivalent, <<strncmp>> returns zero. If <<*<[a]>>>
sorts lexicographically before <<*<[b]>>>, <<strncmp>> returns a
number less than zero.
PORTABILITY
<<strncmp>> is ANSI C.
<<strncmp>> requires no supporting OS subroutines.
QUICKREF
strncmp ansi pure
*/
#include <string.h>
#include <limits.h>
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#define UNALIGNED(X, Y) \
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
#if LONG_MAX == 2147483647L
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
#else
#if LONG_MAX == 9223372036854775807L
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
#else
#error long int is not a 32bit or 64bit type.
#endif
#endif
#ifndef DETECTNULL
#error long int is not a 32bit or 64bit byte
#endif
int
strncmp (const char *s1,
const char *s2,
size_t n)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
if (n == 0)
return 0;
while (n-- != 0 && *s1 == *s2)
{
if (n == 0 || *s1 == '\0')
break;
s1++;
s2++;
}
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
#else
unsigned long *a1;
unsigned long *a2;
if (n == 0)
return 0;
/* If s1 or s2 are unaligned, then compare bytes. */
if (!UNALIGNED (s1, s2))
{
/* If s1 and s2 are word-aligned, compare them a word at a time. */
a1 = (unsigned long*)s1;
a2 = (unsigned long*)s2;
while (n >= sizeof (long) && *a1 == *a2)
{
n -= sizeof (long);
/* If we've run out of bytes or hit a null, return zero
since we already know *a1 == *a2. */
if (n == 0 || DETECTNULL (*a1))
return 0;
a1++;
a2++;
}
/* A difference was detected in last few bytes of s1, so search bytewise */
s1 = (char*)a1;
s2 = (char*)a2;
}
while (n-- > 0 && *s1 == *s2)
{
/* If we've run out of bytes or hit a null, return zero
since we already know *s1 == *s2. */
if (n == 0 || *s1 == '\0')
return 0;
s1++;
s2++;
}
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
#endif /* not PREFER_SIZE_OVER_SPEED */
}
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@@ -21,28 +21,112 @@ namespace ams::kern::svc {
namespace {
Result GetInfo(u64 *out, ams::svc::InfoType info_type, ams::svc::Handle handle, u64 info_subtype) {
MESOSPHERE_LOG("GetInfo(%p, %u, %08x, %lu) was called\n", out, static_cast<u32>(info_type), static_cast<u32>(handle), info_subtype);
ON_SCOPE_EXIT{ MESOSPHERE_LOG("GetInfo returned %016lx\n", *out); };
switch (info_type) {
case ams::svc::InfoType_AliasRegionAddress:
case ams::svc::InfoType_AliasRegionSize:
case ams::svc::InfoType_HeapRegionAddress:
case ams::svc::InfoType_HeapRegionSize:
case ams::svc::InfoType_AslrRegionAddress:
case ams::svc::InfoType_AslrRegionSize:
case ams::svc::InfoType_StackRegionAddress:
case ams::svc::InfoType_StackRegionSize:
{
/* These info types don't support non-zero subtypes. */
R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination());
/* Get the process from its handle. */
KScopedAutoObject process = GetCurrentProcess().GetHandleTable().GetObject<KProcess>(handle);
R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle());
switch (info_type) {
case ams::svc::InfoType_AliasRegionAddress:
*out = GetInteger(process->GetPageTable().GetAliasRegionStart());
break;
case ams::svc::InfoType_AliasRegionSize:
*out = process->GetPageTable().GetAliasRegionSize();
break;
case ams::svc::InfoType_HeapRegionAddress:
*out = GetInteger(process->GetPageTable().GetHeapRegionStart());
break;
case ams::svc::InfoType_HeapRegionSize:
*out = process->GetPageTable().GetHeapRegionSize();
break;
case ams::svc::InfoType_AslrRegionAddress:
*out = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
break;
case ams::svc::InfoType_AslrRegionSize:
*out = process->GetPageTable().GetAliasCodeRegionSize();
break;
case ams::svc::InfoType_StackRegionAddress:
*out = GetInteger(process->GetPageTable().GetStackRegionStart());
break;
case ams::svc::InfoType_StackRegionSize:
*out = process->GetPageTable().GetStackRegionSize();
break;
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
}
}
break;
default:
return svc::ResultInvalidEnumValue();
}
return ResultSuccess();
}
Result GetSystemInfo(u64 *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, u64 info_subtype) {
MESOSPHERE_LOG("GetSystemInfo(%p, %u, %08x, %lu) was called\n", out, static_cast<u32>(info_type), static_cast<u32>(handle), info_subtype);
ON_SCOPE_EXIT{ MESOSPHERE_LOG("GetSystemInfo returned %016lx\n", *out); };
switch (info_type) {
case ams::svc::SystemInfoType_InitialProcessIdRange:
{
R_UNLESS(handle == ams::svc::InvalidHandle, svc::ResultInvalidHandle());
switch (static_cast<ams::svc::InitialProcessIdRangeInfo>(info_subtype)) {
case ams::svc::InitialProcessIdRangeInfo_Minimum:
MESOSPHERE_ABORT_UNLESS(GetInitialProcessIdMin() <= GetInitialProcessIdMax());
*out = GetInitialProcessIdMin();
break;
case ams::svc::InitialProcessIdRangeInfo_Maximum:
MESOSPHERE_ABORT_UNLESS(GetInitialProcessIdMin() <= GetInitialProcessIdMax());
*out = GetInitialProcessIdMax();
break;
default:
return svc::ResultInvalidCombination();
}
}
break;
default:
return svc::ResultInvalidEnumValue();
}
return ResultSuccess();
}
}
/* ============================= 64 ABI ============================= */
Result GetInfo64(uint64_t *out, ams::svc::InfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
MESOSPHERE_PANIC("Stubbed SvcGetInfo64 was called.");
return GetInfo(out, info_type, handle, info_subtype);
}
Result GetSystemInfo64(uint64_t *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
MESOSPHERE_PANIC("Stubbed SvcGetSystemInfo64 was called.");
return GetSystemInfo(out, info_type, handle, info_subtype);
}
/* ============================= 64From32 ABI ============================= */
Result GetInfo64From32(uint64_t *out, ams::svc::InfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
MESOSPHERE_PANIC("Stubbed SvcGetInfo64From32 was called.");
return GetInfo(out, info_type, handle, info_subtype);
}
Result GetSystemInfo64From32(uint64_t *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
MESOSPHERE_PANIC("Stubbed SvcGetSystemInfo64From32 was called.");
return GetSystemInfo(out, info_type, handle, info_subtype);
}
}

View File

@@ -21,7 +21,61 @@ namespace ams::kern::svc {
namespace {
Result ManageNamedPort(ams::svc::Handle *out_server_handle, KUserPointer<const char *> user_name, s32 max_sessions) {
/* Copy the provided name from user memory to kernel memory. */
char name[KObjectName::NameLengthMax] = {};
R_TRY(user_name.CopyStringTo(name, sizeof(name)));
/* Validate that sessions and name are valid. */
R_UNLESS(max_sessions >= 0, svc::ResultOutOfRange());
R_UNLESS(name[sizeof(name) - 1] == '\x00', svc::ResultOutOfRange());
if (max_sessions > 0) {
MESOSPHERE_LOG("Creating Named Port %s (max sessions = %d)\n", name, max_sessions);
/* Get the current handle table. */
auto &handle_table = GetCurrentProcess().GetHandleTable();
/* Create a new port. */
KPort *port = KPort::Create();
R_UNLESS(port != nullptr, svc::ResultOutOfResource());
/* Reserve a handle for the server port. */
R_TRY(handle_table.Reserve(out_server_handle));
auto reserve_guard = SCOPE_GUARD { handle_table.Unreserve(*out_server_handle); };
/* Initialize the new port. */
port->Initialize(max_sessions, false, 0);
/* Register the port. */
KPort::Register(port);
/* Register the handle in the table. */
handle_table.Register(*out_server_handle, std::addressof(port->GetServerPort()));
reserve_guard.Cancel();
auto register_guard = SCOPE_GUARD { handle_table.Remove(*out_server_handle); };
/* Create a new object name. */
R_TRY(KObjectName::NewFromName(std::addressof(port->GetClientPort()), name));
/* Perform resource cleanup. */
port->GetServerPort().Close();
port->GetClientPort().Close();
register_guard.Cancel();
} else /* if (max_sessions == 0) */ {
MESOSPHERE_LOG("Deleting Named Port %s\n", name);
/* Ensure that this else case is correct. */
MESOSPHERE_AUDIT(max_sessions == 0);
/* If we're closing, there's no server handle. */
*out_server_handle = ams::svc::InvalidHandle;
/* Delete the object. */
R_TRY(KObjectName::Delete<KClientPort>(name));
}
return ResultSuccess();
}
}
@@ -36,7 +90,7 @@ namespace ams::kern::svc {
}
Result ManageNamedPort64(ams::svc::Handle *out_server_handle, KUserPointer<const char *> name, int32_t max_sessions) {
MESOSPHERE_PANIC("Stubbed SvcManageNamedPort64 was called.");
return ManageNamedPort(out_server_handle, name, max_sessions);
}
Result ConnectToPort64(ams::svc::Handle *out_handle, ams::svc::Handle port) {
@@ -54,7 +108,7 @@ namespace ams::kern::svc {
}
Result ManageNamedPort64From32(ams::svc::Handle *out_server_handle, KUserPointer<const char *> name, int32_t max_sessions) {
MESOSPHERE_PANIC("Stubbed SvcManageNamedPort64From32 was called.");
return ManageNamedPort(out_server_handle, name, max_sessions);
}
Result ConnectToPort64From32(ams::svc::Handle *out_handle, ams::svc::Handle port) {

View File

@@ -21,6 +21,32 @@ namespace ams::kern::svc {
namespace {
Result GetProcessId(u64 *out_process_id, ams::svc::Handle handle) {
/* Get the object from the handle table. */
KScopedAutoObject obj = GetCurrentProcess().GetHandleTable().GetObject<KAutoObject>(handle);
R_UNLESS(obj.IsNotNull(), svc::ResultInvalidHandle());
/* Get the process from the object. */
KProcess *process = nullptr;
if (obj->IsDerivedFrom(KProcess::GetStaticTypeObj())) {
/* The object is a process, so we can use it directly. */
process = reinterpret_cast<KProcess *>(obj.GetPointerUnsafe());
} else if (obj->IsDerivedFrom(KThread::GetStaticTypeObj())) {
/* The object is a thread, so we want to use its parent. */
process = reinterpret_cast<KThread *>(obj.GetPointerUnsafe())->GetOwnerProcess();
} else if (obj->IsDerivedFrom(KDebug::GetStaticTypeObj())) {
/* The object is a debug, so we want to use the process it's attached to. */
MESOSPHERE_UNIMPLEMENTED();
}
/* Make sure the target process exists. */
R_UNLESS(process != nullptr, svc::ResultInvalidHandle());
/* Get the process id. */
*out_process_id = process->GetId();
return ResultSuccess();
}
}
@@ -32,7 +58,7 @@ namespace ams::kern::svc {
}
Result GetProcessId64(uint64_t *out_process_id, ams::svc::Handle process_handle) {
MESOSPHERE_PANIC("Stubbed SvcGetProcessId64 was called.");
return GetProcessId(out_process_id, process_handle);
}
Result GetProcessList64(int32_t *out_num_processes, KUserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {
@@ -62,7 +88,7 @@ namespace ams::kern::svc {
}
Result GetProcessId64From32(uint64_t *out_process_id, ams::svc::Handle process_handle) {
MESOSPHERE_PANIC("Stubbed SvcGetProcessId64From32 was called.");
return GetProcessId(out_process_id, process_handle);
}
Result GetProcessList64From32(int32_t *out_num_processes, KUserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {

View File

@@ -28,7 +28,7 @@ namespace ams::kern::svc {
/* ============================= 64 ABI ============================= */
void CallSecureMonitor64(ams::svc::lp64::SecureMonitorArguments *args) {
MESOSPHERE_PANIC("Stubbed SvcCallSecureMonitor64 was called.");
KSystemControl::CallSecureMonitorFromUser(args);
}
/* ============================= 64From32 ABI ============================= */

View File

@@ -15,7 +15,7 @@ include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -flto

View File

@@ -20,39 +20,49 @@
#include <vapours.hpp>
/* Libstratosphere-only utility. */
#include "stratosphere/util.hpp"
#include <stratosphere/util.hpp>
/* Sadly required shims. */
#include <stratosphere/svc/svc_stratosphere_shims.hpp>
/* Critical modules with no dependencies. */
#include "stratosphere/ams.hpp"
#include "stratosphere/os.hpp"
#include "stratosphere/dd.hpp"
#include "stratosphere/lmem.hpp"
#include <stratosphere/ams.hpp>
#include <stratosphere/os.hpp>
#include <stratosphere/dd.hpp>
#include <stratosphere/lmem.hpp>
#include <stratosphere/mem.hpp>
/* Lots of things depend on NCM, for Program IDs. */
#include "stratosphere/ncm.hpp"
/* Pull in all ID definitions from NCM. */
#include <stratosphere/ncm/ncm_ids.hpp>
/* At this point, just include the rest alphabetically. */
/* TODO: Figure out optimal order. */
#include "stratosphere/boot2.hpp"
#include "stratosphere/cfg.hpp"
#include "stratosphere/dmnt.hpp"
#include "stratosphere/fatal.hpp"
#include "stratosphere/hid.hpp"
#include "stratosphere/hos.hpp"
#include "stratosphere/kvdb.hpp"
#include "stratosphere/ldr.hpp"
#include "stratosphere/map.hpp"
#include "stratosphere/patcher.hpp"
#include "stratosphere/pm.hpp"
#include "stratosphere/reg.hpp"
#include "stratosphere/ro.hpp"
#include "stratosphere/settings.hpp"
#include "stratosphere/sf.hpp"
#include "stratosphere/sm.hpp"
#include "stratosphere/spl.hpp"
#include "stratosphere/updater.hpp"
#include <stratosphere/boot2.hpp>
#include <stratosphere/cfg.hpp>
#include <stratosphere/dmnt.hpp>
#include <stratosphere/erpt.hpp>
#include <stratosphere/fatal.hpp>
#include <stratosphere/hid.hpp>
#include <stratosphere/hos.hpp>
#include <stratosphere/kvdb.hpp>
#include <stratosphere/ldr.hpp>
#include <stratosphere/lr.hpp>
#include <stratosphere/map.hpp>
#include <stratosphere/ncm.hpp>
#include <stratosphere/nim.hpp>
#include <stratosphere/patcher.hpp>
#include <stratosphere/psc.hpp>
#include <stratosphere/pm.hpp>
#include <stratosphere/reg.hpp>
#include <stratosphere/ro.hpp>
#include <stratosphere/settings.hpp>
#include <stratosphere/sf.hpp>
#include <stratosphere/sm.hpp>
#include <stratosphere/spl.hpp>
#include <stratosphere/time.hpp>
#include <stratosphere/updater.hpp>
/* Include FS last. */
#include "stratosphere/fs.hpp"
#include "stratosphere/fssrv.hpp"
#include "stratosphere/fssystem.hpp"
#include <stratosphere/fs.hpp>
#include <stratosphere/fssrv.hpp>
#include <stratosphere/fssystem.hpp>

View File

@@ -83,12 +83,13 @@ namespace ams {
struct FatalErrorContext : sf::LargeData, sf::PrefersMapAliasTransferMode {
static constexpr size_t MaxStackTrace = 0x20;
static constexpr size_t MaxStackDumpSize = 0x100;
static constexpr size_t ThreadLocalSize = 0x100;
static constexpr size_t NumGprs = 29;
static constexpr uintptr_t StdAbortMagicAddress = 0x8;
static constexpr u64 StdAbortMagicValue = 0xA55AF00DDEADCAFEul;
static constexpr u32 StdAbortErrorDesc = 0xFFE;
static constexpr u32 DataAbortErrorDesc = 0x101;
static constexpr u32 Magic = util::FourCC<'A', 'F', 'E', '1'>::Code;
static constexpr u32 Magic = util::FourCC<'A', 'F', 'E', '2'>::Code;
u32 magic;
u32 error_desc;
@@ -113,10 +114,11 @@ namespace ams {
u64 stack_trace_size;
u64 stack_dump_size;
u64 stack_trace[MaxStackTrace];
u8 stack_dump[MaxStackDumpSize];
u8 stack_dump[MaxStackDumpSize];
u8 tls[ThreadLocalSize];
};
static_assert(sizeof(FatalErrorContext) == 0x350, "sizeof(FatalErrorContext)");
static_assert(sizeof(FatalErrorContext) == 0x450, "sizeof(FatalErrorContext)");
static_assert(std::is_pod<FatalErrorContext>::value, "FatalErrorContext");
#ifdef ATMOSPHERE_GIT_BRANCH

View File

@@ -15,8 +15,8 @@
*/
#pragma once
#include "../os/os_common_types.hpp"
#include "../ncm/ncm_types.hpp"
#include <stratosphere/os.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
namespace ams::cfg {

View File

@@ -15,9 +15,9 @@
*/
#pragma once
#include "../os/os_common_types.hpp"
#include "../ncm/ncm_types.hpp"
#include "../sf/sf_buffer_tags.hpp"
#include <stratosphere/os.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/sf/sf_buffer_tags.hpp>
namespace ams::dmnt::cheat {

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere/erpt/erpt_ids.autogen.hpp>
#include <stratosphere/erpt/erpt_types.hpp>
#include <stratosphere/erpt/erpt_multiple_category_context.hpp>
#include <stratosphere/erpt/sf/erpt_sf_i_context.hpp>
#include <stratosphere/erpt/sf/erpt_sf_i_session.hpp>
#include <stratosphere/erpt/srv/erpt_srv_types.hpp>
#include <stratosphere/erpt/srv/erpt_srv_api.hpp>

View File

@@ -0,0 +1,780 @@
/*
* Copyright (c) 2018-2020 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 <vapours.hpp>
/* NOTE: This file is auto-generated. */
/* Do not make edits to this file by hand. */
#define AMS_ERPT_FOREACH_FIELD_TYPE(HANDLER) \
HANDLER(FieldType_NumericU64, 0 ) \
HANDLER(FieldType_NumericU32, 1 ) \
HANDLER(FieldType_NumericI64, 2 ) \
HANDLER(FieldType_NumericI32, 3 ) \
HANDLER(FieldType_String, 4 ) \
HANDLER(FieldType_U8Array, 5 ) \
HANDLER(FieldType_U32Array, 6 ) \
HANDLER(FieldType_U64Array, 7 ) \
HANDLER(FieldType_I32Array, 8 ) \
HANDLER(FieldType_I64Array, 9 ) \
HANDLER(FieldType_Bool, 10) \
HANDLER(FieldType_NumericU16, 11) \
HANDLER(FieldType_NumericU8, 12) \
HANDLER(FieldType_NumericI16, 13) \
HANDLER(FieldType_NumericI8, 14) \
HANDLER(FieldType_I8Array, 15) \
#define AMS_ERPT_FOREACH_CATEGORY(HANDLER) \
HANDLER(Test, 0 ) \
HANDLER(ErrorInfo, 1 ) \
HANDLER(ConnectionStatusInfo, 2 ) \
HANDLER(NetworkInfo, 3 ) \
HANDLER(NXMacAddressInfo, 4 ) \
HANDLER(StealthNetworkInfo, 5 ) \
HANDLER(LimitHighCapacityInfo, 6 ) \
HANDLER(NATTypeInfo, 7 ) \
HANDLER(WirelessAPMacAddressInfo, 8 ) \
HANDLER(GlobalIPAddressInfo, 9 ) \
HANDLER(EnableWirelessInterfaceInfo, 10 ) \
HANDLER(EnableWifiInfo, 11 ) \
HANDLER(EnableBluetoothInfo, 12 ) \
HANDLER(EnableNFCInfo, 13 ) \
HANDLER(NintendoZoneSSIDListVersionInfo, 14 ) \
HANDLER(LANAdapterMacAddressInfo, 15 ) \
HANDLER(ApplicationInfo, 16 ) \
HANDLER(OccurrenceInfo, 17 ) \
HANDLER(ProductModelInfo, 18 ) \
HANDLER(CurrentLanguageInfo, 19 ) \
HANDLER(UseNetworkTimeProtocolInfo, 20 ) \
HANDLER(TimeZoneInfo, 21 ) \
HANDLER(ControllerFirmwareInfo, 22 ) \
HANDLER(VideoOutputInfo, 23 ) \
HANDLER(NANDFreeSpaceInfo, 24 ) \
HANDLER(SDCardFreeSpaceInfo, 25 ) \
HANDLER(ScreenBrightnessInfo, 26 ) \
HANDLER(AudioFormatInfo, 27 ) \
HANDLER(MuteOnHeadsetUnpluggedInfo, 28 ) \
HANDLER(NumUserRegisteredInfo, 29 ) \
HANDLER(DataDeletionInfo, 30 ) \
HANDLER(ControllerVibrationInfo, 31 ) \
HANDLER(LockScreenInfo, 32 ) \
HANDLER(InternalBatteryLotNumberInfo, 33 ) \
HANDLER(LeftControllerSerialNumberInfo, 34 ) \
HANDLER(RightControllerSerialNumberInfo, 35 ) \
HANDLER(NotificationInfo, 36 ) \
HANDLER(TVInfo, 37 ) \
HANDLER(SleepInfo, 38 ) \
HANDLER(ConnectionInfo, 39 ) \
HANDLER(NetworkErrorInfo, 40 ) \
HANDLER(FileAccessPathInfo, 41 ) \
HANDLER(GameCardCIDInfo, 42 ) \
HANDLER(NANDCIDInfo, 43 ) \
HANDLER(MicroSDCIDInfo, 44 ) \
HANDLER(NANDSpeedModeInfo, 45 ) \
HANDLER(MicroSDSpeedModeInfo, 46 ) \
HANDLER(GameCardSpeedModeInfo, 47 ) \
HANDLER(UserAccountInternalIDInfo, 48 ) \
HANDLER(NetworkServiceAccountInternalIDInfo, 49 ) \
HANDLER(NintendoAccountInternalIDInfo, 50 ) \
HANDLER(USB3AvailableInfo, 51 ) \
HANDLER(CallStackInfo, 52 ) \
HANDLER(SystemStartupLogInfo, 53 ) \
HANDLER(RegionSettingInfo, 54 ) \
HANDLER(NintendoZoneConnectedInfo, 55 ) \
HANDLER(ForceSleepInfo, 56 ) \
HANDLER(ChargerInfo, 57 ) \
HANDLER(RadioStrengthInfo, 58 ) \
HANDLER(ErrorInfoAuto, 59 ) \
HANDLER(AccessPointInfo, 60 ) \
HANDLER(ErrorInfoDefaults, 61 ) \
HANDLER(SystemPowerStateInfo, 62 ) \
HANDLER(PerformanceInfo, 63 ) \
HANDLER(ThrottlingInfo, 64 ) \
HANDLER(GameCardErrorInfo, 65 ) \
HANDLER(EdidInfo, 66 ) \
HANDLER(ThermalInfo, 67 ) \
HANDLER(CradleFirmwareInfo, 68 ) \
HANDLER(RunningApplicationInfo, 69 ) \
HANDLER(RunningAppletInfo, 70 ) \
HANDLER(FocusedAppletHistoryInfo, 71 ) \
HANDLER(CompositorInfo, 72 ) \
HANDLER(BatteryChargeInfo, 73 ) \
HANDLER(NANDExtendedCsd, 74 ) \
HANDLER(NANDPatrolInfo, 75 ) \
HANDLER(NANDErrorInfo, 76 ) \
HANDLER(NANDDriverLog, 77 ) \
HANDLER(SdCardSizeSpec, 78 ) \
HANDLER(SdCardErrorInfo, 79 ) \
HANDLER(SdCardDriverLog , 80 ) \
HANDLER(FsProxyErrorInfo, 81 ) \
HANDLER(SystemAppletSceneInfo, 82 ) \
HANDLER(VideoInfo, 83 ) \
HANDLER(GpuErrorInfo, 84 ) \
HANDLER(PowerClockInfo, 85 ) \
HANDLER(AdspErrorInfo, 86 ) \
HANDLER(NvDispDeviceInfo, 87 ) \
HANDLER(NvDispDcWindowInfo, 88 ) \
HANDLER(NvDispDpModeInfo, 89 ) \
HANDLER(NvDispDpLinkSpec, 90 ) \
HANDLER(NvDispDpLinkStatus, 91 ) \
HANDLER(NvDispDpHdcpInfo, 92 ) \
HANDLER(NvDispDpAuxCecInfo, 93 ) \
HANDLER(NvDispDcInfo, 94 ) \
HANDLER(NvDispDsiInfo, 95 ) \
HANDLER(NvDispErrIDInfo, 96 ) \
HANDLER(SdCardMountInfo, 97 ) \
HANDLER(RetailInteractiveDisplayInfo, 98 ) \
HANDLER(CompositorStateInfo, 99 ) \
HANDLER(CompositorLayerInfo, 100) \
HANDLER(CompositorDisplayInfo, 101) \
HANDLER(CompositorHWCInfo, 102) \
HANDLER(MonitorCapability, 103) \
HANDLER(ErrorReportSharePermissionInfo, 104) \
HANDLER(MultimediaInfo, 105) \
HANDLER(ConnectedControllerInfo, 106) \
HANDLER(FsMemoryInfo, 107) \
HANDLER(UserClockContextInfo, 108) \
HANDLER(NetworkClockContextInfo, 109) \
HANDLER(AcpGeneralSettingsInfo, 110) \
HANDLER(AcpPlayLogSettingsInfo, 111) \
HANDLER(AcpAocSettingsInfo, 112) \
HANDLER(AcpBcatSettingsInfo, 113) \
HANDLER(AcpStorageSettingsInfo, 114) \
HANDLER(AcpRatingSettingsInfo, 115) \
HANDLER(MonitorSettings, 116) \
HANDLER(RebootlessSystemUpdateVersionInfo, 117) \
HANDLER(NifmConnectionTestInfo, 118) \
HANDLER(PcieLoggedStateInfo, 119) \
HANDLER(NetworkSecurityCertificateInfo, 120) \
HANDLER(AcpNeighborDetectionInfo, 121) \
HANDLER(GpuCrashInfo, 122) \
HANDLER(UsbStateInfo, 123) \
HANDLER(NvHostErrInfo, 124) \
HANDLER(RunningUlaInfo, 125) \
#define AMS_ERPT_FOREACH_FIELD(HANDLER) \
HANDLER(TestU64, 0, Test, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(TestU32, 1, Test, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(TestI64, 2, Test, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(TestI32, 3, Test, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(TestString, 4, Test, FieldType_String, FieldFlag_None ) \
HANDLER(TestU8Array, 5, Test, FieldType_U8Array, FieldFlag_None ) \
HANDLER(TestU32Array, 6, Test, FieldType_U32Array, FieldFlag_None ) \
HANDLER(TestU64Array, 7, Test, FieldType_U64Array, FieldFlag_None ) \
HANDLER(TestI32Array, 8, Test, FieldType_I32Array, FieldFlag_None ) \
HANDLER(TestI64Array, 9, Test, FieldType_I64Array, FieldFlag_None ) \
HANDLER(ErrorCode, 10, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ErrorDescription, 11, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(OccurrenceTimestamp, 12, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ReportIdentifier, 13, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
HANDLER(ConnectionStatus, 14, ConnectionStatusInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AccessPointSSID, 15, AccessPointInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AccessPointSecurityType, 16, AccessPointInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RadioStrength, 17, RadioStrengthInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NXMacAddress, 18, NXMacAddressInfo, FieldType_String, FieldFlag_None ) \
HANDLER(IPAddressAcquisitionMethod, 19, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(CurrentIPAddress, 20, NetworkInfo, FieldType_String, FieldFlag_None ) \
HANDLER(SubnetMask, 21, NetworkInfo, FieldType_String, FieldFlag_None ) \
HANDLER(GatewayIPAddress, 22, NetworkInfo, FieldType_String, FieldFlag_None ) \
HANDLER(DNSType, 23, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PriorityDNSIPAddress, 24, NetworkInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AlternateDNSIPAddress, 25, NetworkInfo, FieldType_String, FieldFlag_None ) \
HANDLER(UseProxyFlag, 26, NetworkInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ProxyIPAddress, 27, NetworkInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ProxyPort, 28, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(ProxyAutoAuthenticateFlag, 29, NetworkInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(MTU, 30, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(ConnectAutomaticallyFlag, 31, NetworkInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(UseStealthNetworkFlag, 32, StealthNetworkInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(LimitHighCapacityFlag, 33, LimitHighCapacityInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NATType, 34, NATTypeInfo, FieldType_String, FieldFlag_None ) \
HANDLER(WirelessAPMacAddress, 35, WirelessAPMacAddressInfo, FieldType_String, FieldFlag_None ) \
HANDLER(GlobalIPAddress, 36, GlobalIPAddressInfo, FieldType_String, FieldFlag_None ) \
HANDLER(EnableWirelessInterfaceFlag, 37, EnableWirelessInterfaceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableWifiFlag, 38, EnableWifiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableBluetoothFlag, 39, EnableBluetoothInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(EnableNFCFlag, 40, EnableNFCInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NintendoZoneSSIDListVersion, 41, NintendoZoneSSIDListVersionInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LANAdapterMacAddress, 42, LANAdapterMacAddressInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ApplicationID, 43, ApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ApplicationTitle, 44, ApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ApplicationVersion, 45, ApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ApplicationStorageLocation, 46, ApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(DownloadContentType, 47, OccurrenceInfo, FieldType_String, FieldFlag_None ) \
HANDLER(InstallContentType, 48, OccurrenceInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ConsoleStartingUpFlag, 49, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(SystemStartingUpFlag, 50, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ConsoleFirstInitFlag, 51, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(HomeMenuScreenDisplayedFlag, 52, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(DataManagementScreenDisplayedFlag, 53, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ConnectionTestingFlag, 54, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ApplicationRunningFlag, 55, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(DataCorruptionDetectedFlag, 56, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ProductModel, 57, ProductModelInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CurrentLanguage, 58, CurrentLanguageInfo, FieldType_String, FieldFlag_None ) \
HANDLER(UseNetworkTimeProtocolFlag, 59, UseNetworkTimeProtocolInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TimeZone, 60, TimeZoneInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ControllerFirmware, 61, ControllerFirmwareInfo, FieldType_String, FieldFlag_None ) \
HANDLER(VideoOutputSetting, 62, VideoOutputInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NANDFreeSpace, 63, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SDCardFreeSpace, 64, SDCardFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SerialNumber, 65, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
HANDLER(OsVersion, 66, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
HANDLER(ScreenBrightnessAutoAdjustFlag, 67, ScreenBrightnessInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(HdmiAudioOutputMode, 68, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
HANDLER(SpeakerAudioOutputMode, 69, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
HANDLER(HeadphoneAudioOutputMode, 70, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
HANDLER(MuteOnHeadsetUnpluggedFlag, 71, MuteOnHeadsetUnpluggedInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NumUserRegistered, 72, NumUserRegisteredInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(StorageAutoOrganizeFlag, 73, DataDeletionInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ControllerVibrationVolume, 74, ControllerVibrationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LockScreenFlag, 75, LockScreenInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(InternalBatteryLotNumber, 76, InternalBatteryLotNumberInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LeftControllerSerialNumber, 77, LeftControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RightControllerSerialNumber, 78, RightControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NotifyInGameDownloadCompletionFlag, 79, NotificationInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NotificationSoundFlag, 80, NotificationInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TVResolutionSetting, 81, TVInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RGBRangeSetting, 82, TVInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ReduceScreenBurnFlag, 83, TVInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TVAllowsCecFlag, 84, TVInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(HandheldModeTimeToScreenSleep, 85, SleepInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ConsoleModeTimeToScreenSleep, 86, SleepInfo, FieldType_String, FieldFlag_None ) \
HANDLER(StopAutoSleepDuringContentPlayFlag, 87, SleepInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(LastConnectionTestDownloadSpeed, 88, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(LastConnectionTestUploadSpeed, 89, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(DEPRECATED_ServerFQDN, 90, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(HTTPRequestContents, 91, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(HTTPRequestResponseContents, 92, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(EdgeServerIPAddress, 93, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CDNContentPath, 94, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(FileAccessPath, 95, FileAccessPathInfo, FieldType_String, FieldFlag_None ) \
HANDLER(GameCardCID, 96, GameCardCIDInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(NANDCID, 97, NANDCIDInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(MicroSDCID, 98, MicroSDCIDInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(NANDSpeedMode, 99, NANDSpeedModeInfo, FieldType_String, FieldFlag_None ) \
HANDLER(MicroSDSpeedMode, 100, MicroSDSpeedModeInfo, FieldType_String, FieldFlag_None ) \
HANDLER(GameCardSpeedMode, 101, GameCardSpeedModeInfo, FieldType_String, FieldFlag_None ) \
HANDLER(UserAccountInternalID, 102, UserAccountInternalIDInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NetworkServiceAccountInternalID, 103, NetworkServiceAccountInternalIDInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NintendoAccountInternalID, 104, NintendoAccountInternalIDInfo, FieldType_String, FieldFlag_None ) \
HANDLER(USB3AvailableFlag, 105, USB3AvailableInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(CallStack, 106, CallStackInfo, FieldType_String, FieldFlag_None ) \
HANDLER(SystemStartupLog, 107, SystemStartupLogInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RegionSetting, 108, RegionSettingInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NintendoZoneConnectedFlag, 109, NintendoZoneConnectedInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ForcedSleepHighTemperatureReading, 110, ForceSleepInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(ForcedSleepFanSpeedReading, 111, ForceSleepInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(ForcedSleepHWInfo, 112, ForceSleepInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AbnormalPowerStateInfo, 113, ChargerInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(ScreenBrightnessLevel, 114, ScreenBrightnessInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ProgramId, 115, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AbortFlag, 116, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ReportVisibilityFlag, 117, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
HANDLER(FatalFlag, 118, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(OccurrenceTimestampNet, 119, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ResultBacktrace, 120, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(GeneralRegisterAarch32, 121, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(StackBacktrace32, 122, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(ExceptionInfoAarch32, 123, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(GeneralRegisterAarch64, 124, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(ExceptionInfoAarch64, 125, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(StackBacktrace64, 126, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(RegisterSetFlag32, 127, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(RegisterSetFlag64, 128, ErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(ProgramMappedAddr32, 129, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(ProgramMappedAddr64, 130, ErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(AbortType, 131, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PrivateOsVersion, 132, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
HANDLER(CurrentSystemPowerState, 133, SystemPowerStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PreviousSystemPowerState, 134, SystemPowerStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(DestinationSystemPowerState, 135, SystemPowerStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PscTransitionCurrentState, 136, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PscTransitionPreviousState, 137, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PscInitializedList, 138, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(PscCurrentPmStateList, 139, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(PscNextPmStateList, 140, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(PerformanceMode, 141, PerformanceInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(PerformanceConfiguration, 142, PerformanceInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(Throttled, 143, ThrottlingInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ThrottlingDuration, 144, ThrottlingInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ThrottlingTimestamp, 145, ThrottlingInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(GameCardCrcErrorCount, 146, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardAsicCrcErrorCount, 147, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardRefreshCount, 148, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardReadRetryCount, 149, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(EdidBlock, 150, EdidInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(EdidExtensionBlock, 151, EdidInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(CreateProcessFailureFlag, 152, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(TemperaturePcb, 153, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(TemperatureSoc, 154, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(CurrentFanDuty, 155, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(LastDvfsThresholdTripped, 156, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(CradlePdcHFwVersion, 157, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(CradlePdcAFwVersion, 158, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(CradleMcuFwVersion, 159, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(CradleDp2HdmiFwVersion, 160, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(RunningApplicationId, 161, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningApplicationTitle, 162, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningApplicationVersion, 163, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningApplicationStorageLocation, 164, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningAppletList, 165, RunningAppletInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(FocusedAppletHistory, 166, FocusedAppletHistoryInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(CompositorState, 167, CompositorStateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CompositorLayerState, 168, CompositorLayerInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CompositorDisplayState, 169, CompositorDisplayInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CompositorHWCState, 170, CompositorHWCInfo, FieldType_String, FieldFlag_None ) \
HANDLER(InputCurrentLimit, 171, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(BoostModeCurrentLimit, 172, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FastChargeCurrentLimit, 173, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(ChargeVoltageLimit, 174, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(ChargeConfiguration, 175, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(HizMode, 176, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ChargeEnabled, 177, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(PowerSupplyPath, 178, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(BatteryTemperature, 179, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(BatteryChargePercent, 180, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(BatteryChargeVoltage, 181, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(BatteryAge, 182, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(PowerRole, 183, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(PowerSupplyType, 184, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(PowerSupplyVoltage, 185, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(PowerSupplyCurrent, 186, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FastBatteryChargingEnabled, 187, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ControllerPowerSupplyAcquired, 188, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(OtgRequested, 189, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NANDPreEolInfo, 190, NANDExtendedCsd, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDDeviceLifeTimeEstTypA, 191, NANDExtendedCsd, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDDeviceLifeTimeEstTypB, 192, NANDExtendedCsd, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDPatrolCount, 193, NANDPatrolInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDNumActivationFailures, 194, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDNumActivationErrorCorrections, 195, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDNumReadWriteFailures, 196, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDNumReadWriteErrorCorrections, 197, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NANDErrorLog, 198, NANDDriverLog, FieldType_String, FieldFlag_None ) \
HANDLER(SdCardUserAreaSize, 199, SdCardSizeSpec, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SdCardProtectedAreaSize, 200, SdCardSizeSpec, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SdCardNumActivationFailures, 201, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(SdCardNumActivationErrorCorrections, 202, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(SdCardNumReadWriteFailures, 203, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(SdCardNumReadWriteErrorCorrections, 204, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(SdCardErrorLog, 205, SdCardDriverLog , FieldType_String, FieldFlag_None ) \
HANDLER(EncryptionKey, 206, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(EncryptedExceptionInfo, 207, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(GameCardTimeoutRetryErrorCount, 208, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsRemountForDataCorruptCount, 209, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsRemountForDataCorruptRetryOutCount, 210, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardInsertionCount, 211, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardRemovalCount, 212, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardAsicInitializeCount, 213, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(TestU16, 214, Test, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(TestU8, 215, Test, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(TestI16, 216, Test, FieldType_NumericI16, FieldFlag_None ) \
HANDLER(TestI8, 217, Test, FieldType_NumericI8, FieldFlag_None ) \
HANDLER(SystemAppletScene, 218, SystemAppletSceneInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(CodecType, 219, VideoInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(DecodeBuffers, 220, VideoInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FrameWidth, 221, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FrameHeight, 222, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(ColorPrimaries, 223, VideoInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(TransferCharacteristics, 224, VideoInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(MatrixCoefficients, 225, VideoInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(DisplayWidth, 226, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(DisplayHeight, 227, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(DARWidth, 228, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(DARHeight, 229, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(ColorFormat, 230, VideoInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(ColorSpace, 231, VideoInfo, FieldType_String, FieldFlag_None ) \
HANDLER(SurfaceLayout, 232, VideoInfo, FieldType_String, FieldFlag_None ) \
HANDLER(BitStream, 233, VideoInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(VideoDecState, 234, VideoInfo, FieldType_String, FieldFlag_None ) \
HANDLER(GpuErrorChannelId, 235, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorAruId, 236, GpuErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(GpuErrorType, 237, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorFaultInfo, 238, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorWriteAccess, 239, GpuErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(GpuErrorFaultAddress, 240, GpuErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(GpuErrorFaultUnit, 241, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorFaultType, 242, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorHwContextPointer, 243, GpuErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(GpuErrorContextStatus, 244, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorPbdmaIntr, 245, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorPbdmaErrorType, 246, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorPbdmaHeaderShadow, 247, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorPbdmaHeader, 248, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorPbdmaGpShadow0, 249, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuErrorPbdmaGpShadow1, 250, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AccessPointChannel, 251, AccessPointInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(ThreadName, 252, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AdspExceptionRegisters, 253, AdspErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(AdspExceptionSpsr, 254, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AdspExceptionProgramCounter, 255, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AdspExceptionLinkRegister, 256, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AdspExceptionStackPointer, 257, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AdspExceptionArmModeRegisters, 258, AdspErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(AdspExceptionStackAddress, 259, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AdspExceptionStackDump, 260, AdspErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(AdspExceptionReason, 261, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(OscillatorClock, 262, PowerClockInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(CpuDvfsTableClocks, 263, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(CpuDvfsTableVoltages, 264, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(GpuDvfsTableClocks, 265, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(GpuDvfsTableVoltages, 266, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(EmcDvfsTableClocks, 267, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(EmcDvfsTableVoltages, 268, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(ModuleClockFrequencies, 269, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(ModuleClockEnableFlags, 270, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ModulePowerEnableFlags, 271, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ModuleResetAssertFlags, 272, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ModuleMinimumVoltageClockRates, 273, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(PowerDomainEnableFlags, 274, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(PowerDomainVoltages, 275, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(AccessPointRssi, 276, RadioStrengthInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FuseInfo, 277, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(VideoLog, 278, VideoInfo, FieldType_String, FieldFlag_None ) \
HANDLER(GameCardDeviceId, 279, GameCardCIDInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(GameCardAsicReinitializeCount, 280, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(GameCardAsicReinitializeFailureCount, 281, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(GameCardAsicReinitializeFailureDetail, 282, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(GameCardRefreshSuccessCount, 283, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(GameCardAwakenCount, 284, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardAwakenFailureCount, 285, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(GameCardReadCountFromInsert, 286, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardReadCountFromAwaken, 287, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardLastReadErrorPageAddress, 288, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GameCardLastReadErrorPageCount, 289, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AppletManagerContextTrace, 290, ErrorInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(NvDispIsRegistered, 291, NvDispDeviceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispIsSuspend, 292, NvDispDeviceInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDC0SurfaceNum, 293, NvDispDeviceInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(NvDispDC1SurfaceNum, 294, NvDispDeviceInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(NvDispWindowSrcRectX, 295, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowSrcRectY, 296, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowSrcRectWidth, 297, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowSrcRectHeight, 298, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowDstRectX, 299, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowDstRectY, 300, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowDstRectWidth, 301, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowDstRectHeight, 302, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowIndex, 303, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowBlendOperation, 304, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowAlphaOperation, 305, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowDepth, 306, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowAlpha, 307, NvDispDcWindowInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispWindowHFilter, 308, NvDispDcWindowInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispWindowVFilter, 309, NvDispDcWindowInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispWindowOptions, 310, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispWindowSyncPointId, 311, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPSorPower, 312, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPClkType, 313, NvDispDpModeInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispDPEnable, 314, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPState, 315, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPEdid, 316, NvDispDpModeInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(NvDispDPEdidSize, 317, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPEdidExtSize, 318, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPFakeMode, 319, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPModeNumber, 320, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPPlugInOut, 321, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPAuxIntHandler, 322, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPForceMaxLinkBW, 323, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPIsConnected, 324, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkValid, 325, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkMaxBW, 326, NvDispDpLinkSpec, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispDPLinkMaxLaneCount, 327, NvDispDpLinkSpec, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispDPLinkDownSpread, 328, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkSupportEnhancedFraming, 329, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkBpp, 330, NvDispDpLinkSpec, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkScaramberCap, 331, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkBW, 332, NvDispDpLinkStatus, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispDPLinkLaneCount, 333, NvDispDpLinkStatus, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispDPLinkEnhancedFraming, 334, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkScrambleEnable, 335, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkActivePolarity, 336, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkActiveCount, 337, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkTUSize, 338, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkActiveFrac, 339, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkWatermark, 340, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkHBlank, 341, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkVBlank, 342, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDPLinkOnlyEnhancedFraming, 343, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkOnlyEdpCap, 344, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkSupportFastLT, 345, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkLTDataValid, 346, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkTsp3Support, 347, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDPLinkAuxInterval, 348, NvDispDpLinkStatus, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispHdcpCreated, 349, NvDispDpHdcpInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispHdcpUserRequest, 350, NvDispDpHdcpInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispHdcpPlugged, 351, NvDispDpHdcpInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispHdcpState, 352, NvDispDpHdcpInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispHdcpFailCount, 353, NvDispDpHdcpInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(NvDispHdcpHdcp22, 354, NvDispDpHdcpInfo, FieldType_NumericI8, FieldFlag_None ) \
HANDLER(NvDispHdcpMaxRetry, 355, NvDispDpHdcpInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispHdcpHpd, 356, NvDispDpHdcpInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispHdcpRepeater, 357, NvDispDpHdcpInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispCecRxBuf, 358, NvDispDpAuxCecInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(NvDispCecRxLength, 359, NvDispDpAuxCecInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(NvDispCecTxBuf, 360, NvDispDpAuxCecInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(NvDispCecTxLength, 361, NvDispDpAuxCecInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(NvDispCecTxRet, 362, NvDispDpAuxCecInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(NvDispCecState, 363, NvDispDpAuxCecInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispCecTxInfo, 364, NvDispDpAuxCecInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispCecRxInfo, 365, NvDispDpAuxCecInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispDCIndex, 366, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDCInitialize, 367, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDCClock, 368, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDCFrequency, 369, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDCFailed, 370, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDCModeWidth, 371, NvDispDcInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(NvDispDCModeHeight, 372, NvDispDcInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(NvDispDCModeBpp, 373, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDCPanelFrequency, 374, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDCWinDirty, 375, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDCWinEnable, 376, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDCVrr, 377, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDCPanelInitialize, 378, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDsiDataFormat, 379, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiVideoMode, 380, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiRefreshRate, 381, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiLpCmdModeFrequency, 382, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiHsCmdModeFrequency, 383, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiPanelResetTimeout, 384, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiPhyFrequency, 385, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiFrequency, 386, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDsiInstance, 387, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDcDsiHostCtrlEnable, 388, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDcDsiInit, 389, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDcDsiEnable, 390, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDcDsiHsMode, 391, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDcDsiVendorId, 392, NvDispDsiInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(NvDispDcDsiLcdVendorNum, 393, NvDispDsiInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(NvDispDcDsiHsClockControl, 394, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDcDsiEnableHsClockInLpMode, 395, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDcDsiTeFrameUpdate, 396, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispDcDsiGangedType, 397, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispDcDsiHbpInPktSeq, 398, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NvDispErrID, 399, NvDispErrIDInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispErrData0, 400, NvDispErrIDInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvDispErrData1, 401, NvDispErrIDInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(SdCardMountStatus, 402, SdCardMountInfo, FieldType_String, FieldFlag_None ) \
HANDLER(SdCardMountUnexpectedResult, 403, SdCardMountInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NANDTotalSize, 404, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SdCardTotalSize, 405, SDCardFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(ElapsedTimeSinceInitialLaunch, 406, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ElapsedTimeSincePowerOn, 407, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ElapsedTimeSinceLastAwake, 408, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(OccurrenceTick, 409, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(RetailInteractiveDisplayFlag, 410, RetailInteractiveDisplayInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(FatFsError, 411, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FatFsExtraError, 412, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FatFsErrorDrive, 413, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(FatFsErrorName, 414, FsProxyErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(MonitorManufactureCode, 415, MonitorCapability, FieldType_String, FieldFlag_None ) \
HANDLER(MonitorProductCode, 416, MonitorCapability, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(MonitorSerialNumber, 417, MonitorCapability, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(MonitorManufactureYear, 418, MonitorCapability, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(PhysicalAddress, 419, MonitorCapability, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(Is4k60Hz, 420, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
HANDLER(Is4k30Hz, 421, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
HANDLER(Is1080P60Hz, 422, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
HANDLER(Is720P60Hz, 423, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
HANDLER(PcmChannelMax, 424, MonitorCapability, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(CrashReportHash, 425, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ErrorReportSharePermission, 426, ErrorReportSharePermissionInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(VideoCodecTypeEnum, 427, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(VideoBitRate, 428, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(VideoFrameRate, 429, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(VideoWidth, 430, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(VideoHeight, 431, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(AudioCodecTypeEnum, 432, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(AudioSampleRate, 433, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(AudioChannelCount, 434, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(AudioBitRate, 435, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(MultimediaContainerType, 436, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(MultimediaProfileType, 437, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(MultimediaLevelType, 438, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(MultimediaCacheSizeEnum, 439, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(MultimediaErrorStatusEnum, 440, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(MultimediaErrorLog, 441, MultimediaInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ServerFqdn, 442, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ServerIpAddress, 443, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(TestStringEncrypt, 444, Test, FieldType_String, FieldFlag_Encrypt) \
HANDLER(TestU8ArrayEncrypt, 445, Test, FieldType_U8Array, FieldFlag_Encrypt) \
HANDLER(TestU32ArrayEncrypt, 446, Test, FieldType_U32Array, FieldFlag_Encrypt) \
HANDLER(TestU64ArrayEncrypt, 447, Test, FieldType_U64Array, FieldFlag_Encrypt) \
HANDLER(TestI32ArrayEncrypt, 448, Test, FieldType_I32Array, FieldFlag_Encrypt) \
HANDLER(TestI64ArrayEncrypt, 449, Test, FieldType_I64Array, FieldFlag_Encrypt) \
HANDLER(CipherKey, 450, ErrorInfoAuto, FieldType_U8Array, FieldFlag_None ) \
HANDLER(FileSystemPath, 451, ErrorInfo, FieldType_String, FieldFlag_Encrypt) \
HANDLER(WebMediaPlayerOpenUrl, 452, ErrorInfo, FieldType_String, FieldFlag_Encrypt) \
HANDLER(WebMediaPlayerLastSocketErrors, 453, ErrorInfo, FieldType_I32Array, FieldFlag_None ) \
HANDLER(UnknownControllerCount, 454, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AttachedControllerCount, 455, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(BluetoothControllerCount, 456, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(UsbControllerCount, 457, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(ControllerTypeList, 458, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ControllerInterfaceList, 459, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(ControllerStyleList, 460, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(FsPooledBufferPeakFreeSize, 461, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsPooledBufferRetriedCount, 462, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsPooledBufferReduceAllocationCount, 463, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsBufferManagerPeakFreeSize, 464, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsBufferManagerRetriedCount, 465, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsExpHeapPeakFreeSize, 466, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsBufferPoolPeakFreeSize, 467, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsPatrolReadAllocateBufferSuccessCount, 468, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(FsPatrolReadAllocateBufferFailureCount, 469, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SteadyClockInternalOffset, 470, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SteadyClockCurrentTimePointValue, 471, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(UserClockContextOffset, 472, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(UserClockContextTimeStampValue, 473, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(NetworkClockContextOffset, 474, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(NetworkClockContextTimeStampValue, 475, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(SystemAbortFlag, 476, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(ApplicationAbortFlag, 477, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(NifmErrorCode, 478, ConnectionStatusInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LcsApplicationId, 479, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(LcsContentMetaKeyIdList, 480, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(LcsContentMetaKeyVersionList, 481, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(LcsContentMetaKeyTypeList, 482, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(LcsContentMetaKeyInstallTypeList, 483, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(LcsSenderFlag, 484, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(LcsApplicationRequestFlag, 485, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(LcsHasExFatDriverFlag, 486, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(LcsIpAddress, 487, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AcpStartupUserAccount, 488, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpAocRegistrationType, 489, AcpAocSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpAttributeFlag, 490, AcpGeneralSettingsInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AcpSupportedLanguageFlag, 491, AcpGeneralSettingsInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AcpParentalControlFlag, 492, AcpGeneralSettingsInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(AcpScreenShot, 493, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpVideoCapture, 494, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpDataLossConfirmation, 495, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpPlayLogPolicy, 496, AcpPlayLogSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpPresenceGroupId, 497, AcpGeneralSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(AcpRatingAge, 498, AcpRatingSettingsInfo, FieldType_I8Array, FieldFlag_None ) \
HANDLER(AcpAocBaseId, 499, AcpAocSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(AcpSaveDataOwnerId, 500, AcpStorageSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(AcpUserAccountSaveDataSize, 501, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpUserAccountSaveDataJournalSize, 502, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpDeviceSaveDataSize, 503, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpDeviceSaveDataJournalSize, 504, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpBcatDeliveryCacheStorageSize, 505, AcpBcatSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpApplicationErrorCodeCategory, 506, AcpGeneralSettingsInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AcpLocalCommunicationId, 507, AcpGeneralSettingsInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(AcpLogoType, 508, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpLogoHandling, 509, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpRuntimeAocInstall, 510, AcpAocSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpCrashReport, 511, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpHdcp, 512, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpSeedForPseudoDeviceId, 513, AcpGeneralSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(AcpBcatPassphrase, 514, AcpBcatSettingsInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AcpUserAccountSaveDataSizeMax, 515, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpUserAccountSaveDataJournalSizeMax, 516, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpDeviceSaveDataSizeMax, 517, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpDeviceSaveDataJournalSizeMax, 518, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpTemporaryStorageSize, 519, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpCacheStorageSize, 520, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpCacheStorageJournalSize, 521, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpCacheStorageDataAndJournalSizeMax, 522, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpCacheStorageIndexMax, 523, AcpStorageSettingsInfo, FieldType_NumericI16, FieldFlag_None ) \
HANDLER(AcpPlayLogQueryableApplicationId, 524, AcpPlayLogSettingsInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(AcpPlayLogQueryCapability, 525, AcpPlayLogSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(AcpRepairFlag, 526, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(RunningApplicationPatchStorageLocation, 527, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningApplicationVersionNumber, 528, RunningApplicationInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsRecoveredByInvalidateCacheCount, 529, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsSaveDataIndexCount, 530, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(FsBufferManagerPeakTotalAllocatableSize, 531, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(MonitorCurrentWidth, 532, MonitorSettings, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(MonitorCurrentHeight, 533, MonitorSettings, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(MonitorCurrentRefreshRate, 534, MonitorSettings, FieldType_String, FieldFlag_None ) \
HANDLER(RebootlessSystemUpdateVersion, 535, RebootlessSystemUpdateVersionInfo, FieldType_String, FieldFlag_None ) \
HANDLER(EncryptedExceptionInfo1, 536, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(EncryptedExceptionInfo2, 537, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(EncryptedExceptionInfo3, 538, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(EncryptedDyingMessage, 539, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(DramId, 540, PowerClockInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NifmConnectionTestRedirectUrl, 541, NifmConnectionTestInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AcpRequiredNetworkServiceLicenseOnLaunchFlag, 542, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(PciePort0Flags, 543, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PciePort0Speed, 544, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(PciePort0ResetTimeInUs, 545, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PciePort0IrqCount, 546, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PciePort0Statistics, 547, PcieLoggedStateInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(PciePort1Flags, 548, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PciePort1Speed, 549, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(PciePort1ResetTimeInUs, 550, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PciePort1IrqCount, 551, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(PciePort1Statistics, 552, PcieLoggedStateInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(PcieFunction0VendorId, 553, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(PcieFunction0DeviceId, 554, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(PcieFunction0PmState, 555, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(PcieFunction0IsAcquired, 556, PcieLoggedStateInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(PcieFunction1VendorId, 557, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(PcieFunction1DeviceId, 558, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(PcieFunction1PmState, 559, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(PcieFunction1IsAcquired, 560, PcieLoggedStateInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(PcieGlobalRootComplexStatistics, 561, PcieLoggedStateInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(PciePllResistorCalibrationValue, 562, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(CertificateRequestedHostName, 563, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CertificateCommonName, 564, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(CertificateSANCount, 565, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(CertificateSANs, 566, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(FsBufferPoolMaxAllocateSize, 567, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(CertificateIssuerName, 568, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ApplicationAliveTime, 569, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ApplicationInFocusTime, 570, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ApplicationOutOfFocusTime, 571, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(ApplicationBackgroundFocusTime, 572, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
HANDLER(AcpUserAccountSwitchLock, 573, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(USB3HostAvailableFlag, 574, USB3AvailableInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(USB3DeviceAvailableFlag, 575, USB3AvailableInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(AcpNeighborDetectionClientConfigurationSendDataId, 576, AcpNeighborDetectionInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(AcpNeighborDetectionClientConfigurationReceivableDataIds, 577, AcpNeighborDetectionInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(AcpStartupUserAccountOptionFlag, 578, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(ServerErrorCode, 579, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(AppletManagerMetaLogTrace, 580, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
HANDLER(ServerCertificateSerialNumber, 581, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ServerCertificatePublicKeyAlgorithm, 582, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ServerCertificateSignatureAlgorithm, 583, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(ServerCertificateNotBefore, 584, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(ServerCertificateNotAfter, 585, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(CertificateAlgorithmInfoBits, 586, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(TlsConnectionPeerIpAddress, 587, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
HANDLER(TlsConnectionLastHandshakeState, 588, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(TlsConnectionInfoBits, 589, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SslStateBits, 590, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SslProcessInfoBits, 591, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(SslProcessHeapSize, 592, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(SslBaseErrorCode, 593, NetworkSecurityCertificateInfo, FieldType_NumericI32, FieldFlag_None ) \
HANDLER(GpuCrashDumpSize, 594, GpuCrashInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(GpuCrashDump, 595, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(RunningApplicationProgramIndex, 596, RunningApplicationInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(UsbTopology, 597, UsbStateInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(AkamaiReferenceId, 598, ErrorInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NvHostErrID, 599, NvHostErrInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(NvHostErrDataArrayU32, 600, NvHostErrInfo, FieldType_U32Array, FieldFlag_None ) \
HANDLER(HasSyslogFlag, 601, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
HANDLER(AcpRuntimeParameterDelivery, 602, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(PlatformRegion, 603, RegionSettingInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningUlaApplicationId, 604, RunningUlaInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningUlaAppletId, 605, RunningUlaInfo, FieldType_NumericU8, FieldFlag_None ) \
HANDLER(RunningUlaVersion, 606, RunningUlaInfo, FieldType_NumericU32, FieldFlag_None ) \
HANDLER(RunningUlaApplicationStorageLocation, 607, RunningUlaInfo, FieldType_String, FieldFlag_None ) \
HANDLER(RunningUlaPatchStorageLocation, 608, RunningUlaInfo, FieldType_String, FieldFlag_None ) \
HANDLER(NANDTotalSizeOfSystem, 609, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
HANDLER(NANDFreeSpaceOfSystem, 610, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2018-2020 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 <vapours.hpp>
#include <stratosphere/erpt/erpt_types.hpp>
#include <stratosphere/sf/sf_buffer_tags.hpp>
namespace ams::erpt {
constexpr inline u32 CategoriesPerMultipleCategoryContext = 0x10;
constexpr inline u32 FieldsPerMultipleCategoryContext = CategoriesPerMultipleCategoryContext * 4;
struct MultipleCategoryContextEntry : public sf::LargeData, public sf::PrefersMapAliasTransferMode {
u32 version;
u32 category_count;
CategoryId categories[CategoriesPerMultipleCategoryContext];
u32 field_counts[CategoriesPerMultipleCategoryContext];
u32 array_buf_counts[CategoriesPerMultipleCategoryContext];
FieldEntry fields[FieldsPerMultipleCategoryContext];
};
}

View File

@@ -0,0 +1,234 @@
/*
* Copyright (c) 2018-2020 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 <vapours.hpp>
#include <stratosphere/os.hpp>
#include <stratosphere/time/time_posix_time.hpp>
#include <stratosphere/erpt/erpt_ids.autogen.hpp>
namespace ams::erpt {
#define GENERATE_ENUM(NAME, ID, ...) NAME = ID,
enum FieldType {
AMS_ERPT_FOREACH_FIELD_TYPE(GENERATE_ENUM)
FieldType_Count,
};
#undef GENERATE_ENUM
#define GENERATE_ENUM(NAME, ID, ...) CategoryId_##NAME = ID,
enum CategoryId {
AMS_ERPT_FOREACH_CATEGORY(GENERATE_ENUM)
CategoryId_Count,
};
#undef GENERATE_ENUM
#define GENERATE_ENUM(NAME, ID, ...) FieldId_##NAME = ID,
enum FieldId {
AMS_ERPT_FOREACH_FIELD(GENERATE_ENUM)
FieldId_Count,
};
#undef GENERATE_ENUM
constexpr inline u32 ArrayBufferSizeDefault = 0x100;
constexpr inline u32 ArrayBufferSizeMax = 96_KB;
constexpr inline u32 ArrayFieldSizeMax = 16_KB - 1;
enum ReportType {
ReportType_Start = 0,
ReportType_Visible = ReportType_Start,
ReportType_Invisible = 1,
ReportType_End = 2,
ReportType_Count = ReportType_End,
ReportType_Any = ReportType_Count,
};
constexpr inline u32 ReportCountMax = 50;
constexpr inline u32 AttachmentsPerReportMax = 5;
constexpr inline u32 AttachmentCountMax = ReportCountMax * AttachmentsPerReportMax;
constexpr inline u32 ReportMetaDataSize = 0x20;
struct ReportMetaData {
u8 user_data[ReportMetaDataSize];
};
constexpr inline u32 ReportIdSize = 20;
struct ReportId {
union {
u8 id[ReportIdSize];
util::Uuid uuid;
#pragma pack(push, 1)
struct {
u32 time_low;
u16 time_mid;
u16 time_high_and_version;
u8 clock_high;
u8 clock_low;
u64 node;
} uuid_data;
#pragma pack(pop)
};
};
static_assert(sizeof(ReportId) == ReportIdSize);
inline bool operator==(const ReportId &lhs, const ReportId &rhs) {
return std::memcmp(lhs.id, rhs.id, sizeof(lhs.uuid)) == 0;
}
inline bool operator!=(const ReportId &lhs, const ReportId &rhs) {
return !(lhs == rhs);
}
struct ReportFlag {
using Transmitted = util::BitFlagSet<BITSIZEOF(u32), ReportFlag>::Flag<0>;
using HasAttachment = util::BitFlagSet<BITSIZEOF(u32), ReportFlag>::Flag<1>;
};
using ReportFlagSet = util::BitFlagSet<BITSIZEOF(u32), ReportFlag>;
static_assert(std::is_pod<ReportFlagSet>::value);
static_assert(sizeof(ReportFlagSet) == sizeof(u32));
struct ReportInfo {
ReportType type;
ReportId id;
ReportMetaData meta_data;
ReportFlagSet flags;
time::PosixTime timestamp_user;
time::PosixTime timestamp_network;
s64 report_size;
u64 reserved[3];
};
struct ReportList {
u32 report_count;
ReportInfo reports[ReportCountMax];
};
constexpr inline u32 AttachmentIdSize = 20;
struct AttachmentId {
union {
u8 id[AttachmentIdSize];
util::Uuid uuid;
};
};
static_assert(sizeof(AttachmentId) == AttachmentIdSize);
inline bool operator==(const AttachmentId &lhs, const AttachmentId &rhs) {
return std::memcmp(lhs.id, rhs.id, sizeof(lhs.uuid)) == 0;
}
inline bool operator!=(const AttachmentId &lhs, const AttachmentId &rhs) {
return !(lhs == rhs);
}
struct AttachmentFlag {
using HasOwner = util::BitFlagSet<BITSIZEOF(u32), AttachmentFlag>::Flag<1>;
};
using AttachmentFlagSet = util::BitFlagSet<BITSIZEOF(u32), AttachmentFlag>;
static_assert(std::is_pod<AttachmentFlagSet>::value);
static_assert(sizeof(AttachmentFlagSet) == sizeof(u32));
constexpr inline u32 AttachmentNameSizeMax = 0x20;
struct AttachmentInfo {
ReportId owner_report_id;
AttachmentId attachment_id;
AttachmentFlagSet flags;
s64 attachment_size;
char attachment_name[AttachmentNameSizeMax];
};
struct AttachmentList {
u32 attachment_count;
AttachmentInfo attachments[AttachmentsPerReportMax];
};
constexpr inline u32 AttachmentSizeMax = 512_KB;
struct FieldEntry {
FieldId id;
FieldType type;
union {
u64 value_u64;
u32 value_u32;
u16 value_u16;
u8 value_u8;
s64 value_i64;
s32 value_i32;
s16 value_i16;
s8 value_i8;
bool value_bool;
struct {
u32 start_idx;
u32 size;
} value_array;
};
};
constexpr inline u32 FieldsPerContext = 20;
struct ContextEntry {
u32 version;
u32 field_count;
CategoryId category;
FieldEntry fields[FieldsPerContext];
u8 *array_buffer;
u32 array_free_count;
u32 array_buffer_size;
};
struct StorageUsageStatistics {
util::Uuid journal_uuid;
u32 used_storage_size;
s64 max_report_size;
u32 report_count[ReportType_Count];
u32 transmitted_count[ReportType_Count];
u32 untransmitted_count[ReportType_Count];
};
/* https://github.com/msgpack/msgpack/blob/master/spec.md#overview */
enum class ValueTypeTag {
FixMap = 0x80,
FixArray = 0x90,
FixStr = 0xA0,
False = 0xC2,
True = 0xC3,
Bin8 = 0xC4,
Bin16 = 0xC5,
U8 = 0xCC,
U16 = 0xCD,
U32 = 0xCE,
U64 = 0xCF,
I8 = 0xD0,
I16 = 0xD1,
I32 = 0xD2,
I64 = 0xD3,
Str8 = 0xD9,
Str16 = 0xDA,
Array16 = 0xDC,
Map16 = 0xDE,
};
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2019-2020 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 <vapours.hpp>
#include <stratosphere/erpt/erpt_types.hpp>
namespace ams::erpt::sf {
class IAttachment : public ams::sf::IServiceObject {
protected:
enum class CommandId {
Open = 0,
Read = 1,
SetFlags = 2,
GetFlags = 3,
Close = 4,
GetSize = 5,
};
public:
/* Actual commands. */
virtual Result Open(const AttachmentId &attachment_id) = 0;
virtual Result Read(ams::sf::Out<u32> out_count, const ams::sf::OutBuffer &out_buffer) = 0;
virtual Result SetFlags(AttachmentFlagSet flags) = 0;
virtual Result GetFlags(ams::sf::Out<AttachmentFlagSet> out) = 0;
virtual Result Close() = 0;
virtual Result GetSize(ams::sf::Out<s64> out) = 0;
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(Open),
MAKE_SERVICE_COMMAND_META(Read),
MAKE_SERVICE_COMMAND_META(SetFlags),
MAKE_SERVICE_COMMAND_META(GetFlags),
MAKE_SERVICE_COMMAND_META(Close),
MAKE_SERVICE_COMMAND_META(GetSize),
};
};
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2019-2020 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 <vapours.hpp>
#include <stratosphere/sf.hpp>
#include <stratosphere/erpt/erpt_types.hpp>
#include <stratosphere/erpt/erpt_multiple_category_context.hpp>
#include <stratosphere/time/time_steady_clock_time_point.hpp>
namespace ams::erpt::sf {
class IContext : public ams::sf::IServiceObject {
protected:
enum class CommandId {
SubmitContext = 0,
CreateReport = 1,
SetInitialLaunchSettingsCompletionTime = 2,
ClearInitialLaunchSettingsCompletionTime = 3,
UpdatePowerOnTime = 4,
UpdateAwakeTime = 5,
SubmitMultipleCategoryContext = 6,
UpdateApplicationLaunchTime = 7,
ClearApplicationLaunchTime = 8,
SubmitAttachment = 9,
CreateReportWithAttachments = 10,
};
public:
/* Actual commands. */
virtual Result SubmitContext(const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer) = 0;
virtual Result CreateReport(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer) = 0;
virtual Result SetInitialLaunchSettingsCompletionTime(const time::SteadyClockTimePoint &time_point) = 0;
virtual Result ClearInitialLaunchSettingsCompletionTime() = 0;
virtual Result UpdatePowerOnTime() = 0;
virtual Result UpdateAwakeTime() = 0;
virtual Result SubmitMultipleCategoryContext(const MultipleCategoryContextEntry &ctx_entry, const ams::sf::InBuffer &str_buffer) = 0;
virtual Result UpdateApplicationLaunchTime() = 0;
virtual Result ClearApplicationLaunchTime() = 0;
virtual Result SubmitAttachment(ams::sf::Out<AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data) = 0;
virtual Result CreateReportWithAttachments(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer) = 0;
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(SubmitContext),
MAKE_SERVICE_COMMAND_META(CreateReport),
MAKE_SERVICE_COMMAND_META(SetInitialLaunchSettingsCompletionTime, hos::Version_300),
MAKE_SERVICE_COMMAND_META(ClearInitialLaunchSettingsCompletionTime, hos::Version_300),
MAKE_SERVICE_COMMAND_META(UpdatePowerOnTime, hos::Version_300),
MAKE_SERVICE_COMMAND_META(UpdateAwakeTime, hos::Version_300),
MAKE_SERVICE_COMMAND_META(SubmitMultipleCategoryContext, hos::Version_500),
MAKE_SERVICE_COMMAND_META(UpdateApplicationLaunchTime, hos::Version_600),
MAKE_SERVICE_COMMAND_META(ClearApplicationLaunchTime, hos::Version_600),
MAKE_SERVICE_COMMAND_META(SubmitAttachment, hos::Version_800),
MAKE_SERVICE_COMMAND_META(CreateReportWithAttachments, hos::Version_800),
};
};
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2019-2020 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 <vapours.hpp>
#include <stratosphere/erpt/erpt_types.hpp>
namespace ams::erpt::sf {
class IManager : public ams::sf::IServiceObject {
protected:
enum class CommandId {
GetReportList = 0,
GetEvent = 1,
CleanupReports = 2,
DeleteReport = 3,
GetStorageUsageStatistics = 4,
GetAttachmentList = 5,
};
public:
/* Actual commands. */
virtual Result GetReportList(const ams::sf::OutBuffer &out_list, ReportType type_filter) = 0;
virtual Result GetEvent(ams::sf::OutCopyHandle out) = 0;
virtual Result CleanupReports() = 0;
virtual Result DeleteReport(const ReportId &report_id) = 0;
virtual Result GetStorageUsageStatistics(ams::sf::Out<StorageUsageStatistics> out) = 0;
virtual Result GetAttachmentList(const ams::sf::OutBuffer &out_buf, const ReportId &report_id) = 0;
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetReportList),
MAKE_SERVICE_COMMAND_META(GetEvent),
MAKE_SERVICE_COMMAND_META(CleanupReports, hos::Version_400),
MAKE_SERVICE_COMMAND_META(DeleteReport, hos::Version_500),
MAKE_SERVICE_COMMAND_META(GetStorageUsageStatistics, hos::Version_500),
MAKE_SERVICE_COMMAND_META(GetAttachmentList, hos::Version_800),
};
};
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2019-2020 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 <vapours.hpp>
#include <stratosphere/erpt/erpt_types.hpp>
namespace ams::erpt::sf {
class IReport : public ams::sf::IServiceObject {
protected:
enum class CommandId {
Open = 0,
Read = 1,
SetFlags = 2,
GetFlags = 3,
Close = 4,
GetSize = 5,
};
public:
/* Actual commands. */
virtual Result Open(const ReportId &report_id) = 0;
virtual Result Read(ams::sf::Out<u32> out_count, const ams::sf::OutBuffer &out_buffer) = 0;
virtual Result SetFlags(ReportFlagSet flags) = 0;
virtual Result GetFlags(ams::sf::Out<ReportFlagSet> out) = 0;
virtual Result Close() = 0;
virtual Result GetSize(ams::sf::Out<s64> out) = 0;
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(Open),
MAKE_SERVICE_COMMAND_META(Read),
MAKE_SERVICE_COMMAND_META(SetFlags),
MAKE_SERVICE_COMMAND_META(GetFlags),
MAKE_SERVICE_COMMAND_META(Close),
MAKE_SERVICE_COMMAND_META(GetSize),
};
};
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2019-2020 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 <vapours.hpp>
#include <stratosphere/erpt/erpt_types.hpp>
#include <stratosphere/erpt/sf/erpt_sf_i_report.hpp>
#include <stratosphere/erpt/sf/erpt_sf_i_manager.hpp>
#include <stratosphere/erpt/sf/erpt_sf_i_attachment.hpp>
namespace ams::erpt::sf {
class ISession : public ams::sf::IServiceObject {
protected:
enum class CommandId {
OpenReport = 0,
OpenManager = 1,
OpenAttachment = 2,
};
public:
/* Actual commands. */
virtual Result OpenReport(ams::sf::Out<std::shared_ptr<erpt::sf::IReport>> out) = 0;
virtual Result OpenManager(ams::sf::Out<std::shared_ptr<erpt::sf::IManager>> out) = 0;
virtual Result OpenAttachment(ams::sf::Out<std::shared_ptr<erpt::sf::IAttachment>> out) = 0;
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(OpenReport),
MAKE_SERVICE_COMMAND_META(OpenManager),
MAKE_SERVICE_COMMAND_META(OpenAttachment, hos::Version_800),
};
};
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018-2020 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 <vapours.hpp>
namespace ams::erpt::srv {
Result Initialize(u8 *mem, size_t mem_size);
Result InitializeAndStartService();
Result SetSerialNumberAndOsVersion(const char *sn, u32 sn_len, const char *os, u32 os_len, const char *os_priv, u32 os_priv_len);
Result SetProductModel(const char *model, u32 model_len);
Result SetRegionSetting(const char *region, u32 region_len);
/* Atmosphere extension. */
Result SetRedirectNewReportsToSdCard(bool redirect);
void Wait();
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2018-2020 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 <vapours.hpp>
#include <stratosphere/os.hpp>
#include <stratosphere/erpt/erpt_ids.autogen.hpp>
namespace ams::erpt::srv {
constexpr inline const char ReportOnSdStoragePath[] = "ersd";
constexpr inline const char ReportStoragePath[] = "save";
constexpr inline const char JournalFileName[] = "save:/journal";
constexpr size_t ReportFileNameLength = 64;
constexpr size_t AttachmentFileNameLength = 64;
constexpr size_t MaxFieldStringSize = 64;
struct ReportFileName {
char name[ReportFileNameLength];
};
struct AttachmentFileName {
char name[AttachmentFileNameLength];
};
enum FieldFlag : u8 {
FieldFlag_None = 0,
FieldFlag_Encrypt = 1,
};
#define STRINGIZE_HANDLER(NAME, ...) #NAME,
constexpr inline const char * const FieldString[] = {
AMS_ERPT_FOREACH_FIELD(STRINGIZE_HANDLER)
};
constexpr inline const char * const CategoryString[] = {
AMS_ERPT_FOREACH_CATEGORY(STRINGIZE_HANDLER)
};
constexpr inline const char * const TypeString[] = {
AMS_ERPT_FOREACH_FIELD_TYPE(STRINGIZE_HANDLER)
};
#undef STRINGIZE_HANDLER
#define GET_FIELD_CATEGORY(FIELD, ID, CATEGORY, TYPE, FLAG) [FieldId_##FIELD] = CategoryId_##CATEGORY,
constexpr inline const CategoryId FieldToCategoryMap[] = {
AMS_ERPT_FOREACH_FIELD(GET_FIELD_CATEGORY)
};
#undef GET_FIELD_CATEGORY
#define GET_FIELD_TYPE(FIELD, ID, CATEGORY, TYPE, FLAG) [FieldId_##FIELD] = TYPE,
constexpr inline const FieldType FieldToTypeMap[] = {
AMS_ERPT_FOREACH_FIELD(GET_FIELD_TYPE)
};
#undef GET_FIELD_TYPE
#define GET_FIELD_FLAG(FIELD, ID, CATEGORY, TYPE, FLAG) [FieldId_##FIELD] = FLAG,
constexpr inline const FieldFlag FieldToFlagMap[] = {
AMS_ERPT_FOREACH_FIELD(GET_FIELD_FLAG)
};
#undef GET_FIELD_FLAG
constexpr inline ReportFlagSet MakeNoReportFlags() {
return util::MakeBitFlagSet<32, ReportFlag>();
}
constexpr inline AttachmentFlagSet MakeNoAttachmentFlags() {
return util::MakeBitFlagSet<32, AttachmentFlag>();
}
}

View File

@@ -16,8 +16,8 @@
#pragma once
#include <vapours.hpp>
#include "../ncm/ncm_types.hpp"
#include "../sf/sf_buffer_tags.hpp"
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/sf/sf_buffer_tags.hpp>
namespace ams::fatal {
@@ -324,28 +324,20 @@ namespace ams::fatal {
bool is_creport;
CpuContext cpu_ctx;
bool generate_error_report;
Event erpt_event;
Event battery_event;
os::Event *erpt_event;
os::Event *battery_event;
size_t stack_dump_size;
u64 stack_dump_base;
u8 stack_dump[0x100];
u64 tls_address;
u8 tls_dump[0x100];
void ClearState() {
this->result = ResultSuccess();
this->program_id = ncm::ProgramId::Invalid;
std::memset(this->proc_name, 0, sizeof(this->proc_name));
this->is_creport = false;
std::memset(&this->cpu_ctx, 0, sizeof(this->cpu_ctx));
this->generate_error_report = false;
std::memset(&this->erpt_event, 0, sizeof(this->erpt_event));
std::memset(&this->battery_event, 0, sizeof(this->battery_event));
this->stack_dump_size = 0;
this->stack_dump_base = 0;
std::memset(this->stack_dump, 0, sizeof(this->stack_dump));
this->tls_address = 0;
std::memset(this->tls_dump, 0, sizeof(this->tls_dump));
ThrowContext(os::Event *erpt, os::Event *bat)
: result(ResultSuccess()), program_id(), proc_name(), is_creport(), cpu_ctx(), generate_error_report(),
erpt_event(erpt), battery_event(bat),
stack_dump_size(), stack_dump_base(), stack_dump(), tls_address(), tls_dump()
{
/* ... */
}
};

View File

@@ -19,11 +19,35 @@
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/impl/fs_filesystem_proxy_type.hpp>
#include <stratosphere/fs/fsa/fs_registrar.hpp>
#include <stratosphere/fs/fs_remote_filesystem.hpp>
#include <stratosphere/fs/fs_readonly_filesystem_adapter.hpp>
#include <stratosphere/fs/fs_read_only_filesystem.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/fs_substorage.hpp>
#include <stratosphere/fs/fs_memory_storage.hpp>
#include <stratosphere/fs/fs_remote_storage.hpp>
#include <stratosphere/fs/fs_file_storage.hpp>
#include <stratosphere/fs/fs_query_range.hpp>
#include <stratosphere/fs/impl/fs_common_mount_name.hpp>
#include <stratosphere/fs/fs_mount.hpp>
#include <stratosphere/fs/fs_path_tool.hpp>
#include <stratosphere/fs/fs_path_utils.hpp>
#include <stratosphere/fs/fs_filesystem_utils.hpp>
#include <stratosphere/fs/fs_romfs_filesystem.hpp>
#include <stratosphere/fs/impl/fs_data.hpp>
#include <stratosphere/fs/fs_application.hpp>
#include <stratosphere/fs/fs_bis.hpp>
#include <stratosphere/fs/fs_code.hpp>
#include <stratosphere/fs/fs_content.hpp>
#include <stratosphere/fs/fs_content_storage.hpp>
#include <stratosphere/fs/fs_image_directory.hpp>
#include <stratosphere/fs/fs_game_card.hpp>
#include <stratosphere/fs/fs_save_data_types.hpp>
#include <stratosphere/fs/fs_save_data_management.hpp>
#include <stratosphere/fs/fs_save_data_transaction.hpp>
#include <stratosphere/fs/fs_device_save_data.hpp>
#include <stratosphere/fs/fs_system_save_data.hpp>
#include <stratosphere/fs/fs_sd_card.hpp>
#include <stratosphere/fs/fs_signed_system_partition.hpp>
#include <stratosphere/fs/fs_system_data.hpp>

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
namespace ams::fs {
Result MountApplicationPackage(const char *name, const char *common_path);
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
namespace ams::fs {
enum class BisPartitionId {
/* Boot0 */
BootPartition1Root = 0,
/* Boot1 */
BootPartition2Root = 10,
/* Non-Boot */
UserDataRoot = 20,
BootConfigAndPackage2Part1 = 21,
BootConfigAndPackage2Part2 = 22,
BootConfigAndPackage2Part3 = 23,
BootConfigAndPackage2Part4 = 24,
BootConfigAndPackage2Part5 = 25,
BootConfigAndPackage2Part6 = 26,
CalibrationBinary = 27,
CalibrationFile = 28,
SafeMode = 29,
User = 30,
System = 31,
SystemProperEncryption = 32,
SystemProperPartition = 33,
SignedSystemPartitionOnSafeMode = 34,
};
const char *GetBisMountName(BisPartitionId id);
Result MountBis(BisPartitionId id, const char *root_path);
Result MountBis(const char *name, BisPartitionId id);
void SetBisRootForHost(BisPartitionId id, const char *root_path);
Result OpenBisPartition(std::unique_ptr<fs::IStorage> *out, BisPartitionId id);
Result InvalidateBisCache();
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
#include <stratosphere/ncm/ncm_ids.hpp>
namespace ams::fs {
Result MountCode(const char *name, const char *path, ncm::ProgramId program_id);
Result MountCodeForAtmosphereWithRedirection(const char *name, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific);
Result MountCodeForAtmosphere(const char *name, const char *path, ncm::ProgramId program_id);
}

View File

@@ -15,13 +15,34 @@
*/
#pragma once
#include <vapours.hpp>
#include "../os.hpp"
#include "../ncm.hpp"
#include "../sf.hpp"
#include <stratosphere/os.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/sf.hpp>
namespace ams::fs {
/* TODO: Better place for this? */
constexpr inline size_t MountNameLengthMax = 15;
struct Int64 {
u32 low;
u32 high;
}
constexpr ALWAYS_INLINE void Set(s64 v) {
this->low = static_cast<u32>((v & static_cast<u64>(0x00000000FFFFFFFFul)) >> 0);
this->high = static_cast<u32>((v & static_cast<u64>(0xFFFFFFFF00000000ul)) >> 32);
}
constexpr ALWAYS_INLINE s64 Get() const {
return (static_cast<s64>(this->high) << 32) | (static_cast<s64>(this->low));
}
constexpr ALWAYS_INLINE Int64 &operator=(s64 v) {
this->Set(v);
return *this;
}
constexpr ALWAYS_INLINE operator s64() const {
return this->Get();
}
};
static_assert(std::is_pod<Int64>::value);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
#include <stratosphere/ncm/ncm_ids.hpp>
namespace ams::fs {
enum ContentType {
ContentType_Meta = 0,
ContentType_Control = 1,
ContentType_Manual = 2,
ContentType_Logo = 3,
ContentType_Data = 4,
};
Result MountContent(const char *name, const char *path, ContentType content_type);
Result MountContent(const char *name, const char *path, ncm::ProgramId id, ContentType content_type);
Result MountContent(const char *name, const char *path, ncm::DataId id, ContentType content_type);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
namespace ams::fs {
enum class ContentStorageId : u32 {
System = 0,
User = 1,
SdCard = 2,
};
constexpr inline const char * const ContentStorageDirectoryName = "Contents";
const char *GetContentStorageMountName(ContentStorageId id);
Result MountContentStorage(ContentStorageId id);
Result MountContentStorage(const char *name, ContentStorageId id);
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright (c) 2018-2020 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 "fs_dbm_rom_types.hpp"
#include "fs_dbm_rom_path_tool.hpp"
#include "fs_dbm_rom_key_value_storage.hpp"
namespace ams::fs {
class HierarchicalRomFileTable {
public:
using Position = u32;
struct FindPosition {
Position next_dir;
Position next_file;
};
static_assert(std::is_pod<FindPosition>::value);
using DirectoryInfo = RomDirectoryInfo;
using FileInfo = RomFileInfo;
static constexpr RomFileId ConvertToFileId(Position pos) {
return static_cast<RomFileId>(pos);
}
private:
static constexpr inline Position InvalidPosition = ~Position();
static constexpr inline Position RootPosition = 0;
static constexpr inline size_t ReservedDirectoryCount = 1;
static constexpr RomDirectoryId ConvertToDirectoryId(Position pos) {
return static_cast<RomDirectoryId>(pos);
}
static constexpr Position ConvertToPosition(RomDirectoryId id) {
return static_cast<Position>(id);
}
static_assert(std::is_same<RomDirectoryId, RomFileId>::value);
struct RomDirectoryEntry {
Position next;
Position dir;
Position file;
};
static_assert(std::is_pod<RomDirectoryEntry>::value);
struct RomFileEntry {
Position next;
FileInfo info;
};
static_assert(std::is_pod<RomFileEntry>::value);
static constexpr inline u32 MaxKeyLength = RomPathTool::MaxPathLength;
template<typename ImplKeyType, typename ClientKeyType, typename ValueType>
class EntryMapTable : public RomKeyValueStorage<ImplKeyType, ValueType, MaxKeyLength> {
public:
using ImplKey = ImplKeyType;
using ClientKey = ClientKeyType;
using Value = ValueType;
using Position = HierarchicalRomFileTable::Position;
using Base = RomKeyValueStorage<ImplKeyType, ValueType, MaxKeyLength>;
public:
Result Add(Position *out, const ClientKeyType &key, const Value &value) {
return Base::AddImpl(out, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar), value);
}
Result Get(Position *out_pos, Value *out_val, const ClientKeyType &key) {
return Base::GetImpl(out_pos, out_val, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar));
}
Result GetByPosition(ImplKey *out_key, Value *out_val, Position pos) {
return Base::GetByPosition(out_key, out_val, pos);
}
Result GetByPosition(ImplKey *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
return Base::GetByPosition(out_key, out_val, out_aux, out_aux_size, pos);
}
Result SetByPosition(Position pos, const Value &value) {
return Base::SetByPosition(pos, value);
}
};
struct RomEntryKey {
Position parent;
bool IsEqual(const RomEntryKey &rhs, const void *aux_lhs, size_t aux_lhs_size, const void *aux_rhs, size_t aux_rhs_size) const {
if (this->parent != rhs.parent) {
return false;
}
if (aux_lhs_size != aux_rhs_size) {
return false;
}
return RomPathTool::IsEqualPath(reinterpret_cast<const RomPathChar *>(aux_lhs), reinterpret_cast<const RomPathChar *>(aux_rhs), aux_lhs_size / sizeof(RomPathChar));
}
};
static_assert(std::is_pod<RomEntryKey>::value);
struct EntryKey {
RomEntryKey key;
RomPathTool::RomEntryName name;
constexpr u32 Hash() const {
u32 hash = this->key.parent ^ 123456789;
const RomPathChar *name = this->name.path;
const RomPathChar *end = name + this->name.length;
while (name < end) {
const u32 cur = static_cast<u32>(static_cast<std::make_unsigned<RomPathChar>::type>(*(name++)));
hash = ((hash >> 5) | (hash << 27)) ^ cur;
}
return hash;
}
};
static_assert(std::is_pod<EntryKey>::value);
using DirectoryEntryMapTable = EntryMapTable<RomEntryKey, EntryKey, RomDirectoryEntry>;
using FileEntryMapTable = EntryMapTable<RomEntryKey, EntryKey, RomFileEntry>;
private:
DirectoryEntryMapTable dir_table;
FileEntryMapTable file_table;
public:
static s64 QueryDirectoryEntryStorageSize(u32 count);
static s64 QueryDirectoryEntryBucketStorageSize(s64 count);
static s64 QueryFileEntryStorageSize(u32 count);
static s64 QueryFileEntryBucketStorageSize(s64 count);
static Result Format(SubStorage dir_bucket, SubStorage file_bucket);
public:
HierarchicalRomFileTable();
constexpr u32 GetDirectoryEntryCount() const {
return this->dir_table.GetEntryCount();
}
constexpr u32 GetFileEntryCount() const {
return this->file_table.GetEntryCount();
}
Result Initialize(SubStorage dir_bucket, SubStorage dir_entry, SubStorage file_bucket, SubStorage file_entry);
void Finalize();
Result CreateRootDirectory();
Result CreateDirectory(RomDirectoryId *out, const RomPathChar *path, const DirectoryInfo &info);
Result CreateFile(RomFileId *out, const RomPathChar *path, const FileInfo &info);
Result ConvertPathToDirectoryId(RomDirectoryId *out, const RomPathChar *path);
Result ConvertPathToFileId(RomFileId *out, const RomPathChar *path);
Result GetDirectoryInformation(DirectoryInfo *out, const RomPathChar *path);
Result GetDirectoryInformation(DirectoryInfo *out, RomDirectoryId id);
Result OpenFile(FileInfo *out, const RomPathChar *path);
Result OpenFile(FileInfo *out, RomFileId id);
Result FindOpen(FindPosition *out, const RomPathChar *path);
Result FindOpen(FindPosition *out, RomDirectoryId id);
Result FindNextDirectory(RomPathChar *out, FindPosition *find, size_t length);
Result FindNextFile(RomPathChar *out, FindPosition *find, size_t length);
Result QueryRomFileSystemSize(s64 *out_dir_entry_size, s64 *out_file_entry_size);
private:
Result GetGrandParent(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, Position pos, RomPathTool::RomEntryName name, const RomPathChar *path);
Result FindParentDirectoryRecursive(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, RomPathTool::PathParser *parser, const RomPathChar *path);
Result FindPathRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, bool is_dir, const RomPathChar *path);
Result FindDirectoryRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, const RomPathChar *path);
Result FindFileRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, const RomPathChar *path);
Result CheckSameEntryExists(const EntryKey &key, Result if_exists);
Result GetDirectoryEntry(Position *out_pos, RomDirectoryEntry *out_entry, const EntryKey &key);
Result GetDirectoryEntry(RomDirectoryEntry *out_entry, RomDirectoryId id);
Result GetFileEntry(Position *out_pos, RomFileEntry *out_entry, const EntryKey &key);
Result GetFileEntry(RomFileEntry *out_entry, RomFileId id);
Result GetDirectoryInformation(DirectoryInfo *out, const EntryKey &key);
Result OpenFile(FileInfo *out, const EntryKey &key);
Result FindOpen(FindPosition *out, const EntryKey &key);
};
}

View File

@@ -0,0 +1,379 @@
/*
* Copyright (c) 2018-2020 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 "fs_dbm_rom_types.hpp"
#include "fs_substorage.hpp"
namespace ams::fs {
template<typename KeyType, typename ValueType, size_t MaxAuxiliarySize>
class RomKeyValueStorage {
public:
using Key = KeyType;
using Value = ValueType;
using Position = u32;
using BucketIndex = s64;
struct FindIndex {
BucketIndex ind;
Position pos;
};
static_assert(std::is_pod<FindIndex>::value);
private:
static constexpr inline Position InvalidPosition = ~Position();
struct Element {
Key key;
Value value;
Position next;
u32 size;
};
static_assert(std::is_pod<Element>::value);
private:
s64 bucket_count;
SubStorage bucket_storage;
SubStorage kv_storage;
s64 total_entry_size;
u32 entry_count;
public:
static constexpr s64 QueryBucketStorageSize(s64 num) {
return num * sizeof(Position);
}
static constexpr s64 QueryBucketCount(s64 size) {
return size / sizeof(Position);
}
static constexpr s64 QueryKeyValueStorageSize(u32 num) {
return num * sizeof(Element);
}
static Result Format(SubStorage bucket, s64 count) {
const Position pos = InvalidPosition;
for (s64 i = 0; i < count; i++) {
R_TRY(bucket.Write(i * sizeof(pos), std::addressof(pos), sizeof(pos)));
}
return ResultSuccess();
}
public:
RomKeyValueStorage() : bucket_count(), bucket_storage(), kv_storage(), total_entry_size(), entry_count() { /* ... */ }
Result Initialize(const SubStorage &bucket, s64 count, const SubStorage &kv) {
AMS_ASSERT(count > 0);
this->bucket_storage = bucket;
this->kv_storage = kv;
this->bucket_count = count;
return ResultSuccess();
}
void Finalize() {
this->bucket_storage = SubStorage();
this->kv_storage = SubStorage();
this->bucket_count = 0;
}
s64 GetTotalEntrySize() const {
return this->total_entry_size;
}
Result GetFreeSize(s64 *out) {
AMS_ASSERT(out != nullptr);
s64 kv_size = 0;
R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
*out = kv_size - this->total_entry_size;
return ResultSuccess();
}
constexpr u32 GetEntryCount() const {
return this->entry_count;
}
Result Add(const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
AMS_ASSERT(aux != nullptr);
AMS_ASSERT(aux_size <= MaxAuxiliarySize);
Position pos;
return this->AddImpl(std::addressof(pos), key, hash_key, aux, aux_size, value);
}
Result Get(Value *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
AMS_ASSERT(aux != nullptr);
AMS_ASSERT(aux_size <= MaxAuxiliarySize);
Position pos;
return this->GetImpl(std::addressof(pos), out, key, hash_key, aux, aux_size);
}
void FindOpen(FindIndex *out) const {
AMS_ASSERT(out != nullptr);
out->ind = static_cast<BucketIndex>(-1);
out->pos = InvalidPosition;
}
Result FindNext(Key *out_key, Value *out_val, FindIndex *find) {
AMS_ASSERT(out_key != nullptr);
AMS_ASSERT(out_val != nullptr);
AMS_ASSERT(find != nullptr);
BucketIndex ind = find->ind;
R_UNLESS((ind < this->bucket_count) || ind == static_cast<BucketIndex>(-1), fs::ResultDbmFindKeyFinished());
s64 kv_size;
R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
while (true) {
if (find->pos != InvalidPosition) {
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), find->pos));
AMS_ASSERT(elem.next == InvalidPosition || elem.next < kv_size);
find->pos = elem.next;
*out_key = elem.key;
*out_val = elem.val;
return ResultSuccess();
}
while (true) {
ind++;
if (ind == this->bucket_count) {
find->ind = ind;
find->pos = InvalidPosition;
return fs::ResultDbmFindKeyFinished();
}
Position pos;
R_TRY(this->ReadBucket(std::addressof(pos), ind));
AMS_ASSERT(pos == InvalidPosition || pos < kv_size);
if (pos != InvalidPosition) {
find->ind = ind;
find->pos = pos;
break;
}
}
}
}
protected:
Result AddImpl(Position *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(aux != nullptr);
AMS_ASSERT(this->bucket_count > 0);
{
Position pos, prev_pos;
Element elem;
const Result find_res = this->FindImpl(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size);
R_UNLESS(R_FAILED(find_res), fs::ResultDbmAlreadyExists());
R_UNLESS(fs::ResultDbmKeyNotFound::Includes(find_res), find_res);
}
Position pos;
R_TRY(this->AllocateEntry(std::addressof(pos), aux_size));
Position next_pos;
R_TRY(this->LinkEntry(std::addressof(next_pos), pos, hash_key));
const Element elem = { key, value, next_pos, static_cast<u32>(aux_size) };
R_TRY(this->WriteKeyValue(std::addressof(elem), pos, aux, aux_size));
*out = pos;
this->entry_count++;
return ResultSuccess();
}
Result GetImpl(Position *out_pos, Value *out_val, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
AMS_ASSERT(out_pos != nullptr);
AMS_ASSERT(out_val != nullptr);
AMS_ASSERT(aux != nullptr);
Position pos, prev_pos;
Element elem;
R_TRY(this->FindImpl(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size));
*out_pos = pos;
*out_val = elem.value;
return ResultSuccess();
}
Result GetByPosition(Key *out_key, Value *out_val, Position pos) {
AMS_ASSERT(out_key != nullptr);
AMS_ASSERT(out_val != nullptr);
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), pos));
*out_key = elem.key;
*out_val = elem.value;
return ResultSuccess();
}
Result GetByPosition(Key *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
AMS_ASSERT(out_key != nullptr);
AMS_ASSERT(out_val != nullptr);
AMS_ASSERT(out_aux != nullptr);
AMS_ASSERT(out_aux_size != nullptr);
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), out_aux, out_aux_size, pos));
*out_key = elem.key;
*out_val = elem.value;
return ResultSuccess();
}
Result SetByPosition(Position pos, const Value &value) {
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), pos));
elem.value = value;
return this->WriteKeyValue(std::addressof(elem), pos, nullptr, 0);
}
private:
BucketIndex HashToBucket(u32 hash_key) const {
return hash_key % this->bucket_count;
}
Result FindImpl(Position *out_pos, Position *out_prev, Element *out_elem, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
AMS_ASSERT(out_pos != nullptr);
AMS_ASSERT(out_prev != nullptr);
AMS_ASSERT(out_elem != nullptr);
AMS_ASSERT(aux != nullptr);
AMS_ASSERT(this->bucket_count > 0);
*out_pos = 0;
*out_prev = 0;
const BucketIndex ind = HashToBucket(hash_key);
Position cur;
R_TRY(this->ReadBucket(std::addressof(cur), ind));
s64 kv_size;
R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(cur == InvalidPosition || cur < kv_size);
R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
u8 *buf = static_cast<u8 *>(::ams::fs::impl::Allocate(MaxAuxiliarySize));
R_UNLESS(buf != nullptr, fs::ResultAllocationFailureInDbmRomKeyValueStorage());
ON_SCOPE_EXIT { ::ams::fs::impl::Deallocate(buf, MaxAuxiliarySize); };
while (true) {
size_t cur_aux_size;
R_TRY(this->ReadKeyValue(out_elem, buf, std::addressof(cur_aux_size), cur));
if (key.IsEqual(out_elem->key, aux, aux_size, buf, cur_aux_size)) {
*out_pos = cur;
return ResultSuccess();
}
*out_prev = cur;
cur = out_elem->next;
R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
}
}
Result AllocateEntry(Position *out, size_t aux_size) {
AMS_ASSERT(out != nullptr);
s64 kv_size;
R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
const size_t end_pos = this->total_entry_size + sizeof(Element) + aux_size;
R_UNLESS(end_pos <= static_cast<size_t>(kv_size), fs::ResultDbmKeyFull());
*out = static_cast<Position>(this->total_entry_size);
this->total_entry_size = util::AlignUp(static_cast<s64>(end_pos), s64(4));
return ResultSuccess();
}
Result LinkEntry(Position *out, Position pos, u32 hash_key) {
AMS_ASSERT(out != nullptr);
const BucketIndex ind = HashToBucket(hash_key);
Position next;
R_TRY(this->ReadBucket(std::addressof(next), ind));
s64 kv_size;
R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(next == InvalidPosition || next < kv_size);
R_TRY(this->WriteBucket(pos, ind));
*out = next;
return ResultSuccess();
}
Result ReadBucket(Position *out, BucketIndex ind) {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(ind < this->bucket_count);
const s64 offset = ind * sizeof(Position);
return this->bucket_storage.Read(offset, out, sizeof(*out));
}
Result WriteBucket(Position pos, BucketIndex ind) {
AMS_ASSERT(ind < this->bucket_count);
const s64 offset = ind * sizeof(Position);
return this->bucket_storage.Write(offset, std::addressof(pos), sizeof(pos));
}
Result ReadKeyValue(Element *out, Position pos) {
AMS_ASSERT(out != nullptr);
s64 kv_size;
R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(pos < kv_size);
return this->kv_storage.Read(pos, out, sizeof(*out));
}
Result ReadKeyValue(Element *out, void *out_aux, size_t *out_aux_size, Position pos) {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(out_aux != nullptr);
AMS_ASSERT(out_aux_size != nullptr);
R_TRY(this->ReadKeyValue(out, pos));
*out_aux_size = out->size;
if (out->size > 0) {
R_TRY(this->kv_storage.Read(pos + sizeof(*out), out_aux, out->size));
}
return ResultSuccess();
}
Result WriteKeyValue(const Element *elem, Position pos, const void *aux, size_t aux_size) {
AMS_ASSERT(elem != nullptr);
AMS_ASSERT(aux != nullptr);
s64 kv_size;
R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(pos < kv_size);
R_TRY(this->kv_storage.Write(pos, elem, sizeof(*elem)));
if (aux != nullptr && aux_size > 0) {
R_TRY(this->kv_storage.Write(pos + sizeof(*elem), aux, aux_size));
}
return ResultSuccess();
}
};
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2018-2020 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 "fs_dbm_rom_types.hpp"
namespace ams::fs {
namespace RomPathTool {
constexpr inline u32 MaxPathLength = 0x300;
struct RomEntryName {
size_t length;
const RomPathChar *path;
};
static_assert(std::is_pod<RomEntryName>::value);
constexpr void InitializeRomEntryName(RomEntryName *entry) {
AMS_ABORT_UNLESS(entry != nullptr);
entry->length = 0;
}
constexpr inline bool IsSeparator(RomPathChar c) {
return c == RomStringTraits::DirectorySeparator;
}
constexpr inline bool IsNullTerminator(RomPathChar c) {
return c == RomStringTraits::NullTerminator;
}
constexpr inline bool IsDot(RomPathChar c) {
return c == RomStringTraits::Dot;
}
constexpr inline bool IsCurrentDirectory(const RomEntryName &name) {
return name.length == 1 && IsDot(name.path[0]);
}
constexpr inline bool IsCurrentDirectory(const RomPathChar *p, size_t length) {
AMS_ABORT_UNLESS(p != nullptr);
return length == 1 && IsDot(p[0]);
}
constexpr inline bool IsCurrentDirectory(const RomPathChar *p) {
AMS_ABORT_UNLESS(p != nullptr);
return IsDot(p[0]) && IsNullTerminator(p[1]);
}
constexpr inline bool IsParentDirectory(const RomEntryName &name) {
return name.length == 2 && IsDot(name.path[0]) && IsDot(name.path[1]);
}
constexpr inline bool IsParentDirectory(const RomPathChar *p) {
AMS_ABORT_UNLESS(p != nullptr);
return IsDot(p[0]) && IsDot(p[1]) && IsNullTerminator(p[2]);
}
constexpr inline bool IsParentDirectory(const RomPathChar *p, size_t length) {
AMS_ABORT_UNLESS(p != nullptr);
return length == 2 && IsDot(p[0]) && IsDot(p[1]);
}
constexpr inline bool IsEqualPath(const RomPathChar *lhs, const RomPathChar *rhs, size_t length) {
AMS_ABORT_UNLESS(lhs != nullptr);
AMS_ABORT_UNLESS(rhs != nullptr);
return std::strncmp(lhs, rhs, length) == 0;
}
constexpr inline bool IsEqualName(const RomEntryName &lhs, const RomPathChar *rhs) {
AMS_ABORT_UNLESS(rhs != nullptr);
if (strnlen(rhs, MaxPathLength) != lhs.length) {
return false;
}
return IsEqualPath(lhs.path, rhs, lhs.length);
}
constexpr inline bool IsEqualName(const RomEntryName &lhs, const RomEntryName &rhs) {
if (lhs.length != rhs.length) {
return false;
}
return IsEqualPath(lhs.path, rhs.path, lhs.length);
}
Result GetParentDirectoryName(RomEntryName *out, const RomEntryName &cur, const RomPathChar *p);
class PathParser {
private:
const RomPathChar *prev_path_start;
const RomPathChar *prev_path_end;
const RomPathChar *next_path;
bool finished;
public:
constexpr PathParser() : prev_path_start(), prev_path_end(), next_path(), finished() { /* ... */ }
Result Initialize(const RomPathChar *path);
void Finalize();
bool IsFinished() const;
bool IsDirectoryPath() const;
Result GetAsDirectoryName(RomEntryName *out) const;
Result GetAsFileName(RomEntryName *out) const;
Result GetNextDirectoryName(RomEntryName *out);
};
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
namespace ams::fs {
using RomPathChar = char;
using RomFileId = s32;
using RomDirectoryId = s32;
struct RomFileSystemInformation {
s64 size;
s64 directory_bucket_offset;
s64 directory_bucket_size;
s64 directory_entry_offset;
s64 directory_entry_size;
s64 file_bucket_offset;
s64 file_bucket_size;
s64 file_entry_offset;
s64 file_entry_size;
s64 body_offset;
};
static_assert(std::is_pod<RomFileSystemInformation>::value);
static_assert(sizeof(RomFileSystemInformation) == 0x50);
struct RomDirectoryInfo {
/* ... */
};
static_assert(std::is_pod<RomDirectoryInfo>::value);
struct RomFileInfo {
Int64 offset;
Int64 size;
};
static_assert(std::is_pod<RomFileInfo>::value);
namespace RomStringTraits {
constexpr inline char DirectorySeparator = '/';
constexpr inline char NullTerminator = '\x00';
constexpr inline char Dot = '.';
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
#include "fs_save_data_types.hpp"
namespace ams::fs {
Result MountDeviceSaveData(const char *name);
Result MountDeviceSaveData(const char *name, const ncm::ApplicationId application_id);
}

View File

@@ -22,4 +22,12 @@ namespace ams::fs {
using DirectoryEntry = ::FsDirectoryEntry;
struct DirectoryHandle {
void *handle;
};
Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries);
Result GetDirectoryEntryCount(s64 *out, DirectoryHandle handle);
void CloseDirectory(DirectoryHandle handle);
}

View File

@@ -60,4 +60,19 @@ namespace ams::fs {
static_assert(std::is_pod<WriteOption>::value && sizeof(WriteOption) == sizeof(u32));
struct FileHandle {
void *handle;
};
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);
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);
Result GetFileSize(s64 *out, FileHandle handle);
Result FlushFile(FileHandle handle);
Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option);
Result SetFileSize(FileHandle handle, s64 size);
int GetFileOpenMode(FileHandle handle);
void CloseFile(FileHandle handle);
}

View File

@@ -14,13 +14,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "fs_common.hpp"
#include "fs_istorage.hpp"
#include "fsa/fs_ifile.hpp"
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fs {
class FileStorage : public IStorage {
class FileStorage : public IStorage, public impl::Newable {
private:
static constexpr s64 InvalidSize = -1;
private:
@@ -53,4 +54,32 @@ namespace ams::fs {
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
};
class FileHandleStorage : public IStorage, public impl::Newable {
private:
static constexpr s64 InvalidSize = -1;
private:
FileHandle handle;
bool close_file;
s64 size;
os::Mutex mutex;
public:
constexpr explicit FileHandleStorage(FileHandle handle, bool close_file) : handle(handle), close_file(close_file), size(InvalidSize), mutex(false) { /* ... */ }
constexpr explicit FileHandleStorage(FileHandle handle) : FileHandleStorage(handle, false) { /* ... */ }
virtual ~FileHandleStorage() override {
if (this->close_file) {
CloseFile(this->handle);
}
}
protected:
Result UpdateSize();
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override;
virtual Result Write(s64 offset, const void *buffer, size_t size) override;
virtual Result Flush() override;
virtual Result GetSize(s64 *out_size) override;
virtual Result SetSize(s64 size) override;
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
};
}

View File

@@ -18,13 +18,19 @@
namespace ams::fs {
namespace fsa {
class IFile;
}
enum OpenMode {
OpenMode_Read = ::FsOpenMode_Read,
OpenMode_Write = ::FsOpenMode_Write,
OpenMode_Append = ::FsOpenMode_Append,
OpenMode_Read = (1 << 0),
OpenMode_Write = (1 << 1),
OpenMode_AllowAppend = (1 << 2),
OpenMode_ReadWrite = (OpenMode_Read | OpenMode_Write),
OpenMode_All = (OpenMode_ReadWrite | OpenMode_Append),
OpenMode_All = (OpenMode_ReadWrite | OpenMode_AllowAppend),
};
enum OpenDirectoryMode {
@@ -49,4 +55,27 @@ namespace ams::fs {
using FileTimeStampRaw = ::FsTimeStampRaw;
struct FileHandle;
struct DirectoryHandle;
Result CreateFile(const char *path, s64 size);
Result CreateFile(const char* path, s64 size, int option);
Result DeleteFile(const char *path);
Result CreateDirectory(const char *path);
Result DeleteDirectory(const char *path);
Result DeleteDirectoryRecursively(const char *path);
Result RenameFile(const char *old_path, const char *new_path);
Result RenameDirectory(const char *old_path, const char *new_path);
Result GetEntryType(DirectoryEntryType *out, const char *path);
Result OpenFile(FileHandle *out_file, const char *path, int mode);
Result OpenDirectory(DirectoryHandle *out_dir, const char *path, int mode);
Result CleanDirectoryRecursively(const char *path);
Result GetFreeSpaceSize(s64 *out, const char *path);
Result GetTotalSpaceSize(s64 *out, const char *path);
Result SetConcatenationFileAttribute(const char *path);
Result GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path);
Result OpenFile(FileHandle *out, std::unique_ptr<fsa::IFile> &&file, int mode);
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
#include "fs_filesystem.hpp"
namespace ams::fs {
/* Common utilities. */
Result EnsureDirectoryRecursively(const char *path);
Result EnsureParentDirectoryRecursively(const char *path);
Result HasFile(bool *out, const char *path);
Result HasDirectory(bool *out, const char *path);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
namespace ams::fs {
enum class GameCardPartition {
Update = 0,
Normal = 1,
Secure = 2,
Logo = 3,
};
enum class GameCardPartitionRaw {
NormalReadable,
SecureReadable,
RootWriteable,
};
enum class GameCardAttribute : u8 {
AutoBootFlag = (1 << 0),
HistoryEraseFlag = (1 << 1),
RepairToolFlag = (1 << 2),
DifferentRegionCupToTerraDeviceFlag = (1 << 3),
DifferentRegionCupToGlobalDeviceFlag = (1 << 4),
};
using GameCardHandle = u32;
Result GetGameCardHandle(GameCardHandle *out);
Result MountGameCardPartition(const char *name, GameCardHandle handle, GameCardPartition partition);
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018-2020 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 "fs_common.hpp"
namespace ams::fs {
enum class ImageDirectoryId {
Nand = 0,
SdCard = 1,
};
Result MountImageDirectory(const char *name, ImageDirectoryId id);
}

View File

@@ -26,21 +26,15 @@ namespace ams::fs {
virtual Result Read(s64 offset, void *buffer, size_t size) = 0;
virtual Result Write(s64 offset, const void *buffer, size_t size) {
return fs::ResultUnsupportedOperation();
}
virtual Result Write(s64 offset, const void *buffer, size_t size) = 0;
virtual Result Flush() = 0;
virtual Result SetSize(s64 size) {
return fs::ResultUnsupportedOperation();
}
virtual Result SetSize(s64 size) = 0;
virtual Result GetSize(s64 *out) = 0;
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
return fs::ResultUnsupportedOperation();
}
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) = 0;
virtual Result OperateRange(OperationId op_id, s64 offset, s64 size) {
return this->OperateRange(nullptr, 0, op_id, offset, size, nullptr, 0);
@@ -86,21 +80,31 @@ namespace ams::fs {
virtual ~ReadOnlyStorageAdapter() { /* ... */ }
public:
virtual Result Read(s64 offset, void *buffer, size_t size) {
virtual Result Read(s64 offset, void *buffer, size_t size) override {
return this->storage->Read(offset, buffer, size);
}
virtual Result Flush() {
virtual Result Flush() override {
return this->storage->Flush();
}
virtual Result GetSize(s64 *out) {
virtual Result GetSize(s64 *out) override {
return this->storage->GetSize(out);
}
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
return this->storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
/* TODO: Better result? Is it possible to get a more specific one? */
return fs::ResultUnsupportedOperation();
}
virtual Result SetSize(s64 size) override {
/* TODO: Better result? Is it possible to get a more specific one? */
return fs::ResultUnsupportedOperation();
}
};
}

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