Compare commits

..

359 Commits

Author SHA1 Message Date
Michael Scire
b4ca7fce9e docs: expand dns_mitm wildcard wording 2021-02-02 11:35:57 -08:00
Michael Scire
7872fc0299 dns.mitm: add documentation 2021-02-02 11:11:06 -08:00
Michael Scire
874f5b22e0 dns.mitm: support % in hosts file as stand-in for environment identifier 2021-02-02 00:38:04 -08:00
Michael Scire
5b0821cb03 dns.mitm: fix ABORT_UNLESS -> ABORT 2021-02-01 13:54:55 -08:00
Michael Scire
b93fd40550 dns.mitm: hint = {} fix in options 2021-02-01 13:43:52 -08:00
Michael Scire
a4d7c90da7 dns.mitm: add GetAddrInfo redir, AtmosphereReloadHostsFile, debug logging control 2021-02-01 13:40:23 -08:00
Michael Scire
4357086181 dns.mitm: fix inverted hostname detection 2021-01-31 09:10:24 -08:00
Michael Scire
ec655069d0 meso: update for new fatal encoding 2021-01-31 09:06:54 -08:00
Michael Scire
2b5e8b5c65 ams: take three tries to edit a structure 2021-01-31 09:02:18 -08:00
Michael Scire
f31ecb5c23 ams: afsr0 -> 32 bits in fatal error 2021-01-31 09:00:22 -08:00
Michael Scire
604f899553 ams: fix fatal error context 2021-01-31 08:57:48 -08:00
Michael Scire
25d7ab88e1 dns.mitm: support wildcards in hosts 2021-01-31 08:27:56 -08:00
Michael Scire
a231d7164b dns.mitm: edit default behavior/hosts filenames 2021-01-31 08:04:25 -08:00
Michael Scire
a804e62293 dns.mitm: fix issue in host file parsing 2021-01-30 20:16:45 -08:00
Michael Scire
6706fa49dc dns.mitm: parse redirections from hosts file 2021-01-30 19:50:49 -08:00
Michael Scire
3fd094436e dns: implement GetHostByName redirection (backend TODO) 2021-01-30 17:23:14 -08:00
Michael Scire
45709aa9cd dns: skeleton passthrough mitm 2021-01-30 13:11:39 -08:00
Michael Scire
a28c60970f kern: fix scheduler update semantics in KLightLock::LockSlowPath 2021-01-28 17:47:26 -08:00
Michael Scire
b5f72b9f20 fssystem: fix bug in BufferedStorage 2021-01-28 14:28:45 -08:00
Michael Scire
8d10584a51 result: always prefer diag::Abort to fatal 2021-01-28 00:15:24 -08:00
Michael Scire
366c265ab2 dd: fix include, note gcc-11 TODO 2021-01-27 23:41:35 -08:00
Michael Scire
42964992d1 dmnt: ro:dmnt available on all sysvers 2021-01-27 14:44:25 -08:00
Michael Scire
4a82d9bf28 sm: supercede ams extension via DetachClient 2021-01-27 14:36:15 -08:00
Michael Scire
4190281b2f ams: communicate status to libnx 2021-01-27 14:20:30 -08:00
Michael Scire
48830d190f timespan: explicitly require TimeSpanType as is_pod 2021-01-25 08:27:42 -08:00
Michael Scire
3389aaefc3 strat: update for revised libnx weak alloc funcs 2021-01-22 03:52:10 -08:00
Michael Scire
f8f987aa8d boot: remove references to memalign/malloc 2021-01-20 23:39:31 -08:00
Michael Scire
e87e146112 ams_mitm: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
5751bcc117 dmnt: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
eb1e979257 creport: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
204539664b boot2: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
f5c6736431 boot: update for new sf-semantics 2021-01-20 23:39:31 -08:00
Michael Scire
d00ebaa28a fatal: update screen task to use native window directly 2021-01-20 23:39:31 -08:00
Michael Scire
402e4d1adb fatal: wip (pending libnx pr) update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
ed7c0605f9 jpegdec: note libjpeg-turbo TODO 2021-01-20 23:39:31 -08:00
Michael Scire
c848a830ee libstrat: move weak HasLaunchedBootProgram to non-lto object file 2021-01-20 23:39:31 -08:00
Michael Scire
dbe8add4f4 loader: fix failure-to-early-return in launch record management 2021-01-20 23:39:31 -08:00
Michael Scire
e4e278bb3d util::unique_lock, update loader to new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
3761f80592 string_view: remove now unecessary comment 2021-01-20 23:39:31 -08:00
Michael Scire
9878c18e47 ncm: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
3bb94aa146 util::string_view, update pgl for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
83c04fa5d7 pm: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
dc4ee1a5bc erpt: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
5191f0e305 ro: reduce memory usage by excising (unused) std::malloc 2021-01-20 23:39:31 -08:00
Michael Scire
170034aed3 ro: update for new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
21236020cb sm, spl: update to use new sf semantics 2021-01-20 23:39:31 -08:00
Michael Scire
f06de12bea libstrat: convert to experimental new (super-accurate) sf allocation semantics 2021-01-20 23:39:31 -08:00
Michael Scire
8314d015f3 docs: vaguely update roadmap 2021-01-14 06:12:42 -08:00
Michael Scire
49f07b065a git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "6c11c07e"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "6c11c07e"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2021-01-13 10:42:02 -08:00
Michael Scire
9e104bb83f ams: bump version to 0.17.1 2021-01-13 10:41:13 -08:00
Michael Scire
33457d61da docs: changelog for 0.17.1 2021-01-13 10:40:45 -08:00
Michael Scire
b5816b4a91 stratosphere: discard unnecessary .eh_frame segment 2021-01-13 08:30:24 -08:00
Michael Scire
af7233d84c os: fix missing logic in SdkReplyAndReceive 2021-01-12 18:23:28 -08:00
Michael Scire
8ac8abf295 os: implement 11.x SdkReplyAndReceive 2021-01-12 18:18:39 -08:00
Michael Scire
b26ebc12e1 fs: fix keyslotcache unique_lock usage 2021-01-12 04:37:34 -08:00
Michael Scire
b4122da6ad strat: avoid using unique_lock in a few places 2021-01-12 03:54:46 -08:00
Michael Scire
6a2ee02409 util: fix header dependence 2021-01-12 03:02:09 -08:00
Michael Scire
094cede39e ams: use util::SNPrintf over std:: (size/linker improvements) 2021-01-12 02:59:41 -08:00
Michael Scire
9cfd259c5c spl: reduce heap size 2021-01-12 02:31:57 -08:00
Michael Scire
4f7f37fae6 sf: alter serialization to re-use as much logic as possible 2021-01-12 02:21:33 -08:00
Michael Scire
d2f81d2ca2 ams: save 0x11000 of memory in spl via minor tweaks 2021-01-12 01:27:38 -08:00
Michael Scire
b8072b1398 util: faster constexpr offsetof calc, at the cost of standards compliance 2021-01-08 04:07:45 -08:00
Michael Scire
a6e3a93c07 kern: discard std::__cmpexch_failure_order(std::memory_order) 2021-01-08 02:44:04 -08:00
Michael Scire
1e643f7ab0 kern: further codegen tweaks 2021-01-08 02:35:29 -08:00
Michael Scire
4aa18b06e8 kern: greatly improve codegen for atomics, scheduler 2021-01-08 02:13:43 -08:00
CaramelDunes
f051f707ed Do not blank Rsa2048DeviceCertificate or Rsa2048Device as it prevents HOS from booting on newer PRODINFO versions. 2021-01-07 14:09:15 -08:00
Michael Scire
1c9d6b4d90 kern: fix svc bounds checking for main memory size 4GB -> 8GB (closes #1320) 2021-01-07 03:43:09 -08:00
Michael Scire
b21f8a5043 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "8ad00caa"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "8ad00caa"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2021-01-05 15:14:58 -08:00
Michael Scire
e53b9cc518 ams: update Makefile to build zips with new names 2021-01-05 11:05:33 -08:00
Michael Scire
99e4920d9d fusee: pass along lcd vendor to exosphere (needed for mariko fatal) 2021-01-05 11:05:33 -08:00
Michael Scire
428b5b266c docs/changelog: don't let dreams remain memes 2021-01-05 11:05:33 -08:00
Michael Scire
2b48743265 fusee: perform only pmic reboots on mariko 2021-01-05 11:05:33 -08:00
Michael Scire
a0769844f4 ams: provisional changelog for 0.17.0, release sometime this week 2021-01-05 11:05:33 -08:00
Michael Scire
e0fe29743d pmic: use correct shutdown impl for erista power-off 2021-01-05 11:05:33 -08:00
Michael Scire
9ace85a4aa sept: fix sdram parameter scratch save 2021-01-05 11:05:33 -08:00
Michael Scire
e53b171693 ams: mariko support implies 0.17.0 2021-01-05 11:05:33 -08:00
Michael Scire
8b1835368a sept: fixes to work with new hwinit/etc 2021-01-05 11:05:33 -08:00
Michael Scire
cf7ae775e8 sept is erista-only, and doesn't need mariko sdram (space saving measure) 2021-01-05 11:05:33 -08:00
Michael Scire
07202f7c88 fusee: fix overcorrection for boot reason address 2021-01-05 11:05:33 -08:00
Michael Scire
97157577ab fusee: sdram scratch fixes 2021-01-05 11:05:33 -08:00
Michael Scire
6d65aa7e72 fusee: implement mariko warmboot firmware cache 2021-01-05 11:05:33 -08:00
Michael Scire
601c4516bf fusee/exo: fixes to allow booting (sleep broken until warmboot cache implemented) 2021-01-05 11:05:33 -08:00
Michael Scire
192ea926f6 fusee: commit pre-rendered splash binary 2021-01-05 11:05:33 -08:00
hexkyz
f1d320b6b6 fusee: fix regulator configuration 2021-01-05 11:05:33 -08:00
Michael Scire
6b3a3ecb44 fusee: execute more ccplex boot code out of iram 2021-01-05 11:05:33 -08:00
Michael Scire
dcfd01cf59 fusee: use pre-rendered splash screen instead of bmp 2021-01-05 11:05:33 -08:00
Michael Scire
4b09b5d5ce fusee: minor hwinit fixes 2021-01-05 11:05:33 -08:00
hexkyz
f6833a794a fusee: fix cluster bringup for mariko 2021-01-05 11:05:33 -08:00
Michael Scire
b7895ff2a7 fusee: fix support for mariko key derivation/package1 parsing 2021-01-05 11:05:33 -08:00
Michael Scire
f7898f3519 fusee: add special log level for sd card debug 2021-01-05 11:05:33 -08:00
Michael Scire
96f3c0c387 fusee/sept: build fixes 2021-01-05 11:05:33 -08:00
hexkyz
f4e763ce40 fusee: fix mariko master key derivation 2021-01-05 11:05:33 -08:00
hexkyz
a05e87f78a fusee: cleanup code and start fleshing out mariko keygen 2021-01-05 11:05:33 -08:00
hexkyz
4809ced64d fusee: start fleshing out nxboot for Mariko 2021-01-05 11:05:33 -08:00
hexkyz
222300d03c fusee: accurately match Mariko pk1ldr 2021-01-05 11:05:33 -08:00
hexkyz
b918d4b2aa fusee: 11.0.0 support 2021-01-05 11:05:33 -08:00
hexkyz
53c684a17a fusee/sept: delegate SoC selection to individual components and keep common code SoC-agnostic 2021-01-05 11:05:33 -08:00
hexkyz
4ffdf8d525 fusee: artificially raise main length to avoid elf compilation issues (final size will be much smaller) 2021-01-05 11:05:33 -08:00
hexkyz
7480b6bb80 fusee: move dsi register write to the proper configuration list 2021-01-05 11:05:33 -08:00
hexkyz
3e8688e19e fusee: update display code for mariko 2021-01-05 11:05:33 -08:00
Michael Scire
3b05315616 fusee: fixup extents for chainloader/stack 2021-01-05 11:05:33 -08:00
Michael Scire
2b81ed7315 fusee-primary: fix reboot-to-self for decompressed code 2021-01-05 11:05:33 -08:00
Michael Scire
ff7e52a1c1 fusee/sept: fix fuse driver to not infinitely recurse on get_soc_type() 2021-01-05 11:05:33 -08:00
Michael Scire
e391f593de fusee: fixup common for primary 2021-01-05 11:05:33 -08:00
Michael Scire
f600dff961 fusee: uncompress fusee-primary, which is now getting pretty big. 2021-01-05 11:05:33 -08:00
hexkyz
8104beb2e0 fusee: implement mariko sdram params saving 2021-01-05 11:05:33 -08:00
hexkyz
4cd56f8423 fusee: mariko sdram initialization 2021-01-05 11:05:33 -08:00
hexkyz
198bdacaf4 fusee: initial mariko hwinit 2021-01-05 11:05:33 -08:00
hexkyz
35ab0939fa fusee: support mariko in sdmmc 2021-01-05 11:05:33 -08:00
hexkyz
4958d01153 fusee/sept: support mariko fuses 2021-01-05 11:05:33 -08:00
hexkyz
b625fd324e fusee/sept: update fuse driver code 2021-01-05 11:05:33 -08:00
hexkyz
5e342d8c52 fusee: fix sdmmc speed modes 2021-01-05 11:05:33 -08:00
hexkyz
d233b482fb fusee: update FatFs to R0.14 2021-01-05 11:05:33 -08:00
hexkyz
3e2f776184 fusee/sept: isolate common code for mariko preparation (to be revised during C++ rewrite) 2021-01-05 11:05:33 -08:00
Michael Scire
7a9018dc7a sm: fix wait list reentrancy and state on processing loop entry 2020-12-31 16:01:26 -08:00
Michael Scire
f768e3c8f9 sm: implement accurate request deferral semantics 2020-12-31 16:01:26 -08:00
tuxuser
d42f2e4d1b Add lz4 dependency to the build instructions (#1308)
* Add lz4 dependency to the build instructions

At build-time of exosphere, the `split_program.py` script is called.
It requires python module `lz4` -> https://github.com/Atmosphere-NX/Atmosphere/blob/master/exosphere/program/split_program.py

Adding lz4 to the building.md documentation.

* Remove "(Python Library)" from deps-entries
2020-12-31 12:29:17 -08:00
Michael Scire
24111d46a1 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "b05ba02f"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "b05ba02f"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-29 13:08:25 -08:00
Michael Scire
f2a6a4a6e6 fusee: fix sept enc header dependency 2020-12-29 13:07:48 -08:00
Michael Scire
6633af769e boot: fix rebuild-every-time-make-is-invoked 2020-12-29 13:01:06 -08:00
Michael Scire
131c8609c8 libmeso: explicitly blacklist ::sdmmc::, instead of relying on incorrect board tricks 2020-12-29 12:36:26 -08:00
Michael Scire
30e70e20d8 strat: fix board namespacing for nintendo::nx 2020-12-29 12:30:43 -08:00
Michael Scire
a26e8ac54f ams: resolve source dir inconsistency 2020-12-29 12:28:07 -08:00
Michael Scire
8bfda27e0e kern: remove target-firmware logic for kernel loader 2020-12-29 12:21:41 -08:00
Michael Scire
0c9cb830f7 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "be8388d6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "be8388d6"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-28 17:34:31 -08:00
Michael Scire
ee1b638dde svc: we support kernel version 15.4 2020-12-28 17:33:45 -08:00
Michael Scire
9826358533 ams: update five -> aula, per CalWriterManu 2020-12-28 15:54:25 -08:00
Michael Scire
113ab8439d kern: fix KTrace buffer memory region type to match official kernel 2020-12-28 00:57:45 -08:00
ameerj
60c888126b fix typo in KServerPort::Destroy() 2020-12-25 20:23:10 -08:00
Michael Scire
d7b14f48d2 fusee: fix no-BCT.ini for fusee-secondary 2020-12-19 12:08:05 -08:00
Michael Scire
1085ccbe60 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "886dfaf6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "886dfaf6"
git-subrepo:
  version:  "0.4.0"
  origin:   "???"
  commit:   "???"
2020-12-19 10:22:37 -08:00
Michael Scire
8b61537aa3 ams: bump version to 0.16.2 2020-12-19 10:21:15 -08:00
Michael Scire
968f50bc07 kern: refactor to use m_ for member variables 2020-12-18 13:31:01 -08:00
Michael Scire
0bf2ade76f ams: use default bct0 by default 2020-12-18 13:27:52 -08:00
Adubbz
35a6705d55 git subrepo pull troposphere/daybreak/nanovg/ 2020-12-17 17:19:54 -08:00
Michael Scire
b8471bcd4e loader: correct GetCapabilityId allowal 2020-12-17 04:10:25 -08:00
Michael Scire
f7e83a72a9 kern: fix generic KDevicePageTable 2020-12-16 14:33:07 -08:00
Michael Scire
f6b847177a kern: fix LegacyNFiq interrupt ID 2020-12-16 14:28:24 -08:00
Michael Scire
a6d40e85f1 kern: fix linear region printing output 2020-12-14 21:18:14 -08:00
Michael Scire
6a81206373 pgl: add new snapshotdump logic 2020-12-14 19:31:05 -08:00
Michael Scire
4be5733c8e pgl: update for 11.0.0 behavior 2020-12-14 19:16:18 -08:00
Michael Scire
8dcb07152e creport: update for 11.0.0 behavior 2020-12-14 19:15:49 -08:00
Michael Scire
3b5dff0f83 pm: since 9.0.0, exceptions are signaled only once 2020-12-14 18:53:16 -08:00
Michael Scire
1ca373cd71 set.mitm: add setting for controlling DebugModeFlag for am 2020-12-14 15:56:04 -08:00
Michael Scire
4ff026224e kern: fix inverted conditional in waiter debug print 2020-12-14 10:32:49 -08:00
Michael Scire
2c39efea4c r2p: bring in line with other defs 2020-12-14 10:01:07 -08:00
Michael Scire
16cd1141d1 kern: fix some typos/naming semantics 2020-12-12 05:36:48 -08:00
Michael Scire
4b71e3a87e kern: implement process cpu utilization debug 2020-12-12 05:34:31 -08:00
Michael Scire
d090a7886d kern: add kernel thread utilization debug 2020-12-12 05:02:23 -08:00
Michael Scire
9a6cca7499 kern: add page table contents debug 2020-12-11 19:30:48 -08:00
Michael Scire
1ec2c0c2cb git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "59b4e750"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "59b4e750"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-11 05:02:58 -08:00
Michael Scire
569e1bc650 kern: cfi fix pt 2 2020-12-11 04:59:20 -08:00
Michael Scire
652e9bf9e8 kern: fix cfi (requires x18 not cleared on return to userland) 2020-12-11 04:53:25 -08:00
Michael Scire
ca2cc5e179 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "5a18bea6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "5a18bea6"
git-subrepo:
  version:  "0.4.1"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "a04d8c2"
2020-12-11 03:49:45 -08:00
Michael Scire
17c8c390fc kern: fix building debug config 2020-12-11 03:48:34 -08:00
Michael Scire
d8ae1d873c ams: update changelog for 0.16.1 2020-12-11 03:22:28 -08:00
Michael Scire
63e3c02688 fusee/exo: support dynamic control of invert flag for logging 2020-12-11 03:18:21 -08:00
Michael Scire
14a415c4b2 ams: bump version to 0.16.1 2020-12-11 03:06:47 -08:00
Michael Scire
734122f20a fusee: update for 11.0.1 2020-12-11 03:06:17 -08:00
Michael Scire
7fb902d8fb kern: update for 11.0.1 2020-12-11 02:59:09 -08:00
Michael Scire
be8473cf65 kern: implement memory debug 2020-12-10 16:32:19 -08:00
Michael Scire
6df26d674c kern/sm: fix debug port output 2020-12-10 04:06:02 -08:00
Michael Scire
1a6e003a5d kern: add kernel object debug 2020-12-10 03:31:57 -08:00
Michael Scire
0acd79c8c2 kern: implement port debug 2020-12-10 01:44:27 -08:00
Michael Scire
8a4bf6a0a8 kern: add handle table/process/suspend/resume debug 2020-12-09 23:44:36 -08:00
Michael Scire
af259eabda kern: implement thread call stack debug 2020-12-09 22:49:04 -08:00
Michael Scire
16e2f46aed fatal: prevent crash on fatal from currently-debugged process 2020-12-09 06:45:19 -08:00
Michael Scire
bcc7eed037 kern: add debug thread dump 2020-12-09 05:59:54 -08:00
Michael Scire
abd7ad2720 meso: properly initialize per-thread CFI-value for 11.x 2020-12-08 16:16:49 -08:00
Michael Scire
58c3c8c19a fusee: take three tries for a basic assignment 2020-12-07 19:34:13 -08:00
Michael Scire
f62330c73b fusee: update for exo flags arr-type 2020-12-07 19:33:29 -08:00
Michael Scire
2de85c633a exo/meso/fusee: support dynamic control of log port/baud rate 2020-12-07 19:25:06 -08:00
Michael Scire
121c981bb4 sept: be more forgiving about entrypoint 2020-12-07 03:20:01 -08:00
Michael Scire
15396dbbc2 fs: add ProgramIndexMapInfo 2020-12-07 01:03:39 -08:00
Michael Scire
9ca1d3a7f7 loader: fix process handle management on create process error 2020-12-06 21:20:42 -08:00
Michael Scire
32803d9920 fs: update + consolidate path normalization logic 2020-12-06 19:56:45 -08:00
Michael Scire
5ef93778f6 fs: move file storage to common 2020-12-05 03:31:12 -08:00
Michael Scire
7548940efa IStorage: rename access check helpers 2020-12-05 03:15:48 -08:00
Michael Scire
bf55776241 fsa: *Impl -> Do* 2020-12-05 03:05:06 -08:00
Michael Scire
73167448cc fs/system: deduplicate RomFs code 2020-12-04 22:08:33 -08:00
Michael Scire
c45088d1cd kern: add support for InfoType_FreeThreadCount 2020-12-04 18:20:56 -08:00
Michael Scire
7336dc2b7a git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "2c3ccef1"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "2c3ccef1"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-03 12:54:44 -08:00
Michael Scire
d2f48d5e36 err: fix narrowing conversion 2020-12-03 12:53:20 -08:00
Michael Scire
422e9434d8 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "49c1ace8"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "49c1ace8"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-03 12:48:41 -08:00
Michael Scire
2b93bbd9ee git subrepo pull emummc
subrepo:
  subdir:   "emummc"
  merged:   "5eed18eb"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "5eed18eb"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-03 12:48:06 -08:00
Michael Scire
021b29d2db erpt: give access to ectx:r 2020-12-03 11:22:18 -08:00
Michael Scire
6da28f4a27 erpt: update for 11.0.0 (closes #1218) 2020-12-03 11:13:35 -08:00
Michael Scire
bba99d49da kern: fix inverted conditional in UnmapProcessCodeMemory 2020-12-02 11:31:50 -08:00
Michael Scire
e760a9d4b0 kern: fix reboot to fatal error 2020-12-02 11:31:15 -08:00
Michael Scire
ee91f3fde0 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "78510a74"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "78510a74"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-02 10:00:52 -08:00
Michael Scire
f72475872a exo: add new dram IDs 2020-12-02 09:59:53 -08:00
Michael Scire
199a9aec8b exo: explicitly TODO the warmboot magic 2020-12-02 09:16:34 -08:00
Michael Scire
1b83f5169a docs: typo 2020-12-02 08:36:35 -08:00
Michael Scire
7bb77f44af docs: clarify wording 2020-12-02 08:36:19 -08:00
Michael Scire
801ce24622 docs: usb homebrew is broken, not ams's fault but worth mentioning 2020-12-02 08:28:44 -08:00
Michael Scire
1d778b2dc8 docs: update changelog for 0.16.0 2020-12-02 08:23:05 -08:00
Michael Scire
7c9608021d git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "8233fa00"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "8233fa00"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-02 06:55:24 -08:00
Michael Scire
b8fbd0baff fssystem: fix bug in BufferedStorage 2020-12-02 06:48:42 -08:00
Michael Scire
525da05629 erpt: update category list 2020-12-02 06:47:50 -08:00
Michael Scire
2e9db4d113 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "6fd752da"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "6fd752da"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-12-02 06:45:38 -08:00
Michael Scire
4f1a4e7499 kernel patches: fuck armconverter.com 2020-12-02 06:43:37 -08:00
Michael Scire
972283032a kern: tweak KScopedAutoObject 2020-12-02 06:43:37 -08:00
Michael Scire
57f935391d kern: allow non-inline GetObjectForIpc 2020-12-02 06:43:37 -08:00
Michael Scire
4804e1e1e0 kern: fix KHandleTable null deref in ipc 2020-12-02 06:43:37 -08:00
Michael Scire
4ae74b9b4e kern: session mapping getters are on the hotpath 2020-12-02 06:43:37 -08:00
Michael Scire
726d7b6e4d kern: tweak optimization settings for hot paths 2020-12-02 06:43:37 -08:00
Michael Scire
390bdc7b6b kern: more iterator adjustments 2020-12-02 06:43:37 -08:00
Michael Scire
2d8acf9c64 strat: add new npdm field 2020-12-02 06:43:37 -08:00
Michael Scire
9743f63f0d ams.mitm: fix old hid api references 2020-12-02 06:43:37 -08:00
Michael Scire
ccd2798ae2 ams: this version will be 0.16.0 2020-12-02 06:43:37 -08:00
Adubbz
f3dbab4876 daybreak: update for hid refactor (#1222) 2020-12-02 06:43:37 -08:00
Michael Scire
41a53075e5 hot path: just in case 2020-12-02 06:43:37 -08:00
Michael Scire
ab8de72db0 microkernel: hot paths are pretty fucking hot 2020-12-02 06:43:37 -08:00
Michael Scire
331fa1d00d kern: update KConditionVariable to support new has_waiter_flag rules 2020-12-02 06:43:37 -08:00
Michael Scire
fd745ab2d3 kern: fix SvcGetResourceLimitPeakValue 2020-12-02 06:43:37 -08:00
Michael Scire
972b396f61 kern: fix copy/paste error 2020-12-02 06:43:37 -08:00
Michael Scire
3c8e7de915 kern: fix bugs caused by UB + transition to -Os 2020-12-02 06:43:37 -08:00
Michael Scire
1b164613a6 loader: support 11.x DisableDeviceAddressSpaceMerge 2020-12-02 06:43:37 -08:00
Michael Scire
3d4ab95ab2 kern: allow non-inline KSchedulerLock::Lock 2020-12-02 06:43:37 -08:00
Michael Scire
152def19c0 kern: build as -Os instead of -O2 2020-12-02 06:43:37 -08:00
Michael Scire
63974d9bce kern: reduce KMemoryRegionAllocator slab size 2020-12-02 06:43:37 -08:00
Michael Scire
2b483866c7 kern: assume that uart has been setup by secmon 2020-12-02 06:43:37 -08:00
Michael Scire
7e1da15f6e kern: update Initialize0 to account for new ordering 2020-12-02 06:43:37 -08:00
Michael Scire
0a1465f198 kern: add new overflow checks on KMemoryRegions 2020-12-02 06:43:37 -08:00
Michael Scire
748893fe77 kern: fix assertion in the multi-region pool partition code 2020-12-02 06:43:37 -08:00
Michael Scire
1ca64cf2a1 kern: improve KMemoryManager pool detection 2020-12-02 06:43:37 -08:00
Michael Scire
aac8af8bf5 kern: update KMemoryRegion to store last address rather than size 2020-12-02 06:43:37 -08:00
Michael Scire
5da6b60008 kern: add KAlpha/KBeta 2020-12-02 06:43:37 -08:00
Michael Scire
e400e2afc7 kern: stubs for Svc39, 3A, 46, 47 2020-12-02 06:43:37 -08:00
Michael Scire
56c6e4244a kern: remove now unused SetupFor*Compare funcs 2020-12-02 06:43:37 -08:00
Michael Scire
c8ebd7eea0 KConditionVariable/KAddressArbiter: no need for global compare thread 2020-12-02 06:43:37 -08:00
Michael Scire
550f5690bf kern: set EL2 id registers on deprivilege 2020-12-02 06:43:37 -08:00
Michael Scire
28f9b534b6 kern: implement 64-virtual-core interface 2020-12-02 06:43:37 -08:00
fincs
3fd59b61bc reboot_to_payload: Update for new libnx HID interface 2020-12-02 06:43:37 -08:00
fincs
f86059de70 strat/cfg: Update for new libnx HID interface 2020-12-02 06:43:37 -08:00
fincs
a03ee7b148 strat/hid: Update for new libnx HID interface 2020-12-02 06:43:37 -08:00
Michael Scire
8b2ed36698 kern: cleanup KThread, optimize/normalize KThreadQueue/KWaitObject 2020-12-02 06:43:37 -08:00
Michael Scire
1852fe8612 kern: improve KSynchronizationObject, kill KSynchronization 2020-12-02 06:43:37 -08:00
Michael Scire
b60054dba1 kern: update for new interrupt event locking scheme 2020-12-02 06:43:37 -08:00
Michael Scire
c7f37f81ee kern: fix sleep save/resume for new x18/tpidr scheme 2020-12-02 06:43:37 -08:00
Michael Scire
19a279ce45 kern: fix race-crash on interrupt controller save, improve fatal output 2020-12-02 06:43:37 -08:00
Michael Scire
783f1077be kern: KObjectContainer::Register -> void 2020-12-02 06:43:37 -08:00
Michael Scire
b0debd72a7 kern: Kill KCoreLocalRegion 2020-12-02 06:43:37 -08:00
Michael Scire
24d545701c kern: remove more of clc 2020-12-02 06:43:37 -08:00
Michael Scire
aae565629e kern: move scheduler/interrupt task manager out of core local region 2020-12-02 06:43:37 -08:00
Michael Scire
bee629b8ad kern: update KHardwareTimer, move out of KCoreLocalRegion 2020-12-02 06:43:37 -08:00
Michael Scire
5cb237d030 kern: use single interrupt manager object 2020-12-02 06:43:37 -08:00
Michael Scire
a4e09fc6c4 kern: fix unnecessary align-down 2020-12-02 06:43:37 -08:00
Michael Scire
73d9d5ff47 kern: fix error in SeparatePages 2020-12-02 06:43:37 -08:00
Michael Scire
08cfee54fa kern: fix re-order/assert in KMemoryBlock 2020-12-02 06:43:37 -08:00
Michael Scire
7b279ab863 kern: remove KPageTableBase::MakeAndOpenContiguousPageGroup 2020-12-02 06:43:37 -08:00
Michael Scire
6a85f7225d kern: implement DisableDeviceAddressSpaceMerge 2020-12-02 06:43:37 -08:00
Michael Scire
f469dfbeb3 kern: SvcGetResourceLimitPeakValue 2020-12-02 06:43:37 -08:00
Michael Scire
cc11d452e5 kern: KMemoryManager::Allocate -> AllocateAndOpen 2020-12-02 06:43:37 -08:00
Michael Scire
3bce008170 kern: implement kmemoryblock/kmemoryinfo merge disable 2020-12-02 06:43:37 -08:00
Michael Scire
3383509da6 kern: remove KMemoryAttribute_AnyLocked 2020-12-02 06:43:37 -08:00
Michael Scire
281dcf232a kern: update KMemoryBlockManagerUpdateAllocator api 2020-12-02 06:43:37 -08:00
Michael Scire
71a2fe1bb6 kern: implement new software-reserved page table bits 2020-12-02 06:43:37 -08:00
Michael Scire
4a216dc928 kern: update KPageTableBase for new disable-merge attrs 2020-12-02 06:43:37 -08:00
Michael Scire
18099e19b1 fusee: recognize/support 11.x kernel 2020-12-02 06:43:37 -08:00
Michael Scire
a0a45853dd nogc: update for new lafw 2020-12-02 06:43:37 -08:00
Michael Scire
fe9a4cd2fc fusee: whoops 2020-12-02 06:43:37 -08:00
Michael Scire
88a66c89e2 fusee: fix 11.x pk21 support 2020-12-02 06:43:37 -08:00
Michael Scire
93128b6b17 fusee-secondary: update for 11.0.0 erista 2020-12-02 06:43:37 -08:00
Michael Scire
db2de8ef31 erpt: lightly update (TODO: use context, do new svc stuff) 2020-12-02 06:43:37 -08:00
Michael Scire
05832cec73 sm: implement UserService::DetachClient 2020-12-02 06:43:37 -08:00
Michael Scire
632c8984c8 loader: update for 11.0.0 (anti-dg + set program args abi) 2020-12-02 06:43:37 -08:00
Michael Scire
694e3b579e pgl: update for 11.0.0 2020-12-02 06:43:37 -08:00
Michael Scire
20eba0dc98 fs: nogc patches for 11.0.0 2020-12-02 06:43:37 -08:00
Michael Scire
730ef6d6db emummc: untested 11.0.0 support 2020-12-02 06:43:37 -08:00
Michael Scire
7cb24713ab kldr: update for 11.0.0 2020-12-02 06:43:37 -08:00
Michael Scire
a685842804 exo: update for 11.0.0 2020-12-02 06:43:37 -08:00
Michael Scire
ad6dd60474 result: update for accurate ::Includes 2020-12-02 06:43:37 -08:00
Michael Scire
05af215191 erpt: add update autogenerated ids 2020-12-02 06:43:37 -08:00
hexkyz
e06b73aafa boot: add missing RegisterWrite in DisplayConfigDsi01Init03 2020-11-30 19:35:06 +00:00
Michael Scire
fd7e4dfb97 ncm: fix abort in ListContentMetaInfo 2020-11-29 19:00:15 -08:00
Lusamine
77d7e6b121 Correct some occurrences of "occured" (#1213)
* Correct all occurrences of "occured"

* Correct some occurrences of "occured"
2020-11-25 06:29:09 -08:00
Michael Scire
ee9585dd57 git subrepo pull emummc
subrepo:
  subdir:   "emummc"
  merged:   "25075973"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "25075973"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-11-24 23:20:20 -08:00
Michael Scire
8ba513fefb fs: fix bug in buffer manager 2020-11-24 19:49:11 -08:00
ObscenityIB
ef4d7dc024 docs/building: missing required lib glm 2020-11-23 23:20:50 -08:00
Michael Scire
87512439a3 ams.mitm: fix reboot to payload/fatal error distinction 2020-11-22 10:28:23 -08:00
Michael Scire
51aeb280f1 exo/mariko fatal: add missing ( 2020-11-22 10:28:23 -08:00
Michael Scire
078a42f80c fusee: integrate mariko fatal. 2020-11-22 10:28:23 -08:00
Michael Scire
06dcc6bc17 exo/mariko fatal: disable backlight before we do screen re-init 2020-11-22 10:28:23 -08:00
Michael Scire
2bc6dec126 exo/mariko fatal: stop sound output on fatal error 2020-11-22 10:28:23 -08:00
Michael Scire
5382011b0d exo/mariko fatal: print descriptor for fatal error report 2020-11-22 10:28:23 -08:00
Michael Scire
8ba1cdeef2 exo/mariko fatal: perform display init, reboot on power button press 2020-11-22 10:28:23 -08:00
Michael Scire
45830472c1 exo/mariko fatal: halt other cores when beginning fatal program 2020-11-22 10:28:23 -08:00
Michael Scire
7f1a7cfd2d fs: fix RomFs GetEntryType (fixes mariko daybreak) 2020-11-21 04:00:52 -08:00
Michael Scire
24eef96b15 os: remove completed TODO 2020-11-20 17:50:05 -08:00
Michael Scire
1ea49bdae3 os: do not use deprecated libnx ::virtmemReserve api 2020-11-20 17:48:58 -08:00
Michael Scire
c98f4f1ff6 strat: use 39-bit address space when available (new loader extension) 2020-11-20 17:02:32 -08:00
Michael Scire
dd56f8449f ldr/hbl: support address space width overrides 2020-11-20 16:57:07 -08:00
Michael Scire
835aa6b9db exo: fix building on release 2020-11-18 15:08:44 -08:00
Michael Scire
69f9fb8713 exo: receive saved lcd vendor from bl 2020-11-18 15:08:44 -08:00
Michael Scire
a843cc0ee7 fatal: restructure, skeleton disp 2020-11-18 15:08:44 -08:00
Michael Scire
b96b162b0b sdmmc: fix UHS-I tuning init for SD cards 2020-11-18 15:08:44 -08:00
Michael Scire
512fc8f9b1 sdmmc: various fixes + logging as bugs are debugged 2020-11-18 15:08:44 -08:00
Michael Scire
b32c9bf17c exo/mariko fatal: save fatal error binaries to the SD 2020-11-18 15:08:44 -08:00
Michael Scire
5f6942aec8 exo/mariko_fatal: add sdmmc write function 2020-11-18 15:08:44 -08:00
Michael Scire
a2c89a8f3f mariko fatal: map 0xC0000000 for framebuffer usage 2020-11-18 15:08:44 -08:00
Michael Scire
898fe61034 exo: read first two sd card sectors in mariko_fatal 2020-11-18 15:08:44 -08:00
Michael Scire
7bcd5c6e3b exo: implement start of mariko fatal handler 2020-11-18 15:08:44 -08:00
Michael Scire
123ed80dc7 boot: update DisplayConfigMipiCal01 to reflect newest boot sysmodule 2020-11-16 17:51:52 -08:00
Michael Scire
5dfe355df1 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "791681f5"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "791681f5"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-11-15 22:46:12 -08:00
Michael Scire
c77b76fbd2 emummc: add GetSocType/GetHardwareType utils 2020-11-15 22:45:31 -08:00
Michael Scire
1525c66de7 git subrepo clone --force --branch=develop https://github.com/m4xw/emummc
subrepo:
  subdir:   "emummc"
  merged:   "24bdbec8"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "24bdbec8"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-11-15 22:39:39 -08:00
Michael Scire
f72b21d665 exo: upload memory layout design document I use 2020-11-15 08:44:57 -08:00
Michael Scire
74da8a4885 exo: map stack region for mariko-only program 2020-11-15 08:43:55 -08:00
Michael Scire
cb7c6a5d8a exo: load mariko-only program during boot 2020-11-15 08:35:57 -08:00
Michael Scire
fc97237447 exo: add logging to boot under debug config 2020-11-15 03:24:04 -08:00
Michael Scire
a203ac3f80 exo: free space by moving keys to volatile iram, support logging under debug config 2020-11-15 02:47:44 -08:00
Michael Scire
2ef41f0027 exo: shuffle logic around to support debug code region in iram 2020-11-15 01:36:50 -08:00
Michael Scire
ee3a7e7740 exo: disable untranslated gpu accesses on mariko 2020-11-15 00:45:41 -08:00
Michael Scire
3c595994df exosphere: release, debug, audit configs 2020-11-14 14:40:16 -08:00
Michael Scire
b4c908ba9f exo/program: release, debug, audit configs 2020-11-14 14:14:07 -08:00
Michael Scire
c572024a5e rebootstub: audit/debug/release 2020-11-14 12:19:01 -08:00
Michael Scire
71a38ae74d libexo/sc7fw: support release/debug/audit 2020-11-14 12:17:38 -08:00
Michael Scire
f74527d93c libexosphere: support building under debug/audit configurations 2020-11-14 11:35:51 -08:00
Michael Scire
72f83ea43e exo: reserve a portion of iram for secure monitor debug (including code) 2020-11-14 11:11:41 -08:00
Michael Scire
43ef260c66 boot2: don't wait for bpc.mitm on mariko 2020-11-14 10:40:40 -08:00
Michael Scire
f2c553be1a bpc.mitm: don't mitm bpc on mariko 2020-11-14 10:34:13 -08:00
Michael Scire
304b9bfbd1 i2c: correct missing destruction 2020-11-14 03:37:51 -08:00
Michael Scire
1d8744164e ams.mitm: provide different boot0-protection for custom public key 2020-11-14 03:37:51 -08:00
Michael Scire
d587054f96 wec: whoops 2020-11-14 03:37:51 -08:00
Michael Scire
29facf6141 updater: don't overwrite custom-public-key BCTs 2020-11-14 03:37:51 -08:00
Michael Scire
b8c3128d16 pinmux: whoops 2020-11-14 03:37:51 -08:00
Michael Scire
b62aa044e4 boot/powctl/i2c: more miscellaneous fixes 2020-11-14 03:37:51 -08:00
Michael Scire
affdea9244 boot: various bugfixes (b/w logo displays now) 2020-11-14 03:37:51 -08:00
Michael Scire
fdab964e3d powctl: implement max17050 driver 2020-11-14 03:37:51 -08:00
Michael Scire
15c752f52d powctl: add battery driver logic (missing impl) 2020-11-14 03:37:51 -08:00
Michael Scire
28862f69f8 powctl: implement max17050 custom parameter init 2020-11-14 03:37:51 -08:00
Michael Scire
a20f278ede powctl: implement full bq24193 driver 2020-11-14 03:37:51 -08:00
Michael Scire
7c58a21c4c i2c: add register acccessor helpers 2020-11-14 03:37:51 -08:00
Michael Scire
5bd02f128d powctl: add ChargerDriver body (needs impl) 2020-11-14 03:37:51 -08:00
Michael Scire
d9350d24a9 pinmux: implement updated initial config api 2020-11-14 03:37:51 -08:00
Michael Scire
68f42a14c8 boot: update/refactor display management to support hw type 5/display 0x1040/0x2050 2020-11-14 03:37:51 -08:00
Michael Scire
4d1c4f1677 dd: implement DeviceAddressSpaceType api 2020-11-14 03:37:51 -08:00
Michael Scire
708f5bf1fb boot: refactor battery checking to use new powctl apis 2020-11-14 03:37:51 -08:00
Michael Scire
485304bd17 powctl: implement client api (needs board-specific impl) 2020-11-14 03:37:51 -08:00
Michael Scire
3d31837ca1 pwm: implement driver for boot sysmodule 2020-11-14 03:37:51 -08:00
Michael Scire
35552bac2c gpio: add missing driver functions for boot 2020-11-14 03:37:51 -08:00
Michael Scire
323e893433 i2c: implement remaining required driver logic 2020-11-14 03:37:51 -08:00
Michael Scire
258cfb62a2 i2c: command list format, get boot down to linker errors 2020-11-14 03:37:51 -08:00
Michael Scire
42caa4ffd1 i2c/gpio: hook up open session for sf interface 2020-11-14 03:37:51 -08:00
Michael Scire
b74b309a77 i2c: implement driver init api 2020-11-14 03:37:51 -08:00
Michael Scire
09f3b29a98 i2c: finish I2cBusAccessor 2020-11-14 03:37:51 -08:00
Michael Scire
6c4280d27a i2c: implement BusAccessor::WriteHeader 2020-11-14 03:37:51 -08:00
Michael Scire
6ff58fa4b3 i2c: implement BusAccessor except Send/Receive/WriteHeader 2020-11-14 03:37:51 -08:00
Michael Scire
e5bf06254a boot: add rgltr/clkrst overrides, skel I2cBusAccessor 2020-11-14 03:37:51 -08:00
Michael Scire
f4e499fed9 i2c: add auto-generated bus/device map 2020-11-14 03:37:51 -08:00
Michael Scire
4a2daa4810 i2c: begin skeleton device driver framework 2020-11-14 03:37:51 -08:00
Michael Scire
21fac86080 gpio: remove copy-pasted unused file 2020-11-14 03:37:51 -08:00
Michael Scire
bd3ab76fd2 gpio: implement more of server library for boot sysmodule client usage 2020-11-14 03:37:51 -08:00
Michael Scire
e1b5d81d65 wec: implement wec driver components for boot sysmodule 2020-11-14 03:37:51 -08:00
Michael Scire
4b4f05b4a6 gpio: add (most of) driver framework for boot sysmodule usage 2020-11-14 03:37:51 -08:00
Michael Scire
ddf2f5f3c5 ddsf: implement namespace 2020-11-14 03:37:51 -08:00
Michael Scire
d2e530c2aa libstrat: fix precompiled-header dependency detection 2020-10-30 11:56:12 -07:00
SciresM
166318ba77 sdmmc: implement driver suitable for fs + bootloader
* sdmmc: begin skeletoning sdmmc driver

* sdmmc: add most of SdHostStandardController

* sdmmc: implement most of SdmmcController

* sdmmc: Sdmmc2Controller

* sdmmc: skeleton implementation of Sdmmc1Controller

* sdmmc: complete abstract logic for Sdmmc1 power controller

* sdmmc: implement gpio handling for sdmmc1-register-control

* sdmmc: implement pinmux handling for sdmmc1-register-control

* sdmmc: fix building for arm32 and in stratosphere context

* sdmmc: implement voltage enable/set for sdmmc1-register-control

* util: move T(V)SNPrintf from kernel to util

* sdmmc: implement BaseDeviceAccessor

* sdmmc: implement MmcDeviceAccessor

* sdmmc: implement clock reset controller for register api

* sdmmc: fix bug in WaitWhileCommandInhibit, add mmc accessors

* exo: add sdmmc test program

* sdmmc: fix speed mode extension, add CheckMmcConnection for debug

* sdmmc: add DeviceDetector, gpio: implement client api

* gpio: modernize client api instead of doing it the lazy way

* sdmmc: SdCardDeviceAccessor impl

* sdmmc: update test program to read first two sectors of sd card

* sdmmc: fix vref sel

* sdmmc: finish outward-facing api (untested)

* ams: changes for libvapours including tegra register defs

* sdmmc: remove hwinit
2020-10-30 11:54:30 -07:00
1449 changed files with 127721 additions and 157044 deletions

4
.gitignore vendored
View File

@@ -91,3 +91,7 @@ sept/sept-secondary/KEYS.py
**/out **/out
**/build **/build
**/build_nintendo_nx_arm64
**/build_nintendo_nx_arm
**/build_nintendo_nx_x64
**/build_nintendo_nx_x86

View File

@@ -78,7 +78,7 @@ dist-no-debug: all
cp sept/sept-secondary/sept-secondary_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_01.enc cp sept/sept-secondary/sept-secondary_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_01.enc
cp sept/sept-secondary/sept-secondary_dev_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_00.enc cp sept/sept-secondary/sept-secondary_dev_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_00.enc
cp sept/sept-secondary/sept-secondary_dev_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_01.enc cp sept/sept-secondary/sept-secondary_dev_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_01.enc
cp config_templates/BCT.ini atmosphere-$(AMSVER)/atmosphere/config/BCT.ini cp config_templates/BCT.ini atmosphere-$(AMSVER)/atmosphere/config_templates/BCT.ini
cp config_templates/override_config.ini atmosphere-$(AMSVER)/atmosphere/config_templates/override_config.ini cp config_templates/override_config.ini atmosphere-$(AMSVER)/atmosphere/config_templates/override_config.ini
cp config_templates/system_settings.ini atmosphere-$(AMSVER)/atmosphere/config_templates/system_settings.ini cp config_templates/system_settings.ini atmosphere-$(AMSVER)/atmosphere/config_templates/system_settings.ini
cp config_templates/exosphere.ini atmosphere-$(AMSVER)/atmosphere/config_templates/exosphere.ini cp config_templates/exosphere.ini atmosphere-$(AMSVER)/atmosphere/config_templates/exosphere.ini
@@ -99,14 +99,14 @@ dist-no-debug: all
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
cd atmosphere-$(AMSVER); zip -r ../atmosphere-EXPERIMENTAL-$(AMSVER).zip ./*; cd ../; cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER)-WITHOUT_MESOSPHERE.zip ./*; cd ../;
rm -r atmosphere-$(AMSVER) rm -r atmosphere-$(AMSVER)
mkdir out mkdir out
mv atmosphere-EXPERIMENTAL-$(AMSVER).zip out/atmosphere-EXPERIMENTAL-$(AMSVER).zip
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
mv atmosphere-$(AMSVER)-WITHOUT_MESOSPHERE.zip out/atmosphere-$(AMSVER)-WITHOUT_MESOSPHERE.zip
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
dist: dist-no-debug dist: dist-no-debug
@@ -131,6 +131,7 @@ dist: dist-no-debug
cp exosphere/loader_stub/loader_stub.elf atmosphere-$(AMSVER)-debug/exosphere-loader-stub.elf cp exosphere/loader_stub/loader_stub.elf atmosphere-$(AMSVER)-debug/exosphere-loader-stub.elf
cp exosphere/program/program.elf atmosphere-$(AMSVER)-debug/exosphere-program.elf cp exosphere/program/program.elf atmosphere-$(AMSVER)-debug/exosphere-program.elf
cp exosphere/warmboot/warmboot.elf atmosphere-$(AMSVER)-debug/exosphere-warmboot.elf cp exosphere/warmboot/warmboot.elf atmosphere-$(AMSVER)-debug/exosphere-warmboot.elf
cp exosphere/mariko_fatal/mariko_fatal.elf atmosphere-$(AMSVER)-debug/exosphere-mariko-fatal.elf
cp exosphere/program/sc7fw/sc7fw.elf atmosphere-$(AMSVER)-debug/exosphere-sc7fw.elf cp exosphere/program/sc7fw/sc7fw.elf atmosphere-$(AMSVER)-debug/exosphere-sc7fw.elf
cp exosphere/program/rebootstub/rebootstub.elf atmosphere-$(AMSVER)-debug/exosphere-rebootstub.elf cp exosphere/program/rebootstub/rebootstub.elf atmosphere-$(AMSVER)-debug/exosphere-rebootstub.elf
cp mesosphere/kernel_ldr/kernel_ldr.elf atmosphere-$(AMSVER)-debug/kernel_ldr.elf cp mesosphere/kernel_ldr/kernel_ldr.elf atmosphere-$(AMSVER)-debug/kernel_ldr.elf
@@ -140,15 +141,16 @@ dist: dist-no-debug
cp stratosphere/creport/creport.elf atmosphere-$(AMSVER)-debug/creport.elf cp stratosphere/creport/creport.elf atmosphere-$(AMSVER)-debug/creport.elf
cp stratosphere/dmnt/dmnt.elf atmosphere-$(AMSVER)-debug/dmnt.elf cp stratosphere/dmnt/dmnt.elf atmosphere-$(AMSVER)-debug/dmnt.elf
cp stratosphere/eclct.stub/eclct.stub.elf atmosphere-$(AMSVER)-debug/eclct.stub.elf cp stratosphere/eclct.stub/eclct.stub.elf atmosphere-$(AMSVER)-debug/eclct.stub.elf
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
cp stratosphere/fatal/fatal.elf atmosphere-$(AMSVER)-debug/fatal.elf cp stratosphere/fatal/fatal.elf atmosphere-$(AMSVER)-debug/fatal.elf
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
cp stratosphere/loader/loader.elf atmosphere-$(AMSVER)-debug/loader.elf cp stratosphere/loader/loader.elf atmosphere-$(AMSVER)-debug/loader.elf
cp stratosphere/ncm/ncm.elf atmosphere-$(AMSVER)-debug/ncm.elf
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
cp stratosphere/pm/pm.elf atmosphere-$(AMSVER)-debug/pm.elf cp stratosphere/pm/pm.elf atmosphere-$(AMSVER)-debug/pm.elf
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
cp troposphere/daybreak/daybreak.elf atmosphere-$(AMSVER)-debug/daybreak.elf cp troposphere/daybreak/daybreak.elf atmosphere-$(AMSVER)-debug/daybreak.elf
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../; cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
rm -r atmosphere-$(AMSVER)-debug rm -r atmosphere-$(AMSVER)-debug

View File

@@ -35,6 +35,17 @@
# mmc space, encrypted to prevent detection. This backup can be used # mmc space, encrypted to prevent detection. This backup can be used
# to prevent unrecoverable edits in emergencies. # to prevent unrecoverable edits in emergencies.
# Key: log_port, default: 0.
# Desc: Controls what uart port exosphere will set up for logging.
# NOTE: 0 = UART-A, 1 = UART-B, 2 = UART-C, 3 = UART-D
# Key: log_baud_rate, default: 115200
# Desc: Controls the baud rate exosphere will set up for logging.
# NOTE: 0 is treated as equivalent to 115200.
# Key: log_inverted, default: 0.
# Desc: Controls whether the logging uart port is inverted.
[exosphere] [exosphere]
debugmode=1 debugmode=1
debugmode_user=0 debugmode_user=0
@@ -43,3 +54,6 @@ enable_user_pmu_access=0
blank_prodinfo_sysmmc=0 blank_prodinfo_sysmmc=0
blank_prodinfo_emummc=0 blank_prodinfo_emummc=0
allow_writing_to_cal_sysmmc=0 allow_writing_to_cal_sysmmc=0
log_port=0
log_baud_rate=115200
log_inverted=0

View File

@@ -1,9 +1,10 @@
[hbl_config] [hbl_config]
; Program Specific Config ; Program Specific Config
; Up to 8 program-specific configurations can be set. ; Up to 8 program-specific configurations can be set.
; These use `program_id_#` and `override_key_#` ; These use `program_id_#`, `override_address_space_#`, and `override_key_#`
; where # is in range [0,7]. ; where # is in range [0,7].
; program_id_0=010000000000100D ; program_id_0=010000000000100D
; override_address_space=39_bit
; override_key_0=!R ; override_key_0=!R
; Any Application Config ; Any Application Config
@@ -12,6 +13,7 @@
; by a program specific config. ; by a program specific config.
; override_any_app=true ; override_any_app=true
; override_any_app_key=R ; override_any_app_key=R
; override_any_app_address_space=39_bit
; path=atmosphere/hbl.nsp ; path=atmosphere/hbl.nsp
[default_config] [default_config]

View File

@@ -38,6 +38,20 @@
; Please note this setting may be removed in a ; Please note this setting may be removed in a
; future release of Atmosphere. ; future release of Atmosphere.
; enable_deprecated_hid_mitm = u8!0x0 ; enable_deprecated_hid_mitm = u8!0x0
; Controls whether am sees system settings "DebugModeFlag" as
; enabled or disabled.
; 0 = Disabled (not debug mode), 1 = Enabled (debug mode)
; enable_am_debug_mode = u8!0x0
; Controls whether dns.mitm is enabled
; 0 = Disabled, 1 = Enabled
; enable_dns_mitm = u8!0x1
; Controls whether dns.mitm uses the default redirections in addition to
; whatever is specified in the user's hosts file.
; 0 = Disabled (use hosts file contents), 1 = Enabled (use defaults and hosts file contents)
; add_defaults_to_dns_hosts = u8!0x1
; Controls whether dns.mitm logs to the sd card for debugging
; 0 = Disabled, 1 = Enabled
; enable_dns_mitm_debug_log = u8!0x0
[hbloader] [hbloader]
; Controls the size of the homebrew heap when running as applet. ; Controls the size of the homebrew heap when running as applet.
; If set to zero, all available applet memory is used as heap. ; If set to zero, all available applet memory is used as heap.

View File

@@ -5,6 +5,7 @@ Building Atmosphère is a very straightforward process that relies almost exclus
+ [devkitA64](https://devkitpro.org) + [devkitA64](https://devkitpro.org)
+ [devkitARM](https://devkitpro.org) + [devkitARM](https://devkitpro.org)
+ [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed) + [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed)
+ [LZ4](https://pypi.org/project/lz4)
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional) + [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
## Instructions ## Instructions
@@ -12,16 +13,20 @@ Building Atmosphère is a very straightforward process that relies almost exclus
2. Install the following packages via (dkp-)pacman: 2. Install the following packages via (dkp-)pacman:
+ `switch-dev` + `switch-dev`
+ `switch-glm`
+ `switch-libjpeg-turbo` + `switch-libjpeg-turbo`
+ `devkitARM` + `devkitARM`
+ `devkitarm-rules` + `devkitarm-rules`
3. (Optional) In order to build [sept](components/sept.md) the pycryptodome PyPi package is required, which can be installed by running `pip install pycryptodome` under the installed Python environment of your choice or by installing the complete zip package to support the `make dist` recipe. This is an optional step included for advanced users who have the ability to provide the necessary encryption/signing keys themselves. 3. Install the following library via python's package manager `pip`, required by [exosphere](components/exosphere.md):
+ `lz4`
4. It is, instead, possible to build [sept](components/sept.md) by providing previously encrypted/signed binaries distributed by official Atmosphère release packages. In order to do so, export the following variables in your current environment: 4. (Optional) In order to build [sept](components/sept.md) the pycryptodome PyPi package is required, which can be installed by running `pip install pycryptodome` under the installed Python environment of your choice or by installing the complete zip package to support the `make dist` recipe. This is an optional step included for advanced users who have the ability to provide the necessary encryption/signing keys themselves.
5. It is, instead, possible to build [sept](components/sept.md) by providing previously encrypted/signed binaries distributed by official Atmosphère release packages. In order to do so, export the following variables in your current environment:
+ `SEPT_00_ENC_PATH` (must point to the `sept-secondary_00.enc` file) + `SEPT_00_ENC_PATH` (must point to the `sept-secondary_00.enc` file)
+ `SEPT_01_ENC_PATH` (must point to the `sept-secondary_01.enc` file) + `SEPT_01_ENC_PATH` (must point to the `sept-secondary_01.enc` file)
+ `SEPT_DEV_00_ENC_PATH` (must point to the `sept-secondary_dev_00.enc` file) + `SEPT_DEV_00_ENC_PATH` (must point to the `sept-secondary_dev_00.enc` file)
+ `SEPT_DEV_01_ENC_PATH` (must point to the `sept-secondary_dev_01.enc` file) + `SEPT_DEV_01_ENC_PATH` (must point to the `sept-secondary_dev_01.enc` file)
5. Finally, clone the Atmosphère repository and run `make` under its root directory. 6. Finally, clone the Atmosphère repository and run `make` under its root directory.

View File

@@ -1,4 +1,88 @@
# Changelog # Changelog
## 0.17.1
+ A number of atmosphère's modules were using more memory than their Nintendo equivalent's in 0.17.0; a number of code generatio tweaks have been applied to fix this across the board.
+ A detailed comparison of atmosphère module memory usage versus Nintendo's was made and can be found [here](https://github.com/Atmosphere-NX/Atmosphere/wiki/Memory-Comparisons).
+ Several minor bugs were fixed, including:
+ A bug was fixed in mesosphère that caused games which attempt to map more memory than the Switch has to fail.
+ This affected "Piczle Lines DX 500 More Puzzles!", and possibly other games.
+ Enabling configuration to "blank" PRODINFO no longer causes a hang on Mariko devices (or any devices with newer format).
+ Several issues were fixed, and usability and stability were improved.
## 0.17.0
+ fusee was heavily rewritten in order to add support for Mariko hardware.
+ **Please Note**: Mariko hardware currently has no (and may not ever have any) software exploits; fusee works when loaded from bootloader context with the right keys in the security engine. No means of getting the system into this state is provided.
+ An issue was fixed in the way shutdown was performed on Erista hardware.
+ This fixes an issue that caused OFW to black screen on boot after power off from atmosphere without first doing a reboot.
+ This also substantially improves power drain when the system is shut off; consoles powered off from Atmosphere should now drain battery at the same reduced rate as original firmware.
+ A number of minor changes were made, including:
+ A number of inconsistencies in the build system were fixed.
+ Fow those building atmosphère at home, the `boot` sysmodule will no longer rebuild every time make is invoked.
+ This substantially improves build times during development iteration.
+ `sm` was updated to more accurately reflect how official code manages request deferral.
+ `mesosphère` was updated to more accurately reflect official kernel management of the trace buffer.
+ `mesosphère` was updated to improve kernel loader's logic by taking advantage of the assumption that we only boot our kernel, not Nintendo's.
+ As it has been a few months with zero reported issues, `mesosphère` is now opt-out.
+ Users who wish to begin using or continue using mesosphere should use the standard/cool kids zip ("atmosphere-").
+ Users who wish to opt-out of mesosphere should download and extract the opt-out zip ("atmosphere-WITHOUT_MESOSPHERE-").
+ Several issues were fixed, and usability and stability were improved.
## 0.16.2
+ Atmosphère release zips no longer bundle BCT.ini, instead relying on defaults in code.
+ This means atmosphere updates should no longer overwrite any user configuration at all.
+ If you wish to modify BCT.ini config, copy the template from /config_templates/ as with other configuration.
+ `pgl` and `creport` were further updated to reflect differences in official behavior in 11.0.0.
+ An issue was fixed that caused creport to be launched multiple times on process crash.
+ This fixes the "duplicate reports" issue that sometimes plagued people.
+ A new system setting (`atmosphere!enable_am_debug_mode`) configuring am to use debug mode.
+ If you are not a developer or don't see a clear use for this, leave it configured to the default (off).
+ Reboot to payload NRO was updated to fix support with certain payloads.
+ Support was fixed for atmosphere's extension to support homebrew use of new (8.0.0+) kernel mappings.
+ In particular, when running tracing debug builds of `mesosphère`, hbloader now has access to the kernel trace buffer.
+ Several issues were fixed, and usability and stability were improved.
## 0.16.1
+ Support was added for 11.0.1.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ A new svc::InfoType added in 11.0.0 was implemented (it wasn't discovered before 0.16.0 released).
+ The new Control Flow Integrity (CFI) logic added in 11.0.0 kernel was implemented.
+ `fs` logic was refactored and cleaned up to reflect some newer sysmodule behavioral and structural changes.
+ `exosphère` was updated to allow dynamic control of what uart port is used for logging.
+ This can be controlled by editing the `log_port`, `log_baud_rate`, and `log_inverted` fields in `exosphere.ini`.
+ `mesosphère` was updated to improve debugging capabilities.
+ This is still a work in progress, but developers may be interested.
+ A bug was fixed that caused `fatal` to fatal error if the fatal process was already being debugged.
+ Several issues were fixed, and usability and stability were improved.
## 0.16.0
+ Support was added for 11.0.0.
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `loader`, `sm`, `boot`, `pgl` were updated to reflect the latest official behaviors.
+ **Please Note**: 11.0.0 implements an opt-in version of the atmosphère `sm` extension that allows for closing session without unregistering services.
+ Correspondingly, the extension will be deprecated in favor of the new official opt-in command. In 0.17.0, it will be removed entirely.
+ If your custom system module relies on this extension (however unlikely that seems to me), please update it accordingly.
+ `erpt` was partially updated to provide compatibility with 11.0.0.
+ The latest firmware attaches additional fields and context information to logs.
+ A future atmosphère update will implement this logic, so that users who are interested can also get the new information when examining their logs.
+ **Please Note**: 11.0.0 introduced breaking changes to the `usb` system module's `usb:ds` API.
+ Homebrew which uses the `usb:ds` service should rebuild with the latest libnx version to support running on 11.0.0.
+ The `boot` system module was rewritten to reflect the huge driver changes introduced in 8.0.0.
+ This includes a number of improvements to both logo display and battery management logic.
+ Support was added for configuring the address space width for `hbl`.
+ The `hbl_config!override_address_space_(#)` and `hbl_config!override_any_app_address_space` can now be set to `39_bit`, `36_bit`, or `32_bit` to control the address space for hbl on a per-override basis.
+ If a configuration has not been set, hbl will now default to 39-bit address space.
+ Previously, a legacy 36-bit address space was always used to maintain compatibility with 1.0.0.
+ A new loader extension was added to support 39-bit whenever possible (including mesosphere-on-1.0.0), with fallback to 36-bit when unavailable.
+ Support was added to a number of components for running on Mariko hardware.
+ The `boot` system module can now safely be run on mariko hardware, performing correct hardware initialization.
+ Daybreak (and generally, system update logic) were updated to be usable on Mariko.
+ Boot0 protection/management logic was updated to perform correct actions on Mariko.
+ Reboot to payload does not and cannot work on Mariko. Correspondingly, A "fatal error" handler was written, to display and save fatal errors from within TrustZone.
+ **Please Note:** Atmosphere is still not properly usable on Mariko hardware.
+ In particular, wake-from-sleep will not properly function (the magic numbers aren't set correctly), among a few other minor issues.
+ `exosphère` received support for building under debug configuration.
+ A small (otherwise unused) portion of IRAM is now reserved for debug-only exosphere code (this region is unused/untouched under release config).
+ This enables logging (including printf) to uart from the secure monitor, for those interested.
+ A number of bugs were fixed, including:
+ Minor issues in a number of filesystem related code were fixed.
+ An issue was fixed that could cause NCM to abort on consoles which came with 3.0.x and were never updated.
+ Several issues were fixed, and usability and stability were improved.
## 0.15.0 ## 0.15.0
+ fusee-primary's panic display was updated to automatically identify and give suggestions to resolve many of the most common errors users encounter. + fusee-primary's panic display was updated to automatically identify and give suggestions to resolve many of the most common errors users encounter.
+ Having been tested as well as I can alone, `mesosphere` (atmosphère's reimplementation of the Nintendo Switch kernel) is now available for users interested in trying it. + Having been tested as well as I can alone, `mesosphere` (atmosphère's reimplementation of the Nintendo Switch kernel) is now available for users interested in trying it.

View File

@@ -0,0 +1,103 @@
exosphere, storage requirements:
Nonvolatile memory:
0xE000
Volatile memory: 0x2000
Physical Address Space:
-0x7C010000-0x7C012000 - boot code/volatile memory
-0x7C012000-0x7C01E000 - program region
-0x7C01E000-0x7C01F000 - global data/context
-0x7C01F000-0x7C020000 - L2/L3 page table
-0x7C020000-0x7C040000 - Mariko-only program region
-0x7C040000-0x7C048000 - Mariko-only program stack
-0x7C048000-0x7C050000 - Reserved Mariko TZRAM (SE context carveouts, etc)
Virtual Address Space:
L1: 0x40 bytes.
L1 Entries:
-0 (0x000000000-0x040000000): Empty
-1 (0x040000000-0x080000000): Identity Mapping/Empty
-2 (0x080000000-0x0C0000000): DRAM Mapping/Empty
-3 (0x0C0000000-0x100000000): DRAM Mapping/Empty
-4 (0x100000000-0x140000000): Empty
-5 (0x140000000-0x180000000): Empty
-6 (0x180000000-0x1C0000000): Empty
-7 (0x1C0000000-0x200000000): Virtual Region
L2 Page and L3 page are both0x7C01F000
L2 Entries:
-0x040000000 (Identity IRAM Table)
- Entry Used: 0x000
-0x07C000000 (Identity TZRAM Table)
- Entry Used: 0x1E0
-0x1F0000000 (Virtual Region Table)
- Entry Used: 0x180
L3 Entries:
- Identity TZRAM mapping (0x7C010000-0x7C020000)
- Entry Used: 0x010-0x01F
- Identity IRAM mapping (0x40020000-0x40040000)
- Entry Used: 0x020-0x03F
- Virtual Device region (0x1F0040000-0x1F0080000)
- Entry Used: 0x040-0x07F
- Read Only TZRAM Alias (0x1F00A0000-0x1F00B0000)
- Entry Used: 0x0A0-0x0AF
- Program region (0x1F00C0000-0x1F00CC000)
- Entry Used: 0x0C0-0x0CB
- Mariko Program region (0x1F00D0000-0x1F00F0000)
- Entry Used: 0x0D0-0x0EF
- Mariko Program stack (0x1F00F4000-0x1F00FC000)
- Entry Used: 0x0F4-0x0FB
- Secure DRAM Storage (0x1F0100000-0x1F0110000)
- Entry Used: 0x100-0x10F
- Debug DRAM Storage (0x1F0110000-0x1F0114000)
- Entry Used: 0x110-0x113
- SC7 IRAM Work Space (0x1F0120000-0x1F0130000)
- Entry Used: 0x120-0x12F
- SC7 IRAM Firmware (0x1F0140000-0x1F0141000)
- Entry Used: 0x140-0x140
- Debug Code (0x1F0150000-0x1F0154000)
- Entry Used: 0x150-0x153
- Reserved For Debug (0x1F0160000-0x1F0170000)
- Entry Used: 0x160-0x16F
- Boot Code (0x1F01C0000-0x1F01C2000)
- Entry Used: 0x1C0-0x1C1
- AMS IRAM Page (0x1F01F2000-0x1F01F2000)
- Entry Used: 0x1F2-0x1F2
- AMS User Page (0x1F01F4000-0x1F01F4000)
- Entry Used: 0x1F4-0x1F4
- SMC User Page (0x1F01F6000-0x1F01F6000)
- Entry Used: 0x1F6-0x1F6
- Volatile (Data) (0x1F01F8000-0x1F01F9000)
- Entry Used: 0x1F8-0x1F8
- Volatile (Stacks) (0x1F01FA000-0x1F01FB000)
- Entry Used: 0x1FA-0x1FA
- Global Data (0x1F01FC000-0x1F01FD000)
NV Global Data needs:
Exosphere + Emummc Config (<=0x200)
Boot Config[0x400]
RSA Context(0x100)
Old Device Keys[0x20][0x10];
Old Master Keys[0x20][0x10];
Imported Rsa Keys[4][0x200];
CPU Ctx[4][0x100];
Total: 0x1700
Global Data Page (accessible via X18):
0x000-0x200: Exosphere Config
0x200-0x400: Emummc Config
0x400-0x800: Sealed AES Keys
0x800-0xC00: Boot Config
0xC00-0xFFF: CPU contexts. Can be replaced, but this fits exactly so minimizes program space waste.
Volatile Global Data needs:
Random Cache 0x400 bytes

View File

@@ -25,6 +25,12 @@ set_mitm enables intercepting requests to the system settings service. It curren
+ `ns` system module and games (to allow for overriding game locales) + `ns` system module and games (to allow for overriding game locales)
+ All firmware debug settings requests (to allow modification of system settings not directly exposed to the user) + All firmware debug settings requests (to allow modification of system settings not directly exposed to the user)
## dns_mitm
dns_mitm enables intercepting requests to dns resolution services, to enable redirecting requests for specified hostnames.
For documentation, see [here](../../features/dns_mitm.md).
### Firmware Version ### Firmware Version
set_mitm intercepts the `GetFirmwareVersion` command, if the requester is `qlaunch` or `maintenance`. set_mitm intercepts the `GetFirmwareVersion` command, if the requester is `qlaunch` or `maintenance`.
It modifies the `display_version` field of the returned system version, causing the version to display It modifies the `display_version` field of the returned system version, causing the version to display

51
docs/features/dns_mitm.md Normal file
View File

@@ -0,0 +1,51 @@
# DNS.mitm
As of 0.18.0, atmosphère provides a mechanism for redirecting DNS resolution requests.
By default, atmosphère redirects resolution requests for official telemetry servers, redirecting them to a loopback address.
## Hosts files
DNS.mitm can be configured through the usage of a slightly-extended `hosts` file format, which is parsed only once on system startup.
In particular, hosts files parsed by DNS.mitm have the following extensions to the usual format:
+ `*` is treated as a wildcard character, matching any collection of 0 or more characters wherever it occurs in a hostname.
+ `%` is treated as a stand-in for the value of `nsd!environment_identifier`. This is always `lp1`, on production devices.
Please note that homebrew may trigger a hosts file re-parse by sending the extension IPC command 65000 ("AtmosphereReloadHostsFile") to a connected `sfdnsres` session.
### Hosts file selection
Atmosphère will try to read hosts from the following file paths, in order, stopping once it successfully performs a file read:
+ (emummc only) `/atmosphere/hosts/emummc_%04lx.txt`, formatted with the emummc's id number (see `emummc.ini`).
+ (emummc only) `/atmosphere/hosts/emummc.txt`.
+ (sysmmc only) `/atmosphere/hosts/sysmmc.txt`.
+ `/atmosphere/hosts/default.txt`
If `/atmosphere/hosts/default.txt` does not exist, atmosphère will create it to contain the defaults.
### Atmosphère defaults
By default, atmosphère's default redirections are parsed **in addition to** the contents of the loaded hosts file.
This is equivalent to thinking of the loaded hosts file as having the atmosphère defaults prepended to it.
This setting is considered desirable, because it minimizes the telemetry risks if a user forgets to update a custom hosts file on a system update which changes the telemetry servers.
This behavior can be opted-out from by setting `atmosphere!add_defaults_to_dns_hosts = u8!0x0` in `system_settings.ini`.
The current default redirections are:
```
# Nintendo telemetry servers
127.0.0.1 receive-%.dg.srv.nintendo.net receive-%.er.srv.nintendo.net
```
## Debugging
On startup (or on hosts file re-parse), DNS.mitm will log both what hosts file it selected and the contents of all redirections it parses to `/atmosphere/logs/dns_mitm_startup.log`.
In addition, if the user sets `atmosphere!enable_dns_mitm_debug_log = u8!0x1` in `system_settings.ini`, DNS.mitm will log all requests to GetHostByName/GetAddrInfo to `/atmosphere/logs/dns_mitm_debug.log`. All redirections will be noted when they occur.
## Opting-out of DNS.mitm entirely
If you wish to disable DNS.mitm entirely, `system_settings.ini` can be edited to set `atmosphere!enable_dns_mitm = u8!0x0`.

View File

@@ -1,42 +1,32 @@
# Planned Features # Planned Features
atmosphère has a number of features that are either works-in-progress or planned. Please note that while time-estimates are given, they are loose, and things may be completed sooner or later than advertised. atmosphère has a number of features that are either works-in-progress or planned. Please note that while time-estimates are given, they are loose, and things may be completed sooner or later than advertised.
The following descriptions were last updated on July 7th, 2020. The following descriptions were last updated on January 14th, 2021
## ams-on-mariko
* **Description**: Atmosphere cannot run as-is on Mariko hardware. A large number of changes are needed in many components. Although secure monitor support is complete in exosphere, additional work is needed on the bootloader and stratosphere sides as well. Mariko support will also require further design thought; atmosphere's debugging design heavily relies on reboot-to-payload and (more generally) the ability to perform warmboot bootrom hax at will. This is not possible on Mariko, and will require a new design/software support for whatever solution is chosen.
* **Development Status**: Planned.
* **Estimated Time**: Summer 2020
## settings reimplementation
* **Description**: A planned reimplementation of the settings system module, and with it a removal of the settings mitm. This will greatly simplify atmosphère's boot process, and will allow much more flexible control over the various system settings.
* **Development Status**: Undergoing research/initial development by Adubbz.
* **Estimated Time**: Mid 2020
## mesosphere
* **Description**: mesosphère is a reimplementation of the Horizon operating system's Kernel. It aims to provide an open-source reference for Nintendo's code.
* **Development Status**: Under active development by SciresM.
* **Estimated Time**: Mid-to-Late 2020
## tma reimplementation ## tma reimplementation
* **Description** tma ("target manager agent") is a system module that manages communication between the Switch and a client PC. Atmosphere's implementation will allow homebrew on the switch to communicate with a connected PC to do various operations such as exchanging data or interacting with files. It will also serve as the communicator for Atmosphère's planned debugger. This will also include PC-side software for interacting with the Switch. * **Description** tma ("target manager agent") is a system module that manages communication between the Switch and a client PC. Atmosphere's implementation will allow homebrew on the switch to communicate with a connected PC to do various operations such as exchanging data or interacting with files. It will also serve as the communicator for Atmosphère's planned debugger. This will also include PC-side software for interacting with the Switch.
* **Development Status**: Planned. Switch-side code is fully implemented but needs heavy refactoring/rebasing, as the code was originally authored in 2018. * **Development Status**: Planned. Switch-side code is fully implemented but needs heavy refactoring/rebasing, as the code was originally authored in 2018.
* **Estimated Time**: Late 2020-2021. * **Estimated Time**: 2021-2022.
## dmnt.gen2 reimplementation ## dmnt.gen2 reimplementation
* **Description**: A reimplementation of the Switch's debug monitor, dmnt will provide an interface for debugging applications or system modules running on the Switch. This will include a gdbstub for debugging actively-running system components or applications. * **Description**: A reimplementation of the Switch's debug monitor, dmnt will provide an interface for debugging applications or system modules running on the Switch. This will include a gdbstub for debugging actively-running system components or applications.
* **Development Status**: Planned * **Development Status**: Planned
* **Estimated Time**: 2021 * **Estimated Time**: 2021-2022
## fs reimplementation ## fs reimplementation
* **Description**: Following mesosphère's completion, atmosphère will have reimplemented all components of the BootImagePackage firmware except for the filesystem services system module. Reimplementing fs will allow for fixing Nintendo bugs (such as corruption when using exFAT filesystems and encoding inconsistencies with UTF-8 and Shift-JIS). * **Description**: Following mesosphère's completion, atmosphère will have reimplemented all components of the BootImagePackage firmware except for the filesystem services system module. Reimplementing fs will allow for fixing Nintendo bugs (such as corruption when using exFAT filesystems and encoding inconsistencies with UTF-8 and Shift-JIS).
* **Development Status**: Planned. * **Development Status**: Planned.
* **Estimated Time**: 2021-2022. * **Estimated Time**: 2021-2022.
## settings reimplementation
* **Description**: A planned reimplementation of the settings system module, and with it a removal of the settings mitm. This will greatly simplify atmosphère's boot process, and will allow much more flexible control over the various system settings.
* **Development Status**: Pending development by Adubbz.
* **Estimated Time**: Unclear, pending developer availability.
## thermosphère ## thermosphère
* **Description**: A general-purpose hypervisor, thermosphère will enable the virtualization of the Switch's operating system; this is planned to enable debugging of the Switch's kernel. * **Description**: A general-purpose hypervisor, thermosphère will enable the virtualization of the Switch's operating system; this is planned to enable debugging of the Switch's kernel.
* **Development Status**: Under semi-active development by TuxSH. * **Development Status**: Pending development by TuxSH.
* **Estimated Time**: 2020-2021. * **Estimated Time**: Unclear, pending developer availability.
## other planned features ## other planned features
* **Description**: General system stability improvements to enhance the user's experience. * **Description**: General system stability improvements to enhance the user's experience.
@@ -59,4 +49,12 @@ Please note that this is not an exhaustive list of features present in atmosphè
## exosphere re-write ## exosphere re-write
* **Description**: exosphère, atmosphère's reimplementation of Horizon's Secure Monitor, was the first component authored for the project in early 2018. It is written in C, and in a style very different from the rest of atmosphère's code. In addition, exosphère was written to conform to constraints that no longer apply in an environment where it is not launched from the web browser, and where using a custom firmware image to orchestrate wake-from-sleep is possible. exosphère currently uses all but 1 KB of the space available to it, putting it at risk of breaking as future firmware updates are supported. A re-write will solve these issues. * **Description**: exosphère, atmosphère's reimplementation of Horizon's Secure Monitor, was the first component authored for the project in early 2018. It is written in C, and in a style very different from the rest of atmosphère's code. In addition, exosphère was written to conform to constraints that no longer apply in an environment where it is not launched from the web browser, and where using a custom firmware image to orchestrate wake-from-sleep is possible. exosphère currently uses all but 1 KB of the space available to it, putting it at risk of breaking as future firmware updates are supported. A re-write will solve these issues.
* **Completion Time**: June 2020 * **Completion Time**: June 2020
## mesosphere
* **Description**: mesosphère is a reimplementation of the Horizon operating system's Kernel. It aims to provide an open-source reference for Nintendo's code.
* **Estimated Time**: September 2020
## ams-on-mariko
* **Description**: Atmosphere cannot run as-is on Mariko hardware. A large number of changes are needed in many components. Although secure monitor support is complete in exosphere, additional work is needed on the bootloader and stratosphere sides as well. Mariko support will also require further design thought; atmosphere's debugging design heavily relies on reboot-to-payload and (more generally) the ability to perform warmboot bootrom hax at will. This is not possible on Mariko, and will require a new design/software support for whatever solution is chosen.
* **Completion Time**: January 2021

View File

@@ -5,8 +5,8 @@
; ;
[subrepo] [subrepo]
remote = https://github.com/m4xw/emuMMC remote = https://github.com/m4xw/emuMMC
branch = exo2 branch = develop
commit = 6a814ebbe72cf5245b863b9edea9cd3801437a12 commit = 5eed18eb527bbaa63aee5323c26de5b0cca6d28e
parent = f551ca4461a79908c37307db10cd8cacf8b98f17 parent = 021b29d2dbc8ed0469bc822393e58c9f0d174d57
method = rebase method = rebase
cmdver = 0.4.1 cmdver = 0.4.1

View File

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

View File

@@ -49,6 +49,8 @@
#include "offsets/1000_exfat.h" #include "offsets/1000_exfat.h"
#include "offsets/1020.h" #include "offsets/1020.h"
#include "offsets/1020_exfat.h" #include "offsets/1020_exfat.h"
#include "offsets/1100.h"
#include "offsets/1100_exfat.h"
#include "../utils/fatal.h" #include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers #define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -69,6 +71,7 @@ static const fs_offsets_t GET_OFFSET_STRUCT_NAME(vers) = { \
.nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \ .nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \
.active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \ .active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \
.sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \ .sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \
.sdmmc_accessor_controller_open = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_OPEN, \
.sdmmc_accessor_controller_close = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_CLOSE, \ .sdmmc_accessor_controller_close = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_CLOSE, \
.sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \ .sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \
.nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \ .nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \
@@ -108,6 +111,8 @@ DEFINE_OFFSET_STRUCT(_1000);
DEFINE_OFFSET_STRUCT(_1000_EXFAT); DEFINE_OFFSET_STRUCT(_1000_EXFAT);
DEFINE_OFFSET_STRUCT(_1020); DEFINE_OFFSET_STRUCT(_1020);
DEFINE_OFFSET_STRUCT(_1020_EXFAT); DEFINE_OFFSET_STRUCT(_1020_EXFAT);
DEFINE_OFFSET_STRUCT(_1100);
DEFINE_OFFSET_STRUCT(_1100_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) { const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) { switch (version) {
@@ -177,6 +182,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_1020)); return &(GET_OFFSET_STRUCT_NAME(_1020));
case FS_VER_10_2_0_EXFAT: case FS_VER_10_2_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT)); return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT));
case FS_VER_11_0_0:
return &(GET_OFFSET_STRUCT_NAME(_1100));
case FS_VER_11_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1100_EXFAT));
default: default:
fatal_abort(Fatal_UnknownVersion); fatal_abort(Fatal_UnknownVersion);
} }

View File

@@ -41,6 +41,7 @@ typedef struct {
// Misc funcs // Misc funcs
uintptr_t lock_mutex; uintptr_t lock_mutex;
uintptr_t unlock_mutex; uintptr_t unlock_mutex;
uintptr_t sdmmc_accessor_controller_open;
uintptr_t sdmmc_accessor_controller_close; uintptr_t sdmmc_accessor_controller_close;
// Misc data // Misc data
uintptr_t sd_mutex; uintptr_t sd_mutex;

View File

@@ -35,7 +35,7 @@ typedef struct sdmmc_accessor_vt
void *dtor; void *dtor;
void *map_device_addr_space; void *map_device_addr_space;
void *unmap_device_addr_space; void *unmap_device_addr_space;
void *controller_open; uint64_t (*sdmmc_accessor_controller_open)(void *);
uint64_t (*sdmmc_accessor_controller_close)(void *); uint64_t (*sdmmc_accessor_controller_close)(void *);
uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t); uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t);
// More not included because we don't use it. // More not included because we don't use it.

View File

@@ -71,6 +71,9 @@ enum FS_VER
FS_VER_10_2_0, FS_VER_10_2_0,
FS_VER_10_2_0_EXFAT, FS_VER_10_2_0_EXFAT,
FS_VER_11_0_0,
FS_VER_11_0_0_EXFAT,
FS_VER_MAX, FS_VER_MAX,
}; };

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_100_LOCK_MUTEX 0x2884 #define FS_OFFSET_100_LOCK_MUTEX 0x2884
#define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0 #define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x6A8AC #define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x6A8AC
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_1000_LOCK_MUTEX 0x28910 #define FS_OFFSET_1000_LOCK_MUTEX 0x28910
#define FS_OFFSET_1000_UNLOCK_MUTEX 0x28960 #define FS_OFFSET_1000_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0 #define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910 #define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910
#define FS_OFFSET_1000_EXFAT_UNLOCK_MUTEX 0x28960 #define FS_OFFSET_1000_EXFAT_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0 #define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910 #define FS_OFFSET_1020_LOCK_MUTEX 0x28910
#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960 #define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740 #define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910 #define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960 #define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740 #define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
// Misc Data // Misc Data

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1100_H__
#define __FS_1100_H__
// Accessor vtable getters
#define FS_OFFSET_1100_SDMMC_ACCESSOR_GC 0x156D90
#define FS_OFFSET_1100_SDMMC_ACCESSOR_SD 0x154F40
#define FS_OFFSET_1100_SDMMC_ACCESSOR_NAND 0x1500F0
// Hooks
#define FS_OFFSET_1100_SDMMC_WRAPPER_READ 0x14B990
#define FS_OFFSET_1100_SDMMC_WRAPPER_WRITE 0x14BA70
#define FS_OFFSET_1100_RTLD 0x688
#define FS_OFFSET_1100_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1100_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40
// Misc funcs
#define FS_OFFSET_1100_LOCK_MUTEX 0x28FF0
#define FS_OFFSET_1100_UNLOCK_MUTEX 0x29040
#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840
#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0
// Misc Data
#define FS_OFFSET_1100_SD_MUTEX 0xE323E8
#define FS_OFFSET_1100_NAND_MUTEX 0xE2D338
#define FS_OFFSET_1100_ACTIVE_PARTITION 0xE2D378
#define FS_OFFSET_1100_SDMMC_DAS_HANDLE 0xE15D40
// NOPs
#define FS_OFFSET_1100_SD_DAS_INIT 0x273B4
// Nintendo Paths
#define FS_OFFSET_1100_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1100_H__

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1100_EXFAT_H__
#define __FS_1100_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_GC 0x156D90
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_SD 0x154F40
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_NAND 0x1500F0
// Hooks
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_READ 0x14B990
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_WRITE 0x14BA70
#define FS_OFFSET_1100_EXFAT_RTLD 0x688
#define FS_OFFSET_1100_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1100_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40
// Misc funcs
#define FS_OFFSET_1100_EXFAT_LOCK_MUTEX 0x28FF0
#define FS_OFFSET_1100_EXFAT_UNLOCK_MUTEX 0x29040
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0
// Misc Data
#define FS_OFFSET_1100_EXFAT_SD_MUTEX 0xE403E8
#define FS_OFFSET_1100_EXFAT_NAND_MUTEX 0xE3B338
#define FS_OFFSET_1100_EXFAT_ACTIVE_PARTITION 0xE3B378
#define FS_OFFSET_1100_EXFAT_SDMMC_DAS_HANDLE 0xE23D40
// NOPs
#define FS_OFFSET_1100_EXFAT_SD_DAS_INIT 0x273B4
// Nintendo Paths
#define FS_OFFSET_1100_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1100_EXFAT_H__

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_200_LOCK_MUTEX 0x3264 #define FS_OFFSET_200_LOCK_MUTEX 0x3264
#define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4 #define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264 #define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264
#define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4 #define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_210_LOCK_MUTEX 0x3264 #define FS_OFFSET_210_LOCK_MUTEX 0x3264
#define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4 #define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264 #define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264
#define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4 #define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_300_LOCK_MUTEX 0x35CC #define FS_OFFSET_300_LOCK_MUTEX 0x35CC
#define FS_OFFSET_300_UNLOCK_MUTEX 0x3638 #define FS_OFFSET_300_UNLOCK_MUTEX 0x3638
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270 #define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC #define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC
#define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638 #define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270 #define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_301_LOCK_MUTEX 0x3638 #define FS_OFFSET_301_LOCK_MUTEX 0x3638
#define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4 #define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C #define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638 #define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638
#define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4 #define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C #define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_400_LOCK_MUTEX 0x39A0 #define FS_OFFSET_400_LOCK_MUTEX 0x39A0
#define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48 #define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0 #define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0
#define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48 #define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
// Misc Data // Misc Data

View File

@@ -34,7 +34,8 @@
#define FS_OFFSET_410_LOCK_MUTEX 0x39A0 #define FS_OFFSET_410_LOCK_MUTEX 0x39A0
#define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC #define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
// Misc Data // Misc Data
#define FS_OFFSET_410_SD_MUTEX 0xE80268 #define FS_OFFSET_410_SD_MUTEX 0xE80268

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0 #define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0
#define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC #define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_500_LOCK_MUTEX 0x4080 #define FS_OFFSET_500_LOCK_MUTEX 0x4080
#define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380 #define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080 #define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080
#define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380 #define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_510_LOCK_MUTEX 0x4080 #define FS_OFFSET_510_LOCK_MUTEX 0x4080
#define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750 #define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080 #define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080
#define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750 #define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_600_LOCK_MUTEX 0x1412C0 #define FS_OFFSET_600_LOCK_MUTEX 0x1412C0
#define FS_OFFSET_600_UNLOCK_MUTEX 0x141310 #define FS_OFFSET_600_UNLOCK_MUTEX 0x141310
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x148500 #define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x148500
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0 #define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0
#define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10 #define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x153C00 #define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x153C00
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_700_LOCK_MUTEX 0x148A90 #define FS_OFFSET_700_LOCK_MUTEX 0x148A90
#define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0 #define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14FD50 #define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14FD50
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040 #define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040
#define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090 #define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15B300 #define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15B300
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0 #define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0
#define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720 #define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0 #define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80 #define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80
#define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0 #define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90 #define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0 #define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0
#define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720 #define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0 #define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80 #define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80
#define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0 #define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90 #define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_900_LOCK_MUTEX 0x25280 #define FS_OFFSET_900_LOCK_MUTEX 0x25280
#define FS_OFFSET_900_UNLOCK_MUTEX 0x252D0 #define FS_OFFSET_900_UNLOCK_MUTEX 0x252D0
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740 #define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280 #define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280
#define FS_OFFSET_900_EXFAT_UNLOCK_MUTEX 0x252D0 #define FS_OFFSET_900_EXFAT_UNLOCK_MUTEX 0x252D0
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740 #define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_910_LOCK_MUTEX 0x25280 #define FS_OFFSET_910_LOCK_MUTEX 0x25280
#define FS_OFFSET_910_UNLOCK_MUTEX 0x252D0 #define FS_OFFSET_910_UNLOCK_MUTEX 0x252D0
#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750 #define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
// Misc Data // Misc Data

View File

@@ -34,6 +34,7 @@
#define FS_OFFSET_910_EXFAT_LOCK_MUTEX 0x25280 #define FS_OFFSET_910_EXFAT_LOCK_MUTEX 0x25280
#define FS_OFFSET_910_EXFAT_UNLOCK_MUTEX 0x252D0 #define FS_OFFSET_910_EXFAT_UNLOCK_MUTEX 0x252D0
#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750 #define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
// Misc Data // Misc Data

View File

@@ -136,8 +136,8 @@ c : clear by read
#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ #define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ #define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
#define R1_ERASE_RESET (1 << 13) /* sr, c */ #define R1_ERASE_RESET (1 << 13) /* sr, c */
#define R1_STATUS(x) (x & 0xFFFFE000) #define R1_STATUS(x) ((x) & 0xFFFFE000)
#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ #define R1_CURRENT_STATE(x) (((x) & 0x00001E00) >> 9) /* sx, b (4 bits) */
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ #define R1_READY_FOR_DATA (1 << 8) /* sx, a */
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ #define R1_SWITCH_ERROR (1 << 7) /* sx, c */
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ #define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */

View File

@@ -1,6 +1,4 @@
/* /*
* include/linux/mmc/sd.h
*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018 CTCaer * Copyright (c) 2018 CTCaer
* *
@@ -10,8 +8,8 @@
* your option) any later version. * your option) any later version.
*/ */
#ifndef LINUX_MMC_SD_H #ifndef MMC_SD_H
#define LINUX_MMC_SD_H #define MMC_SD_H
/* SD commands type argument response */ /* SD commands type argument response */
/* class 0 */ /* class 0 */

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -156,7 +156,7 @@ int sdmmc_calculate_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_
} }
} }
} }
sdmmc_memcpy_buf = true; sdmmc_memcpy_buf = true;
return dma_buf_idx; return dma_buf_idx;
} }
@@ -164,15 +164,18 @@ int sdmmc_calculate_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_
static int _sdmmc_storage_check_result(u32 res) static int _sdmmc_storage_check_result(u32 res)
{ {
//Error mask: //Error mask:
//R1_OUT_OF_RANGE, R1_ADDRESS_ERROR, R1_BLOCK_LEN_ERROR, //TODO: R1_SWITCH_ERROR can be skipped for certain card types.
//R1_ERASE_SEQ_ERROR, R1_ERASE_PARAM, R1_WP_VIOLATION, if (res &
//R1_LOCK_UNLOCK_FAILED, R1_COM_CRC_ERROR, R1_ILLEGAL_COMMAND, (R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR |
//R1_CARD_ECC_FAILED, R1_CC_ERROR, R1_ERROR, R1_CID_CSD_OVERWRITE, R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION |
//R1_WP_ERASE_SKIP, R1_ERASE_RESET, R1_SWITCH_ERROR R1_LOCK_UNLOCK_FAILED | R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND |
if (!(res & 0xFDF9A080)) R1_CARD_ECC_FAILED | R1_CC_ERROR | R1_ERROR |
return 1; R1_CID_CSD_OVERWRITE | R1_WP_ERASE_SKIP | R1_ERASE_RESET |
//TODO: R1_SWITCH_ERROR we can skip for certain card types. R1_SWITCH_ERROR))
return 0; return 0;
// No errors.
return 1;
} }
static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state, u32 mask) static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state, u32 mask)
@@ -285,14 +288,23 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
sdmmc_end(storage->sdmmc); sdmmc_end(storage->sdmmc);
storage->initialized = 0;
return 1; return 1;
} }
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write) static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
{ {
u8 *bbuf = (u8 *)buf; u8 *bbuf = (u8 *)buf;
bool first_reinit = false; u32 sct_off = sector;
while (num_sectors) u32 sct_total = num_sectors;
bool first_reinit = true;
// Exit if not initialized.
if (!storage->initialized)
return 0;
while (sct_total)
{ {
u32 blkcnt = 0; u32 blkcnt = 0;
// Retry 5 times if failed. // Retry 5 times if failed.
@@ -300,7 +312,7 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
do do
{ {
reinit_try: reinit_try:
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write)) if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sct_off, MIN(sct_total, 0xFFFF), bbuf, is_write))
goto out; goto out;
else else
retries--; retries--;
@@ -313,24 +325,33 @@ reinit_try:
{ {
int res; int res;
if (!first_reinit) if (first_reinit)
res = nx_sd_initialize(true); res = nx_sd_initialize(true);
else else
res = nx_sd_init_retry(true); res = nx_sd_init_retry(true);
// Reset values for a retry.
blkcnt = 0;
retries = 3; retries = 3;
first_reinit = true; first_reinit = false;
// If succesful reinit, restart xfer.
if (res) if (res)
{
bbuf = (u8 *)buf;
sct_off = sector;
sct_total = num_sectors;
goto reinit_try; goto reinit_try;
}
} }
// Failed.
return 0; return 0;
out: out:
DPRINTF("readwrite: %08X\n", blkcnt); sct_off += blkcnt;
sector += blkcnt; sct_total -= blkcnt;
num_sectors -= blkcnt;
bbuf += 512 * blkcnt; bbuf += 512 * blkcnt;
} }
@@ -459,9 +480,11 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u
case SDMMC_POWER_1_8: case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18; arg = SD_OCR_CCS | SD_OCR_VDD_18;
break; break;
case SDMMC_POWER_3_3: case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34; arg = SD_OCR_CCS | SD_OCR_VDD_27_34;
break; break;
default: default:
return 0; return 0;
} }
@@ -518,6 +541,7 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
storage->cid.fwrev = unstuff_bits(raw_cid, 40, 4); storage->cid.fwrev = unstuff_bits(raw_cid, 40, 4);
storage->cid.serial = unstuff_bits(raw_cid, 16, 24); storage->cid.serial = unstuff_bits(raw_cid, 16, 24);
break; break;
case 2: /* MMC v2.0 - v2.2 */ case 2: /* MMC v2.0 - v2.2 */
case 3: /* MMC v3.1 - v3.3 */ case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */ case 4: /* MMC v4 */
@@ -527,6 +551,7 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
storage->cid.prv = unstuff_bits(raw_cid, 48, 8); storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
storage->cid.serial = unstuff_bits(raw_cid, 16, 32); storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
break; break;
default: default:
break; break;
} }
@@ -571,6 +596,10 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS]; storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
} }
@@ -613,6 +642,7 @@ static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
case SDMMC_BUS_WIDTH_4: case SDMMC_BUS_WIDTH_4:
arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
break; break;
case SDMMC_BUS_WIDTH_8: case SDMMC_BUS_WIDTH_8:
arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8); arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8);
break; break;
@@ -671,7 +701,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
if (!_mmc_storage_enable_HS200(storage)) if (!_mmc_storage_enable_HS200(storage))
return 0; return 0;
sdmmc_set_tap_value(storage->sdmmc); sdmmc_save_tap_value(storage->sdmmc);
if (!_mmc_storage_enable_HS(storage, 0)) if (!_mmc_storage_enable_HS(storage, 0))
return 0; return 0;
@@ -727,7 +757,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_wid
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
storage->rca = 2; //TODO: this could be a config item. storage->rca = 2; //TODO: this could be a config item.
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_AUTO_CAL_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
return 0; return 0;
DPRINTF("[MMC] after init\n"); DPRINTF("[MMC] after init\n");
@@ -798,7 +828,9 @@ DPRINTF("[MMC] BKOPS enabled\n");
return 0; return 0;
DPRINTF("[MMC] succesfully switched to HS mode\n"); DPRINTF("[MMC] succesfully switched to HS mode\n");
sdmmc_card_clock_ctrl(storage->sdmmc, SDMMC_AUTO_CAL_ENABLE); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
storage->initialized = 1;
return 1; return 1;
} }
@@ -812,6 +844,7 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
return 0; return 0;
storage->partition = partition; storage->partition = partition;
return 1; return 1;
} }
@@ -850,7 +883,7 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
return (resp & 0xFF) == 0xAA ? 0 : 2; return (resp & 0xFF) == 0xAA ? 0 : 2;
} }
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int supports_low_voltage) static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
// Support for Current > 150mA // Support for Current > 150mA
@@ -858,7 +891,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int
// Support for handling block-addressed SDHC cards // Support for handling block-addressed SDHC cards
arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0; arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0;
// Support for 1.8V // Support for 1.8V
arg |= (supports_low_voltage & ~is_version_1 & 1) ? SD_OCR_S18R : 0; arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0;
// This is needed for most cards. Do not set bit7 even if 1.8V is supported. // This is needed for most cards. Do not set bit7 even if 1.8V is supported.
arg |= SD_OCR_VDD_32_33; arg |= SD_OCR_VDD_32_33;
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
@@ -868,22 +901,24 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
} }
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int supports_low_voltage) static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support)
{ {
u64 timeout = get_tmr_ms() + 1500; u64 timeout = get_tmr_ms() + 1500;
while (1) while (1)
{ {
u32 cond = 0; u32 cond = 0;
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, supports_low_voltage)) if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support))
break; break;
if (cond & MMC_CARD_BUSY) if (cond & MMC_CARD_BUSY)
{ {
DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support);
if (cond & SD_OCR_CCS) if (cond & SD_OCR_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
// Check if card supports 1.8V signaling. // Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && supports_low_voltage) if (cond & SD_ROCR_S18A && bus_low_voltage_support)
{ {
//The low voltage regulator configuration is valid for SDMMC1 only. //The low voltage regulator configuration is valid for SDMMC1 only.
if (storage->sdmmc->id == SDMMC_1 && if (storage->sdmmc->id == SDMMC_1 &&
@@ -896,6 +931,10 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
DPRINTF("-> switched to low voltage\n"); DPRINTF("-> switched to low voltage\n");
} }
} }
else
{
DPRINTF("[SD] no low voltage support\n");
}
return 1; return 1;
} }
@@ -1050,12 +1089,15 @@ void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit,
case SD_SET_CURRENT_LIMIT_800: case SD_SET_CURRENT_LIMIT_800:
DPRINTF("[SD] power limit raised to 800mA\n"); DPRINTF("[SD] power limit raised to 800mA\n");
break; break;
case SD_SET_CURRENT_LIMIT_600: case SD_SET_CURRENT_LIMIT_600:
DPRINTF("[SD] power limit raised to 600mA\n"); DPRINTF("[SD] power limit raised to 600mA\n");
break; break;
case SD_SET_CURRENT_LIMIT_400: case SD_SET_CURRENT_LIMIT_400:
DPRINTF("[SD] power limit raised to 400mA\n"); DPRINTF("[SD] power limit raised to 400mA\n");
break; break;
default: default:
case SD_SET_CURRENT_LIMIT_200: case SD_SET_CURRENT_LIMIT_200:
DPRINTF("[SD] power limit defaulted to 200mA\n"); DPRINTF("[SD] power limit defaulted to 200mA\n");
@@ -1068,7 +1110,7 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
{ {
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type)) if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type))
return 0; return 0;
DPRINTF("[SD] supports switch to (U)HS mode\n"); DPRINTF("[SD] supports (U)HS mode: %d\n", buf[16] & 0xF);
u32 type_out = buf[16] & 0xF; u32 type_out = buf[16] & 0xF;
if (type_out != hs_type) if (type_out != hs_type)
@@ -1104,6 +1146,7 @@ int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf)
u8 access_mode = buf[13]; u8 access_mode = buf[13];
u16 current_limit = buf[7] | buf[6] << 8; u16 current_limit = buf[7] | buf[6] << 8;
DPRINTF("[SD] access: %02X, current: %02X\n", access_mode, current_limit);
// Try to raise the current limit to let the card perform better. // Try to raise the current limit to let the card perform better.
_sd_storage_set_current_limit(storage, current_limit, buf); _sd_storage_set_current_limit(storage, current_limit, buf);
@@ -1142,7 +1185,7 @@ DPRINTF("[SD] bus speed set to SDR50\n");
if (access_mode & SD_MODE_UHS_SDR25) if (access_mode & SD_MODE_UHS_SDR25)
{ {
type = SDHCI_TIMING_UHS_SDR25; type = SDHCI_TIMING_UHS_SDR25;
hs_type = UHS_SDR50_BUS_SPEED; hs_type = UHS_SDR25_BUS_SPEED;
DPRINTF("[SD] bus speed set to SDR25\n"); DPRINTF("[SD] bus speed set to SDR25\n");
storage->csd.busspeed = 25; storage->csd.busspeed = 25;
break; break;
@@ -1155,6 +1198,7 @@ DPRINTF("[SD] bus speed set to SDR25\n");
DPRINTF("[SD] bus speed set to SDR12\n"); DPRINTF("[SD] bus speed set to SDR12\n");
storage->csd.busspeed = 12; storage->csd.busspeed = 12;
break; break;
default: default:
return 0; return 0;
break; break;
@@ -1165,10 +1209,10 @@ DPRINTF("[SD] bus speed set to SDR12\n");
DPRINTF("[SD] card accepted UHS\n"); DPRINTF("[SD] card accepted UHS\n");
if (!sdmmc_setup_clock(storage->sdmmc, type)) if (!sdmmc_setup_clock(storage->sdmmc, type))
return 0; return 0;
DPRINTF("[SD] setup clock\n"); DPRINTF("[SD] after setup clock\n");
if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
return 0; return 0;
DPRINTF("[SD] config tuning\n"); DPRINTF("[SD] after tuning\n");
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
@@ -1227,6 +1271,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
case 0: case 0:
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
break; break;
case 1: case 1:
storage->csd.c_size = (1 + unstuff_bits(raw_csd, 48, 22)); storage->csd.c_size = (1 + unstuff_bits(raw_csd, 48, 22));
storage->csd.capacity = storage->csd.c_size << 10; storage->csd.capacity = storage->csd.c_size << 10;
@@ -1235,7 +1280,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
} }
} }
static bool _sdmmc_storage_supports_low_voltage(u32 bus_width, u32 type) static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type)
{ {
switch (type) switch (type)
{ {
@@ -1261,7 +1306,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_widt
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_AUTO_CAL_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_POWER_SAVE_DISABLE))
return 0; return 0;
DPRINTF("[SD] after init\n"); DPRINTF("[SD] after init\n");
@@ -1276,9 +1321,9 @@ DPRINTF("[SD] went to idle state\n");
return 0; return 0;
DPRINTF("[SD] after send if cond\n"); DPRINTF("[SD] after send if cond\n");
bool supports_low_voltage = _sdmmc_storage_supports_low_voltage(bus_width, type); bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type);
if (!_sd_storage_get_op_cond(storage, is_version_1, supports_low_voltage)) if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
@@ -1356,7 +1401,7 @@ DPRINTF("[SD] SD does not support wide bus width\n");
return 0; return 0;
DPRINTF("[SD] enabled UHS\n"); DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_ctrl(sdmmc, SDMMC_AUTO_CAL_ENABLE); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
} }
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0) else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0)
{ {
@@ -1369,12 +1414,15 @@ DPRINTF("[SD] enabled HS\n");
case SDMMC_BUS_WIDTH_4: case SDMMC_BUS_WIDTH_4:
storage->csd.busspeed = 25; storage->csd.busspeed = 25;
break; break;
case SDMMC_BUS_WIDTH_1: case SDMMC_BUS_WIDTH_1:
storage->csd.busspeed = 6; storage->csd.busspeed = 6;
break; break;
} }
} }
storage->initialized = 1;
return 1; return 1;
} }
@@ -1414,17 +1462,19 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_DDR52, SDMMC_AUTO_CAL_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS102, SDMMC_POWER_SAVE_DISABLE))
return 0; return 0;
DPRINTF("[gc] after init\n"); DPRINTF("[gc] after init\n");
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_DDR52, MMC_SEND_TUNING_BLOCK_HS200)) if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS102, MMC_SEND_TUNING_BLOCK_HS200))
return 0; return 0;
DPRINTF("[gc] after tuning\n"); DPRINTF("[gc] after tuning\n");
sdmmc_card_clock_ctrl(sdmmc, SDMMC_AUTO_CAL_ENABLE); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
storage->initialized = 1;
return 1; return 1;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -54,16 +54,19 @@ typedef struct _mmc_csd
typedef struct _mmc_ext_csd typedef struct _mmc_ext_csd
{ {
u8 rev;
u32 sectors; u32 sectors;
int bkops; /* background support bit */ int bkops; /* background support bit */
int bkops_en; /* manual bkops enable bit */ int bkops_en; /* manual bkops enable bit */
u8 rev;
u8 ext_struct; /* 194 */ u8 ext_struct; /* 194 */
u8 card_type; /* 196 */ u8 card_type; /* 196 */
u8 bkops_status; /* 246 */ u8 bkops_status; /* 246 */
u16 dev_version; u8 pre_eol_info;
u8 dev_life_est_a;
u8 dev_life_est_b;
u8 boot_mult; u8 boot_mult;
u8 rpmb_mult; u8 rpmb_mult;
u16 dev_version;
} mmc_ext_csd_t; } mmc_ext_csd_t;
typedef struct _sd_scr typedef struct _sd_scr
@@ -81,6 +84,7 @@ typedef struct _sd_ssr
u8 uhs_grade; u8 uhs_grade;
u8 video_class; u8 video_class;
u8 app_class; u8 app_class;
u32 protected_size;
} sd_ssr_t; } sd_ssr_t;
/*! SDMMC storage context. */ /*! SDMMC storage context. */
@@ -99,6 +103,7 @@ typedef struct _sdmmc_storage_t
mmc_csd_t csd; mmc_csd_t csd;
mmc_ext_csd_t ext_csd; mmc_ext_csd_t ext_csd;
sd_scr_t scr; sd_scr_t scr;
int initialized;
} sdmmc_storage_t; } sdmmc_storage_t;
extern sdmmc_accessor_t *_current_accessor; extern sdmmc_accessor_t *_current_accessor;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -58,12 +58,15 @@ static int _sdmmc_set_io_power(sdmmc_t *sdmmc, u32 power)
case SDMMC_POWER_OFF: case SDMMC_POWER_OFF:
sdmmc->regs->pwrcon &= ~SDHCI_POWER_ON; sdmmc->regs->pwrcon &= ~SDHCI_POWER_ON;
break; break;
case SDMMC_POWER_1_8: case SDMMC_POWER_1_8:
sdmmc->regs->pwrcon = SDHCI_POWER_180; sdmmc->regs->pwrcon = SDHCI_POWER_180;
break; break;
case SDMMC_POWER_3_3: case SDMMC_POWER_3_3:
sdmmc->regs->pwrcon = SDHCI_POWER_330; sdmmc->regs->pwrcon = SDHCI_POWER_330;
break; break;
default: default:
return 0; return 0;
} }
@@ -96,7 +99,7 @@ void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width)
sdmmc->regs->hostctl = host_control | SDHCI_CTRL_8BITBUS; sdmmc->regs->hostctl = host_control | SDHCI_CTRL_8BITBUS;
} }
void sdmmc_set_tap_value(sdmmc_t *sdmmc) void sdmmc_save_tap_value(sdmmc_t *sdmmc)
{ {
sdmmc->venclkctl_tap = sdmmc->regs->venclkctl >> 16; sdmmc->venclkctl_tap = sdmmc->regs->venclkctl >> 16;
sdmmc->venclkctl_set = 1; sdmmc->venclkctl_set = 1;
@@ -105,7 +108,7 @@ void sdmmc_set_tap_value(sdmmc_t *sdmmc)
static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
{ {
const u32 dqs_trim_val = 0x28; const u32 dqs_trim_val = 0x28;
const u32 tap_values[] = { 4, 0, 3, 0 }; const u32 tap_values_t210[] = { 4, 0, 3, 0 };
u32 tap_val = 0; u32 tap_val = 0;
@@ -122,36 +125,49 @@ static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
tap_val = sdmmc->venclkctl_tap; tap_val = sdmmc->venclkctl_tap;
} }
else else
{ tap_val = sdmmc->t210b01 ? 11 : tap_values_t210[sdmmc->id];
tap_val = tap_values[sdmmc->id];
}
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap_val << 16); sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap_val << 16);
return 1; return 1;
} }
static int _sdmmc_get_clkcon(sdmmc_t *sdmmc) static int _sdmmc_commit_changes(sdmmc_t *sdmmc)
{ {
return sdmmc->regs->clkcon; return sdmmc->regs->clkcon;
} }
static void _sdmmc_pad_config_fallback(sdmmc_t *sdmmc, u32 power) static void _sdmmc_pad_config_fallback(sdmmc_t *sdmmc, u32 power)
{ {
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
switch (sdmmc->id) switch (sdmmc->id)
{ {
case SDMMC_1: // 33 Ohm 2X Driver. case SDMMC_1: // 33 Ohm 2X Driver.
if (power == SDMMC_POWER_OFF) if (power == SDMMC_POWER_OFF)
break; break;
u32 sdmmc1_pad_cfg = APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xF8080FFF; u32 sdmmc1_pad_cfg = APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xF8080FFF;
if (power == SDMMC_POWER_1_8) if (sdmmc->t210b01)
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = sdmmc1_pad_cfg | (0xB0F << 12); // Up: 11, Dn: 15. For 33 ohm. sdmmc1_pad_cfg |= (0x808 << 12); // Up: 8, Dn: 8. For 33 ohm.
else if (power == SDMMC_POWER_1_8)
sdmmc1_pad_cfg |= (0xB0F << 12); // Up: 11, Dn: 15. For 33 ohm.
else if (power == SDMMC_POWER_3_3) else if (power == SDMMC_POWER_3_3)
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = sdmmc1_pad_cfg | (0xC0C << 12); // Up: 12, Dn: 12. For 33 ohm. sdmmc1_pad_cfg |= (0xC0C << 12); // Up: 12, Dn: 12. For 33 ohm.
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = sdmmc1_pad_cfg;
(void)APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL); // Commit write.
break; break;
case SDMMC_2: case SDMMC_2:
case SDMMC_4: // 50 Ohm 2X Driver. PU:16, PD:16. if (sdmmc->t210b01)
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040; APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) & 0xF8080FFF) | 0xA0A000;
else
APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040; // PU:16, PD:16.
(void)APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL);
break;
case SDMMC_4: // 50 Ohm 2X Driver. PU:16, PD:16, B01: PU:10, PD:10.
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) =
(APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | (sdmmc->t210b01 ? 0xA28 : 0x1040);
(void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write.
break; break;
} }
} }
@@ -169,13 +185,13 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
if (!(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD)) if (!(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD))
{ {
sdmmc->regs->sdmemcmppadctl |= TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; sdmmc->regs->sdmemcmppadctl |= TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep(1); usleep(1);
} }
// Enable auto calibration and start auto configuration. // Enable auto calibration and start auto configuration.
sdmmc->regs->autocalcfg |= TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE | TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START; sdmmc->regs->autocalcfg |= TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE | TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep(2); usleep(2);
u64 timeout = get_tmr_ms() + 10; u64 timeout = get_tmr_ms() + 10;
@@ -187,24 +203,18 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
break; break;
} }
} }
/*
// Check if PU results are inside limits. #if 0
// SDMMC1: CZ pads - 7-bit PU. SDMMC2/4: LV_CZ pads - 5-bit PU. // Check if Comp pad is open or short to ground.
u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x7F; // SDMMC1: CZ pads - T210/T210B01: 7-bit/5-bit. SDMMC2/4: LV_CZ pads - 5-bit.
switch (sdmmc->id) u8 code_mask = (sdmmc->t210b01 || sdmmc->id != SDMMC_1) ? 0x1F : 0x7F;
{ u8 autocal_pu_status = sdmmc->regs->autocalsts & code_mask;
case SDMMC_1: if (!autocal_pu_status)
if (!autocal_pu_status || autocal_pu_status == 0x7F) EPRINTF("SDMMC: Comp Pad short to gnd!");
timeout = 0; else if (autocal_pu_status == code_mask)
break; EPRINTF("SDMMC: Comp Pad open!");
case SDMMC_2: #endif
case SDMMC_4:
autocal_pu_status &= 0x1F;
if (!autocal_pu_status || autocal_pu_status == 0x1F)
timeout = 0;
break;
}
*/
// In case auto calibration fails, we load suggested standard values. // In case auto calibration fails, we load suggested standard values.
if (!timeout) if (!timeout)
{ {
@@ -230,7 +240,7 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc)
} }
sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u64 timeout = get_tmr_ms() + 5; u64 timeout = get_tmr_ms() + 5;
while (sdmmc->regs->vendllcalcfg & TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE) while (sdmmc->regs->vendllcalcfg & TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE)
@@ -261,12 +271,21 @@ out:;
static void _sdmmc_reset(sdmmc_t *sdmmc) static void _sdmmc_reset(sdmmc_t *sdmmc)
{ {
sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA; sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u64 timeout = get_tmr_ms() + 2000; u64 timeout = get_tmr_ms() + 2000;
while ((sdmmc->regs->swrst & (SDHCI_RESET_CMD | SDHCI_RESET_DATA)) && get_tmr_ms() < timeout) while ((sdmmc->regs->swrst & (SDHCI_RESET_CMD | SDHCI_RESET_DATA)) && get_tmr_ms() < timeout)
; ;
} }
static void _sdmmc_reset_all(sdmmc_t *sdmmc)
{
sdmmc->regs->swrst |= SDHCI_RESET_ALL;
_sdmmc_commit_changes(sdmmc);
u32 timeout = get_tmr_ms() + 2000;//100ms
while ((sdmmc->regs->swrst & SDHCI_RESET_ALL) && get_tmr_ms() < timeout)
;
}
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
{ {
// Disable the SD clock if it was enabled, and reenable it later. // Disable the SD clock if it was enabled, and reenable it later.
@@ -290,36 +309,41 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
sdmmc->regs->hostctl &= ~SDHCI_CTRL_HISPD; sdmmc->regs->hostctl &= ~SDHCI_CTRL_HISPD;
sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_MMC_HS52: case SDHCI_TIMING_MMC_HS52:
case SDHCI_TIMING_SD_HS25: case SDHCI_TIMING_SD_HS25:
sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD; sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD;
sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_MMC_HS200: case SDHCI_TIMING_MMC_HS200:
case SDHCI_TIMING_UHS_SDR50: // T210 Errata for SDR50, the host must be set to SDR104. case SDHCI_TIMING_UHS_SDR50: // T210 Errata for SDR50, the host must be set to SDR104.
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_SDR82:
case SDHCI_TIMING_UHS_DDR50: case SDHCI_TIMING_UHS_DDR50:
case SDHCI_TIMING_MMC_DDR52: case SDHCI_TIMING_MMC_HS102:
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR104_BUS_SPEED; sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR104_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_MMC_HS400:
// Non standard. // Non standard.
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | HS400_BUS_SPEED; sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | HS400_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_UHS_SDR25: case SDHCI_TIMING_UHS_SDR25:
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR25_BUS_SPEED; sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR25_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR12:
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR12_BUS_SPEED; sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR12_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
} }
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u32 clock; u32 clock;
u16 divisor; u16 divisor;
@@ -349,10 +373,10 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc) static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
{ {
// Recalibrate conditionally. // Recalibrate conditionally.
if ((sdmmc->id == SDMMC_1) && !sdmmc->auto_cal_enabled) if (sdmmc->manual_cal && !sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
if (!sdmmc->auto_cal_enabled) if (!sdmmc->powersave_enabled)
{ {
if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN))
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
@@ -366,18 +390,17 @@ static void _sdmmc_sd_clock_disable(sdmmc_t *sdmmc)
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
} }
void sdmmc_card_clock_ctrl(sdmmc_t *sdmmc, int auto_cal_enable) void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
{ {
// Recalibrate periodically for SDMMC1. // Recalibrate periodically for SDMMC1.
if ((sdmmc->id == SDMMC_1) && !auto_cal_enable && sdmmc->card_clock_enabled) if (sdmmc->manual_cal && !powersave_enable && sdmmc->card_clock_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
sdmmc->auto_cal_enabled = auto_cal_enable; sdmmc->powersave_enabled = powersave_enable;
if (auto_cal_enable) if (powersave_enable)
{ {
if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) if (sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)
return; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
return; return;
} }
@@ -398,6 +421,7 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
return 0; return 0;
rsp[0] = sdmmc->regs->rspreg0; rsp[0] = sdmmc->regs->rspreg0;
break; break;
case SDMMC_RSP_TYPE_2: case SDMMC_RSP_TYPE_2:
if (size < 0x10) if (size < 0x10)
return 0; return 0;
@@ -426,9 +450,9 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
rsp[i - 1] |= (tempreg >> 24) & 0xFF; rsp[i - 1] |= (tempreg >> 24) & 0xFF;
} }
break; break;
default: default:
return 0; return 0;
break;
} }
return 1; return 1;
@@ -449,6 +473,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
return 0; return 0;
rsp[0] = sdmmc->rsp[0]; rsp[0] = sdmmc->rsp[0];
break; break;
case SDMMC_RSP_TYPE_2: case SDMMC_RSP_TYPE_2:
if (size < 0x10) if (size < 0x10)
return 0; return 0;
@@ -457,9 +482,9 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
rsp[2] = sdmmc->rsp[2]; rsp[2] = sdmmc->rsp[2];
rsp[3] = sdmmc->rsp[3]; rsp[3] = sdmmc->rsp[3];
break; break;
default: default:
return 0; return 0;
break;
} }
return 1; return 1;
@@ -467,7 +492,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat)
{ {
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u64 timeout = get_tmr_ms() + 2000; u64 timeout = get_tmr_ms() + 2000;
while(sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT) while(sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT)
@@ -493,7 +518,7 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat)
static int _sdmmc_wait_card_busy(sdmmc_t *sdmmc) static int _sdmmc_wait_card_busy(sdmmc_t *sdmmc)
{ {
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u64 timeout = get_tmr_ms() + 2000; u64 timeout = get_tmr_ms() + 2000;
while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL_MASK)) while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL_MASK))
@@ -512,16 +537,19 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc)
{ {
case SDMMC_BUS_WIDTH_1: case SDMMC_BUS_WIDTH_1:
return 0; return 0;
break;
case SDMMC_BUS_WIDTH_4: case SDMMC_BUS_WIDTH_4:
sdmmc->regs->blksize = 64; sdmmc->regs->blksize = 64;
break; break;
case SDMMC_BUS_WIDTH_8: case SDMMC_BUS_WIDTH_8:
sdmmc->regs->blksize = 128; sdmmc->regs->blksize = 128;
break; break;
} }
sdmmc->regs->blkcnt = 1; sdmmc->regs->blkcnt = 1;
sdmmc->regs->trnmod = SDHCI_TRNS_READ; sdmmc->regs->trnmod = SDHCI_TRNS_READ;
return 1; return 1;
} }
@@ -533,6 +561,7 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen
{ {
case SDMMC_RSP_TYPE_0: case SDMMC_RSP_TYPE_0:
break; break;
case SDMMC_RSP_TYPE_1: case SDMMC_RSP_TYPE_1:
case SDMMC_RSP_TYPE_4: case SDMMC_RSP_TYPE_4:
case SDMMC_RSP_TYPE_5: case SDMMC_RSP_TYPE_5:
@@ -541,15 +570,17 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen
else else
cmdflags = SDHCI_CMD_RESP_LEN48 | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; cmdflags = SDHCI_CMD_RESP_LEN48 | SDHCI_CMD_INDEX | SDHCI_CMD_CRC;
break; break;
case SDMMC_RSP_TYPE_2: case SDMMC_RSP_TYPE_2:
cmdflags = SDHCI_CMD_RESP_LEN136 | SDHCI_CMD_CRC; cmdflags = SDHCI_CMD_RESP_LEN136 | SDHCI_CMD_CRC;
break; break;
case SDMMC_RSP_TYPE_3: case SDMMC_RSP_TYPE_3:
cmdflags = SDHCI_CMD_RESP_LEN48; cmdflags = SDHCI_CMD_RESP_LEN48;
break; break;
default: default:
return 0; return 0;
break;
} }
if (is_data_present) if (is_data_present)
@@ -572,7 +603,7 @@ static void _sdmmc_send_tuning_cmd(sdmmc_t *sdmmc, u32 cmd)
static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd)
{ {
if (sdmmc->auto_cal_enabled) if (sdmmc->powersave_enabled)
return 0; return 0;
if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true)) if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true))
return 0; return 0;
@@ -584,13 +615,13 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd)
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
_sdmmc_send_tuning_cmd(sdmmc, cmd); _sdmmc_send_tuning_cmd(sdmmc, cmd);
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep(1); usleep(1);
_sdmmc_reset(sdmmc); _sdmmc_reset(sdmmc);
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u64 timeout = get_tmr_us() + 5000; u64 timeout = get_tmr_us() + 5000;
while (get_tmr_us() < timeout) while (get_tmr_us() < timeout)
@@ -599,7 +630,7 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd)
{ {
sdmmc->regs->norintsts = SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintsts = SDHCI_INT_DATA_AVAIL;
sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor);
return 1; return 1;
} }
@@ -608,7 +639,7 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd)
_sdmmc_reset(sdmmc); _sdmmc_reset(sdmmc);
sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor);
return 0; return 0;
@@ -627,15 +658,18 @@ int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd)
max = 128; max = 128;
flag = (2 << 13); // 128 iterations. flag = (2 << 13); // 128 iterations.
break; break;
case SDHCI_TIMING_UHS_SDR50: case SDHCI_TIMING_UHS_SDR50:
case SDHCI_TIMING_UHS_DDR50: case SDHCI_TIMING_UHS_DDR50:
case SDHCI_TIMING_MMC_DDR52: case SDHCI_TIMING_MMC_HS102:
max = 256; max = 256;
flag = (4 << 13); // 256 iterations. flag = (4 << 13); // 256 iterations.
break; break;
case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR12:
case SDHCI_TIMING_UHS_SDR25: case SDHCI_TIMING_UHS_SDR25:
return 1; return 1;
default: default:
return 0; return 0;
} }
@@ -664,7 +698,7 @@ static int _sdmmc_enable_internal_clock(sdmmc_t *sdmmc)
{ {
//Enable internal clock and wait till it is stable. //Enable internal clock and wait till it is stable.
sdmmc->regs->clkcon |= SDHCI_CLOCK_INT_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_INT_EN;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u64 timeout = get_tmr_ms() + 2000; u64 timeout = get_tmr_ms() + 2000;
while (!(sdmmc->regs->clkcon & SDHCI_CLOCK_INT_STABLE)) while (!(sdmmc->regs->clkcon & SDHCI_CLOCK_INT_STABLE))
{ {
@@ -700,17 +734,28 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
off_pd = 5; off_pd = 5;
off_pu = 5; off_pu = 5;
break; break;
case SDMMC_1: case SDMMC_1:
case SDMMC_3:
if (power == SDMMC_POWER_1_8) if (power == SDMMC_POWER_1_8)
{ {
off_pd = 123; if (!sdmmc->t210b01)
off_pu = 123; {
off_pd = 123;
off_pu = 123;
}
else
{
off_pd = 6;
off_pu = 6;
}
} }
else if (power == SDMMC_POWER_3_3) else if (power == SDMMC_POWER_3_3)
{ {
off_pd = 125; if (!sdmmc->t210b01)
off_pu = 0; {
off_pd = 125;
off_pu = 0;
}
} }
else else
return 0; return 0;
@@ -740,7 +785,7 @@ static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
u16 norintsts = sdmmc->regs->norintsts; u16 norintsts = sdmmc->regs->norintsts;
u16 errintsts = sdmmc->regs->errintsts; u16 errintsts = sdmmc->regs->errintsts;
DPRINTF("norintsts %08X; errintsts %08X\n", norintsts, errintsts); DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts);
if (pout) if (pout)
*pout = norintsts; *pout = norintsts;
@@ -762,7 +807,7 @@ DPRINTF("norintsts %08X; errintsts %08X\n", norintsts, errintsts);
static int _sdmmc_wait_response(sdmmc_t *sdmmc) static int _sdmmc_wait_response(sdmmc_t *sdmmc)
{ {
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
u64 timeout = get_tmr_ms() + 2000; u64 timeout = get_tmr_ms() + 2000;
while (true) while (true)
@@ -813,7 +858,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
return 0; return 0;
// Recalibrate periodically for SDMMC1. // Recalibrate periodically for SDMMC1.
if ((sdmmc->id == SDMMC_1) && sdmmc->auto_cal_enabled) if (sdmmc->manual_cal && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
bool should_disable_sd_clock = false; bool should_disable_sd_clock = false;
@@ -821,7 +866,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
{ {
should_disable_sd_clock = true; should_disable_sd_clock = true;
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
} }
@@ -842,7 +887,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
u32 blkcnt = req->num_sectors; u32 blkcnt = req->num_sectors;
if (blkcnt >= 0xFFFF) if (blkcnt >= 0xFFFF)
blkcnt = 0xFFFF; blkcnt = 0xFFFF;
u64 admaaddr = (u64)sdmmc_calculate_dma_addr(_current_accessor, req->buf, blkcnt); u64 admaaddr = (u64)sdmmc_calculate_dma_addr(_current_accessor, req->buf, blkcnt);
if (!admaaddr) if (!admaaddr)
{ {
@@ -861,7 +906,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
sdmmc->dma_addr_next = (admaaddr + 0x80000) & 0xFFFFFFFFFFF80000; sdmmc->dma_addr_next = (admaaddr + 0x80000) & 0xFFFFFFFFFFF80000;
sdmmc->regs->blksize = req->blksize | 0x7000; sdmmc->regs->blksize = req->blksize | 0x7000; // DMA 512KB (Detects A18 carry out).
sdmmc->regs->blkcnt = blkcnt; sdmmc->regs->blkcnt = blkcnt;
if (blkcnt_out) if (blkcnt_out)
@@ -953,8 +998,6 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
is_data_present = true; is_data_present = true;
} }
else
is_data_present = false;
_sdmmc_enable_interrupts(sdmmc); _sdmmc_enable_interrupts(sdmmc);
@@ -962,7 +1005,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
return 0; return 0;
int result = _sdmmc_wait_response(sdmmc); int result = _sdmmc_wait_response(sdmmc);
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
if (result) if (result)
{ {
@@ -970,12 +1013,6 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
{ {
sdmmc->expected_rsp_type = cmd->rsp_type; sdmmc->expected_rsp_type = cmd->rsp_type;
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type); result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type);
/*if(sdmmc->rsp[0] & 0xFDF9A080)
{
res = 0;
sdmmc->rsp[0] = 0; // Reset error
}*/
} }
if (req && result) if (req && result)
@@ -1029,7 +1066,56 @@ bool sdmmc_get_sd_inserted()
return (!gpio_read(GPIO_PORT_Z, GPIO_PIN_1)); return (!gpio_read(GPIO_PORT_Z, GPIO_PIN_1));
} }
static int _sdmmc_config_sdmmc1() static void _sdmmc_config_sdmmc1_schmitt()
{
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) |= PINMUX_SCHMT;
}
static void _sdmmc_config_sdmmc2_schmitt()
{
PINMUX_AUX(PINMUX_AUX_SDMMC2_CLK) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_CMD) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT7) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT6) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT5) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT4) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT3) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT2) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT1) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT0) |= PINMUX_SCHMT;
}
static void _sdmmc_config_sdmmc1_pads(bool discharge)
{
u32 sdmmc1_pin_mask = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
// Set values for Reset state.
u32 function = GPIO_MODE_SPIO;
u32 level = GPIO_LOW;
u32 output = GPIO_OUTPUT_DISABLE;
// Set values for dicharging.
if (discharge)
{
function = GPIO_MODE_GPIO;
level = GPIO_HIGH;
output = GPIO_OUTPUT_ENABLE;
}
// Set all pads function.
gpio_config(GPIO_PORT_M, sdmmc1_pin_mask, function);
// Set all pads output level.
gpio_write(GPIO_PORT_M, sdmmc1_pin_mask, level);
// Set all pads output.
gpio_output_enable(GPIO_PORT_M, sdmmc1_pin_mask, output);
}
static int _sdmmc_config_sdmmc1(bool t210b01)
{ {
// Configure SD card detect. // Configure SD card detect.
PINMUX_AUX(PINMUX_AUX_GPIO_PZ1) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP | 2; // GPIO control, pull up. PINMUX_AUX(PINMUX_AUX_GPIO_PZ1) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP | 2; // GPIO control, pull up.
@@ -1044,76 +1130,102 @@ static int _sdmmc_config_sdmmc1()
/* /*
* Pinmux config: * Pinmux config:
* DRV_TYPE = DRIVE_2X * DRV_TYPE = DRIVE_2X (for 33 Ohm driver)
* E_SCHMT = ENABLE (for 1.8V), DISABLE (for 3.3V) * E_SCHMT = ENABLE (for 1.8V), DISABLE (for 3.3V)
* E_INPUT = ENABLE * E_INPUT = ENABLE
* TRISTATE = PASSTHROUGH * TRISTATE = PASSTHROUGH
* APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK * APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK
*/ */
// Configure SDMMC1 pinmux. // Enable deep loopback for SDMMC1 CLK pad.
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Enable deep loopback for SDMMC1 CLK pad. APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1;
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED;
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; // Configure SDMMC1 CLK pinmux, based on state and SoC type.
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; if (PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) != (PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN)) // Check if CLK pad is already configured.
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | (t210b01 ? PINMUX_PULL_NONE : PINMUX_PULL_DOWN);
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; // Configure the reset of SDMMC1 pins pinmux.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
// Force schmitt trigger for T210B01.
if (t210b01)
_sdmmc_config_sdmmc1_schmitt();
// Make sure the SDMMC1 controller is powered. // Make sure the SDMMC1 controller is powered.
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, PMC_NO_IOPOWER_SDMMC1_IO_EN, PMC_NO_IOPOWER_SDMMC1_IO_EN);
usleep(1000);
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, ~PMC_NO_IOPOWER_SDMMC1_IO_EN, PMC_NO_IOPOWER_SDMMC1_IO_EN); smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, ~PMC_NO_IOPOWER_SDMMC1_IO_EN, PMC_NO_IOPOWER_SDMMC1_IO_EN);
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, 0, 0); // Commit write.
// Inform IO pads that voltage is gonna be 3.3V. // Inform IO pads that voltage is gonna be 3.3V.
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN); smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN);
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, 0, 0); // Commit write.
// Set enable SD card power. // Set enable SD card power.
//PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2; // Pull down. //PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2; // Proper pinmuxing. Breaks on HOS, takes over 1 minute to recover.
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN | 1; // GPIO control, pull down. PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN | 1; // Wrong but working pinmuxing. Instant take over by FS.
gpio_config(GPIO_PORT_E, GPIO_PIN_4, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_E, GPIO_PIN_4, GPIO_MODE_GPIO);
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH); gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_ENABLE);
usleep(1000); usleep(10000);
// Enable SD card power. // Enable SD card IO power.
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
max77620_regulator_enable(REGULATOR_LDO2, 1); max77620_regulator_enable(REGULATOR_LDO2, 1);
usleep(1000); usleep(1000);
// Set pad slew codes to get good quality clock. // Set pad slew codes to get good quality clock.
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xFFFFFFF) | 0x50000000; if (!t210b01)
usleep(1000); {
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xFFFFFFF) | 0x50000000;
(void)APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL); // Commit write.
usleep(1000);
}
return 1; return 1;
} }
static void _sdmmc_config_emmc(u32 id) static void _sdmmc_config_emmc(u32 id, bool t210b01)
{ {
switch (id) switch (id)
{ {
case SDMMC_2: case SDMMC_2:
// Unset park for pads. if (!t210b01)
APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) &= 0xF8003FFF; {
// Unset park for pads.
APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) &= 0xF8003FFF;
(void)APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL); // Commit write.
}
else // Enable schmitt trigger for T210B01.
_sdmmc_config_sdmmc2_schmitt();
break; break;
case SDMMC_4: case SDMMC_4:
// Unset park for pads. // Unset park for pads.
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) &= 0xF8003FFF; APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) &= 0xF8003FFF;
// Set default pad cfg. // Set default pad cfg.
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040; if (t210b01)
APB_MISC(APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL) &= 0xFFBFFFF9; // Unset CMD/CLK/DQS powedown.
// Enabled schmitt trigger. // Enable schmitt trigger.
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) |= 1; // Enable Schmitt trigger. APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) |= 1;
(void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write.
break; break;
} }
} }
int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int auto_cal_enable) int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable)
{ {
const u32 trim_values[] = { 2, 8, 3, 8 }; u32 clock;
u16 divisor;
u8 vref_sel = 7;
if (id > SDMMC_4) const u32 trim_values_t210[] = { 2, 8, 3, 8 };
const u32 trim_values_t210b01[] = { 14, 13, 15, 13 };
const u32 *trim_values = sdmmc->t210b01 ? trim_values_t210b01 : trim_values_t210;
if (id > SDMMC_4 || id == SDMMC_3)
return 0; return 0;
memset(sdmmc, 0, sizeof(sdmmc_t)); memset(sdmmc, 0, sizeof(sdmmc_t));
@@ -1121,45 +1233,57 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int a
sdmmc->regs = (t210_sdmmc_t *)QueryIoMapping(_sdmmc_bases[id], 0x200); sdmmc->regs = (t210_sdmmc_t *)QueryIoMapping(_sdmmc_bases[id], 0x200);
sdmmc->id = id; sdmmc->id = id;
sdmmc->clock_stopped = 1; sdmmc->clock_stopped = 1;
sdmmc->t210b01 = splGetSocType() == SplSocType_Mariko;
// Do specific SDMMC HW configuration. // Do specific SDMMC HW configuration.
switch (id) switch (id)
{ {
case SDMMC_1: case SDMMC_1:
if (!_sdmmc_config_sdmmc1()) if (!_sdmmc_config_sdmmc1(sdmmc->t210b01))
return 0; return 0;
if (sdmmc->t210b01)
vref_sel = 0;
else
sdmmc->manual_cal = 1;
break; break;
case SDMMC_2: case SDMMC_2:
case SDMMC_4: case SDMMC_4:
_sdmmc_config_emmc(id); _sdmmc_config_emmc(id, sdmmc->t210b01);
break; break;
} }
// Disable clock if enabled.
if (clock_sdmmc_is_not_reset_and_enabled(id)) if (clock_sdmmc_is_not_reset_and_enabled(id))
{ {
_sdmmc_sd_clock_disable(sdmmc); _sdmmc_sd_clock_disable(sdmmc);
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
} }
u32 clock; // Configure and enable selected clock.
u16 divisor;
clock_sdmmc_get_card_clock_div(&clock, &divisor, type); clock_sdmmc_get_card_clock_div(&clock, &divisor, type);
clock_sdmmc_enable(id, clock); clock_sdmmc_enable(id, clock);
// Make sure all sdmmc registers are reset.
_sdmmc_reset_all(sdmmc);
sdmmc->clock_stopped = 0; sdmmc->clock_stopped = 0;
//TODO: make this skip-able. // Set default pad IO trimming configuration.
sdmmc->regs->iospare |= 0x80000; // Enable muxing. sdmmc->regs->iospare |= 0x80000; // Enable muxing.
sdmmc->regs->veniotrimctl &= 0xFFFFFFFB; // Set Band Gap VREG to supply DLL. sdmmc->regs->veniotrimctl &= 0xFFFFFFFB; // Set Band Gap VREG to supply DLL.
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | (trim_values[sdmmc->id] << 24); sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | (trim_values[sdmmc->id] << 24);
sdmmc->regs->sdmemcmppadctl = sdmmc->regs->sdmemcmppadctl =
(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK) | 7; (sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK) | vref_sel;
// Configure auto calibration values.
if (!_sdmmc_autocal_config_offset(sdmmc, power)) if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0; return 0;
// Calibrate pads.
_sdmmc_autocal_execute(sdmmc, power); _sdmmc_autocal_execute(sdmmc, power);
// Enable internal clock and power.
if (_sdmmc_enable_internal_clock(sdmmc)) if (_sdmmc_enable_internal_clock(sdmmc))
{ {
sdmmc_set_bus_width(sdmmc, bus_width); sdmmc_set_bus_width(sdmmc, bus_width);
@@ -1167,18 +1291,50 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int a
if (sdmmc_setup_clock(sdmmc, type)) if (sdmmc_setup_clock(sdmmc, type))
{ {
sdmmc_card_clock_ctrl(sdmmc, auto_cal_enable); sdmmc_card_clock_powersave(sdmmc, powersave_enable);
_sdmmc_card_clock_enable(sdmmc); _sdmmc_card_clock_enable(sdmmc);
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
return 1; return 1;
} }
return 0;
} }
return 0; return 0;
} }
void sdmmc1_disable_power()
{
// Clear pull down from CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK;
// Set pads to discharge state.
_sdmmc_config_sdmmc1_pads(true);
// Disable SD card IO power regulator.
max77620_regulator_enable(REGULATOR_LDO2, 0);
usleep(4000);
// Disable SD card IO power pin.
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
// T210/T210B01 WAR: Set start timer for IO and Controller power discharge.
msleep(239);
// Disable SDMMC1 controller power.
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, PMC_NO_IOPOWER_SDMMC1_IO_EN, PMC_NO_IOPOWER_SDMMC1_IO_EN);
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, 0, 0); // Commit write.
// Inform IO pads that next voltage might be 3.3V.
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN);
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, 0, 0); // Commit write.
// Set pads to reset state.
_sdmmc_config_sdmmc1_pads(false);
// Set pull down to CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_PULL_DOWN;
}
void sdmmc_end(sdmmc_t *sdmmc) void sdmmc_end(sdmmc_t *sdmmc)
{ {
if (!sdmmc->clock_stopped) if (!sdmmc->clock_stopped)
@@ -1189,17 +1345,9 @@ void sdmmc_end(sdmmc_t *sdmmc)
// Disable SD card power. // Disable SD card power.
if (sdmmc->id == SDMMC_1) if (sdmmc->id == SDMMC_1)
{ sdmmc1_disable_power();
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
max77620_regulator_enable(REGULATOR_LDO2, 0);
// Inform IO pads that next voltage might be 3.3V. _sdmmc_commit_changes(sdmmc);
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN);
msleep(100); // To power cycle min 1ms without power is needed.
}
_sdmmc_get_clkcon(sdmmc);
clock_sdmmc_disable(sdmmc->id); clock_sdmmc_disable(sdmmc->id);
sdmmc->clock_stopped = 1; sdmmc->clock_stopped = 1;
} }
@@ -1219,7 +1367,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
return 0; return 0;
// Recalibrate periodically for SDMMC1. // Recalibrate periodically for SDMMC1.
if (sdmmc->id == SDMMC_1 && sdmmc->auto_cal_enabled) if (sdmmc->manual_cal && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
int should_disable_sd_clock = 0; int should_disable_sd_clock = 0;
@@ -1227,7 +1375,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
{ {
should_disable_sd_clock = 1; should_disable_sd_clock = 1;
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
} }
@@ -1248,36 +1396,32 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
if (!sdmmc_setup_clock(sdmmc, SDHCI_TIMING_UHS_SDR12)) if (!sdmmc_setup_clock(sdmmc, SDHCI_TIMING_UHS_SDR12))
return 0; return 0;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
// Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed.
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
usleep(300); usleep(150);
// Inform IO pads that we switched to 1.8V. // Inform IO pads that we switched to 1.8V.
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, ~PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN); smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, ~PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN);
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, 0, 0); // Commit write.
// Enable schmitt trigger for better duty cycle and low jitter clock. // Enable schmitt trigger for better duty cycle and low jitter clock.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_SCHMT; _sdmmc_config_sdmmc1_schmitt();
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) |= PINMUX_SCHMT;
_sdmmc_autocal_config_offset(sdmmc, SDMMC_POWER_1_8); _sdmmc_autocal_config_offset(sdmmc, SDMMC_POWER_1_8);
_sdmmc_autocal_execute(sdmmc, SDMMC_POWER_1_8); _sdmmc_autocal_execute(sdmmc, SDMMC_POWER_1_8);
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_1_8); _sdmmc_set_io_power(sdmmc, SDMMC_POWER_1_8);
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
msleep(5); // Wait minimum 5ms before turning on the card clock. msleep(5); // Wait minimum 5ms before turning on the card clock.
// Turn on SDCLK. // Turn on SDCLK.
if (sdmmc->regs->hostctl2 & SDHCI_CTRL_VDD_180) if (sdmmc->regs->hostctl2 & SDHCI_CTRL_VDD_180)
{ {
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_get_clkcon(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep(1000); usleep(1000);
if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000) if ((sdmmc->regs->prnsts & SDHCI_DATA_LVL_MASK) == SDHCI_DATA_LVL_MASK)
return 1; return 1;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -195,13 +195,13 @@
#define SDHCI_TIMING_UHS_SDR104 11 #define SDHCI_TIMING_UHS_SDR104 11
#define SDHCI_TIMING_UHS_SDR82 12 // SDR104 with a 163.2MHz -> 81.6MHz clock. #define SDHCI_TIMING_UHS_SDR82 12 // SDR104 with a 163.2MHz -> 81.6MHz clock.
#define SDHCI_TIMING_UHS_DDR50 13 #define SDHCI_TIMING_UHS_DDR50 13
#define SDHCI_TIMING_MMC_DDR52 14 #define SDHCI_TIMING_MMC_HS102 14
#define SDHCI_CAN_64BIT 0x10000000 #define SDHCI_CAN_64BIT 0x10000000
/*! SDMMC Low power features. */ /*! SDMMC Low power features. */
#define SDMMC_AUTO_CAL_DISABLE 0 #define SDMMC_POWER_SAVE_DISABLE 0
#define SDMMC_AUTO_CAL_ENABLE 1 #define SDMMC_POWER_SAVE_ENABLE 1
/*! Helper for SWITCH command argument. */ /*! Helper for SWITCH command argument. */
#define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8)) #define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8))
@@ -213,7 +213,8 @@ typedef struct _sdmmc_t
u32 id; u32 id;
u32 divisor; u32 divisor;
u32 clock_stopped; u32 clock_stopped;
int auto_cal_enabled; int powersave_enabled;
int manual_cal;
int card_clock_enabled; int card_clock_enabled;
int venclkctl_set; int venclkctl_set;
u32 venclkctl_tap; u32 venclkctl_tap;
@@ -222,6 +223,7 @@ typedef struct _sdmmc_t
u64 dma_addr_next; u64 dma_addr_next;
u32 rsp[4]; u32 rsp[4];
u32 rsp3; u32 rsp3;
int t210b01;
} sdmmc_t; } sdmmc_t;
/*! SDMMC command. */ /*! SDMMC command. */
@@ -247,15 +249,15 @@ typedef struct _sdmmc_req_t
int sdmmc_get_io_power(sdmmc_t *sdmmc); int sdmmc_get_io_power(sdmmc_t *sdmmc);
u32 sdmmc_get_bus_width(sdmmc_t *sdmmc); u32 sdmmc_get_bus_width(sdmmc_t *sdmmc);
void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width); void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width);
void sdmmc_set_tap_value(sdmmc_t *sdmmc); void sdmmc_save_tap_value(sdmmc_t *sdmmc);
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type); int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type);
void sdmmc_card_clock_ctrl(sdmmc_t *sdmmc, int auto_cal_enable); void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable);
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type); int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type);
int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd); int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd);
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp); int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
int sdmmc_get_sd_power_enabled(); int sdmmc_get_sd_power_enabled();
bool sdmmc_get_sd_inserted(); bool sdmmc_get_sd_inserted();
int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int auto_cal_enable); int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable);
void sdmmc_end(sdmmc_t *sdmmc); void sdmmc_end(sdmmc_t *sdmmc);
void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy); void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy);
int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out); int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out);

View File

@@ -103,6 +103,7 @@ typedef struct _t210_sdmmc_t
vu32 iospare; vu32 iospare;
vu32 mcciffifoctl; vu32 mcciffifoctl;
vu32 timeoutwcoal; vu32 timeoutwcoal;
vu32 unk1;
} t210_sdmmc_t; } t210_sdmmc_t;
#endif #endif

View File

@@ -271,7 +271,7 @@ int sdmmc_nand_get_active_partition_index()
static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned int num_sectors, bool is_write) static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned int num_sectors, bool is_write)
{ {
if ((emuMMC_ctx.EMMC_Type == emuMMC_SD)) if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw))
{ {
// raw partition sector offset: emuMMC_ctx.EMMC_StoragePartitionOffset. // raw partition sector offset: emuMMC_ctx.EMMC_StoragePartitionOffset.
sector += emuMMC_ctx.EMMC_StoragePartitionOffset; sector += emuMMC_ctx.EMMC_StoragePartitionOffset;
@@ -318,6 +318,31 @@ static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned
return res; return res;
} }
// Controller open wrapper
uint64_t sdmmc_wrapper_controller_open(int mmc_id)
{
uint64_t result;
sdmmc_accessor_t *_this;
_this = sdmmc_accessor_get(mmc_id);
if (_this != NULL)
{
// Lock eMMC xfer while SD card is being initialized by FS.
if (_this == sdmmc_accessor_get(FS_SDMMC_SD))
mutex_lock_handler(FS_SDMMC_EMMC); // Recursive Mutex, handler will lock SD as well if custom_driver
result = _this->vtab->sdmmc_accessor_controller_open(_this);
// Unlock eMMC.
if (_this == sdmmc_accessor_get(FS_SDMMC_SD))
mutex_unlock_handler(FS_SDMMC_EMMC);
return result;
}
fatal_abort(Fatal_OpenAccessor);
}
// Controller close wrapper // Controller close wrapper
uint64_t sdmmc_wrapper_controller_close(int mmc_id) uint64_t sdmmc_wrapper_controller_close(int mmc_id)
{ {
@@ -389,7 +414,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
if (first_sd_read) if (first_sd_read)
{ {
first_sd_read = false; first_sd_read = false;
if (emuMMC_ctx.EMMC_Type == emuMMC_SD) if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
{ {
// Because some SD cards have issues with emuMMC's driver // Because some SD cards have issues with emuMMC's driver
// we currently swap to FS's driver after first SD read // we currently swap to FS's driver after first SD read
@@ -400,7 +425,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
} }
} }
// Call hekates driver. // Call hekate's driver.
if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf)) if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf))
{ {
mutex_unlock_handler(mmc_id); mutex_unlock_handler(mmc_id);

View File

@@ -52,6 +52,7 @@ void mutex_lock_handler(int mmc_id);
void mutex_unlock_handler(int mmc_id); void mutex_unlock_handler(int mmc_id);
// Hooks // Hooks
uint64_t sdmmc_wrapper_controller_open(int mmc_id);
uint64_t sdmmc_wrapper_controller_close(int mmc_id); uint64_t sdmmc_wrapper_controller_close(int mmc_id);
uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors); uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors);
uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize); uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize);

View File

@@ -30,7 +30,7 @@ enum emuMMC_Type
emuMMC_EMMC = 0, emuMMC_EMMC = 0,
// SD Device raw // SD Device raw
emuMMC_SD, emuMMC_SD_Raw,
// SD Device File // SD Device File
emuMMC_SD_File, emuMMC_SD_File,

View File

@@ -92,7 +92,7 @@ volatile __attribute__((aligned(0x1000))) emuMMC_ctx_t emuMMC_ctx = {
.fs_ver = FS_VER_MAX, .fs_ver = FS_VER_MAX,
// SD Default Metadata // SD Default Metadata
.SD_Type = emuMMC_SD, .SD_Type = emuMMC_SD_Raw,
.SD_StoragePartitionOffset = 0, .SD_StoragePartitionOffset = 0,
// EMMC Default Metadata // EMMC Default Metadata
@@ -155,8 +155,8 @@ void __initheap(void)
static void _receive_process_handle_thread(void *_session_handle) { static void _receive_process_handle_thread(void *_session_handle) {
Result rc; Result rc;
// Convert the argument to a handle we can use. // Convert the argument to a handle copy we can use.
Handle session_handle = (Handle)(uintptr_t)_session_handle; Handle session_handle = *(Handle*)_session_handle;
// Receive the request from the client thread. // Receive the request from the client thread.
memset(armGetTls(), 0, 0x10); memset(armGetTls(), 0, 0x10);
@@ -194,7 +194,7 @@ static void _init_process_handle(void) {
// Create a new thread to receive our handle. // Create a new thread to receive our handle.
Handle thread_handle; Handle thread_handle;
rc = svcCreateThread(&thread_handle, _receive_process_handle_thread, (void *)(uintptr_t)server_handle, temp_thread_stack + sizeof(temp_thread_stack), 0x20, 3); rc = svcCreateThread(&thread_handle, _receive_process_handle_thread, &server_handle, temp_thread_stack + sizeof(temp_thread_stack), 0x20, 3);
if (rc != 0) if (rc != 0)
{ {
fatal_abort(Fatal_BadResult); fatal_abort(Fatal_BadResult);
@@ -285,6 +285,9 @@ void setup_hooks(void)
INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read); INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read);
// sdmmc_wrapper_write hook // sdmmc_wrapper_write hook
INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write); INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write);
// sdmmc_wrapper_controller_open hook
if (fs_offsets->sdmmc_accessor_controller_open)
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_open, sdmmc_wrapper_controller_open);
// sdmmc_wrapper_controller_close hook // sdmmc_wrapper_controller_close hook
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close); INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close);
@@ -346,7 +349,7 @@ static void load_emummc_ctx(void)
emuMMC_ctx.id = config.base_cfg.id; emuMMC_ctx.id = config.base_cfg.id;
emuMMC_ctx.EMMC_Type = (enum emuMMC_Type)config.base_cfg.type; emuMMC_ctx.EMMC_Type = (enum emuMMC_Type)config.base_cfg.type;
emuMMC_ctx.fs_ver = (enum FS_VER)config.base_cfg.fs_version; emuMMC_ctx.fs_ver = (enum FS_VER)config.base_cfg.fs_version;
if (emuMMC_ctx.EMMC_Type == emuMMC_SD) if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
{ {
emuMMC_ctx.EMMC_StoragePartitionOffset = config.partition_cfg.start_sector; emuMMC_ctx.EMMC_StoragePartitionOffset = config.partition_cfg.start_sector;
} }

View File

@@ -59,6 +59,47 @@ Result smcGetConfig(SplConfigItem config_item, u64 *out_config)
return rc; return rc;
} }
SplHardwareType splGetHardwareType(void)
{
u64 value;
Result rc = smcGetConfig(SplConfigItem_HardwareType, &value);
if (rc != 0)
{
fatal_abort(Fatal_BadResult);
}
return (SplHardwareType)value;
}
SplSocType splGetSocType(void)
{
static SplSocType soc_type;
static bool soc_type_set = false;
if (soc_type_set)
return soc_type;
switch (splGetHardwareType())
{
case SplHardwareType_Icosa:
case SplHardwareType_Copper:
soc_type = SplSocType_Erista;
break;
case SplHardwareType_Hoag:
case SplHardwareType_Iowa:
case SplHardwareType_Calcio:
case SplHardwareType_Five:
soc_type = SplSocType_Mariko;
break;
default:
fatal_abort(Fatal_InvalidEnum);
}
soc_type_set = true;
return soc_type;
}
Result smcCopyToIram(uintptr_t iram_addr, const void *src_addr, u32 size) Result smcCopyToIram(uintptr_t iram_addr, const void *src_addr, u32 size)
{ {
SecmonArgs args; SecmonArgs args;

View File

@@ -37,6 +37,20 @@ typedef enum {
SplConfigItem_HasRcmBugPatch = 65004, SplConfigItem_HasRcmBugPatch = 65004,
} SplConfigItem; } SplConfigItem;
typedef enum {
SplSocType_Erista = 0,
SplSocType_Mariko = 1,
} SplSocType;
typedef enum {
SplHardwareType_Icosa = 0,
SplHardwareType_Copper = 1,
SplHardwareType_Hoag = 2,
SplHardwareType_Iowa = 3,
SplHardwareType_Calcio = 4,
SplHardwareType_Five = 5,
} SplHardwareType;
typedef enum { typedef enum {
EXO_EMUMMC_TYPE_NONE = 0, EXO_EMUMMC_TYPE_NONE = 0,
EXO_EMUMMC_TYPE_PARTITION = 1, EXO_EMUMMC_TYPE_PARTITION = 1,
@@ -69,6 +83,9 @@ typedef struct {
Result smcGetConfig(SplConfigItem config_item, u64 *out_config); Result smcGetConfig(SplConfigItem config_item, u64 *out_config);
SplHardwareType splGetHardwareType(void);
SplSocType splGetSocType(void);
void smcRebootToRcm(void); void smcRebootToRcm(void);
void smcRebootToIramPayload(void); void smcRebootToIramPayload(void);
void smcPerformShutdown(void); void smcPerformShutdown(void);

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -410,7 +411,7 @@ void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type)
*pclock = 40800; *pclock = 40800;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_MMC_DDR52: // Actual IO Freq: 49.92 MHz. case SDHCI_TIMING_MMC_HS102: // Actual IO Freq: 99.84 MHz.
*pclock = 200000; *pclock = 200000;
*pdivisor = 2; *pdivisor = 2;
break; break;

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -17,78 +18,151 @@
#include "../soc/gpio.h" #include "../soc/gpio.h"
#include "../soc/t210.h" #include "../soc/t210.h"
static const u16 _gpio_cnf[31] = { #define GPIO_BANK_IDX(port) ((port) >> 2)
0x000, 0x004, 0x008, 0x00C,
0x100, 0x104, 0x108, 0x10C,
0x200, 0x204, 0x208, 0x20C,
0x300, 0x304, 0x308, 0x30C,
0x400, 0x404, 0x408, 0x40C,
0x500, 0x504, 0x508, 0x50C,
0x600, 0x604, 0x608, 0x60C,
0x700, 0x704, 0x708
};
static const u16 _gpio_oe[31] = { #define GPIO_CNF_OFFSET(port) (0x00 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x010, 0x014, 0x018, 0x01C, #define GPIO_OE_OFFSET(port) (0x10 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x110, 0x114, 0x118, 0x11C, #define GPIO_OUT_OFFSET(port) (0x20 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x210, 0x214, 0x218, 0x21C, #define GPIO_IN_OFFSET(port) (0x30 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x310, 0x314, 0x318, 0x31C, #define GPIO_INT_STA_OFFSET(port) (0x40 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x410, 0x414, 0x418, 0x41C, #define GPIO_INT_ENB_OFFSET(port) (0x50 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x510, 0x514, 0x518, 0x51C, #define GPIO_INT_LVL_OFFSET(port) (0x60 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x610, 0x614, 0x618, 0x61C, #define GPIO_INT_CLR_OFFSET(port) (0x70 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x710, 0x714, 0x718
};
static const u16 _gpio_out[31] = { #define GPIO_CNF_MASKED_OFFSET(port) (0x80 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x020, 0x024, 0x028, 0x02C, #define GPIO_OE_MASKED_OFFSET(port) (0x90 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x120, 0x124, 0x128, 0x12C, #define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x220, 0x224, 0x228, 0x22C, #define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x320, 0x324, 0x328, 0x32C, #define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x420, 0x424, 0x428, 0x42C, #define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
0x520, 0x524, 0x528, 0x52C,
0x620, 0x624, 0x628, 0x62C,
0x720, 0x724, 0x728
};
static const u16 _gpio_in[31] = { #define GPIO_IRQ_BANK1 32
0x030, 0x034, 0x038, 0x03C, #define GPIO_IRQ_BANK2 33
0x130, 0x134, 0x138, 0x13C, #define GPIO_IRQ_BANK3 34
0x230, 0x234, 0x238, 0x23C, #define GPIO_IRQ_BANK4 35
0x330, 0x334, 0x338, 0x33C, #define GPIO_IRQ_BANK5 55
0x430, 0x434, 0x438, 0x43C, #define GPIO_IRQ_BANK6 87
0x530, 0x534, 0x538, 0x53C, #define GPIO_IRQ_BANK7 89
0x630, 0x634, 0x638, 0x63C, #define GPIO_IRQ_BANK8 125
0x730, 0x734, 0x738
static u8 gpio_bank_irq_ids[8] = {
GPIO_IRQ_BANK1, GPIO_IRQ_BANK2, GPIO_IRQ_BANK3, GPIO_IRQ_BANK4,
GPIO_IRQ_BANK5, GPIO_IRQ_BANK6, GPIO_IRQ_BANK7, GPIO_IRQ_BANK8
}; };
void gpio_config(u32 port, u32 pins, int mode) void gpio_config(u32 port, u32 pins, int mode)
{ {
u32 offset = GPIO_CNF_OFFSET(port);
if (mode) if (mode)
GPIO(_gpio_cnf[port]) |= pins; GPIO(offset) |= pins;
else else
GPIO(_gpio_cnf[port]) &= ~pins; GPIO(offset) &= ~pins;
(void)GPIO(_gpio_cnf[port]);
(void)GPIO(offset); // Commit the write.
} }
void gpio_output_enable(u32 port, u32 pins, int enable) void gpio_output_enable(u32 port, u32 pins, int enable)
{ {
u32 port_offset = GPIO_OE_OFFSET(port);
if (enable) if (enable)
GPIO(_gpio_oe[port]) |= pins; GPIO(port_offset) |= pins;
else else
GPIO(_gpio_oe[port]) &= ~pins; GPIO(port_offset) &= ~pins;
(void)GPIO(_gpio_oe[port]);
(void)GPIO(port_offset); // Commit the write.
} }
void gpio_write(u32 port, u32 pins, int high) void gpio_write(u32 port, u32 pins, int high)
{ {
u32 port_offset = GPIO_OUT_OFFSET(port);
if (high) if (high)
GPIO(_gpio_out[port]) |= pins; GPIO(port_offset) |= pins;
else else
GPIO(_gpio_out[port]) &= ~pins; GPIO(port_offset) &= ~pins;
(void)GPIO(_gpio_out[port]);
(void)GPIO(port_offset); // Commit the write.
} }
int gpio_read(u32 port, u32 pins) int gpio_read(u32 port, u32 pins)
{ {
return (GPIO(_gpio_in[port]) & pins) ? 1 : 0; u32 port_offset = GPIO_IN_OFFSET(port);
return (GPIO(port_offset) & pins) ? 1 : 0;
}
static void _gpio_interrupt_clear(u32 port, u32 pins)
{
u32 port_offset = GPIO_INT_CLR_OFFSET(port);
GPIO(port_offset) |= pins;
(void)GPIO(port_offset); // Commit the write.
}
int gpio_interrupt_status(u32 port, u32 pins)
{
u32 port_offset = GPIO_INT_STA_OFFSET(port);
u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins;
int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0;
// Clear the interrupt status.
if (status)
_gpio_interrupt_clear(port, pins);
return status;
}
void gpio_interrupt_enable(u32 port, u32 pins, int enable)
{
u32 port_offset = GPIO_INT_ENB_OFFSET(port);
// Clear any possible stray interrupt.
_gpio_interrupt_clear(port, pins);
if (enable)
GPIO(port_offset) |= pins;
else
GPIO(port_offset) &= ~pins;
(void)GPIO(port_offset); // Commit the write.
}
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta)
{
u32 port_offset = GPIO_INT_LVL_OFFSET(port);
u32 val = GPIO(port_offset);
if (high)
val |= pins;
else
val &= ~pins;
if (edge)
val |= pins << 8;
else
val &= ~(pins << 8);
if (delta)
val |= pins << 16;
else
val &= ~(pins << 16);
GPIO(port_offset) = val;
(void)GPIO(port_offset); // Commit the write.
// Clear any possible stray interrupt.
_gpio_interrupt_clear(port, pins);
}
u32 gpio_get_bank_irq_id(u32 port)
{
u32 bank_idx = GPIO_BANK_IDX(port);
return gpio_bank_irq_ids[bank_idx];
} }

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -21,10 +22,23 @@
#define GPIO_MODE_SPIO 0 #define GPIO_MODE_SPIO 0
#define GPIO_MODE_GPIO 1 #define GPIO_MODE_GPIO 1
#define GPIO_OUTPUT_DISABLE 0 #define GPIO_OUTPUT_DISABLE 0
#define GPIO_OUTPUT_ENABLE 1 #define GPIO_OUTPUT_ENABLE 1
#define GPIO_IRQ_DISABLE 0
#define GPIO_IRQ_ENABLE 1
#define GPIO_LOW 0 #define GPIO_LOW 0
#define GPIO_HIGH 1 #define GPIO_HIGH 1
#define GPIO_FALLING 0
#define GPIO_RISING 1
#define GPIO_LEVEL 0
#define GPIO_EDGE 1
#define GPIO_CONFIGURED_EDGE 0
#define GPIO_ANY_EDGE_CHANGE 1
/*! GPIO pins (0-7 for each port). */ /*! GPIO pins (0-7 for each port). */
#define GPIO_PIN_0 (1 << 0) #define GPIO_PIN_0 (1 << 0)
@@ -72,6 +86,10 @@
void gpio_config(u32 port, u32 pins, int mode); void gpio_config(u32 port, u32 pins, int mode);
void gpio_output_enable(u32 port, u32 pins, int enable); void gpio_output_enable(u32 port, u32 pins, int enable);
void gpio_write(u32 port, u32 pins, int high); void gpio_write(u32 port, u32 pins, int high);
int gpio_read(u32 port, u32 pins); int gpio_read(u32 port, u32 pins);
int gpio_interrupt_status(u32 port, u32 pins);
void gpio_interrupt_enable(u32 port, u32 pins, int enable);
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta);
u32 gpio_get_bank_irq_id(u32 port);
#endif #endif

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -20,25 +21,88 @@
#include "../utils/util.h" #include "../utils/util.h"
#include "t210.h" #include "t210.h"
// TODO: not hardcode I2C_5 #define I2C_PACKET_PROT_I2C (1 << 4)
static u64 i2c_addrs[] = { #define I2C_HEADER_CONT_XFER (1 << 15)
0x7000C000, 0x7000C400, 0x7000C500, #define I2C_HEADER_REP_START (1 << 16)
0x7000C700, 0x7000D000, 0x7000D100 #define I2C_HEADER_IE_ENABLE (1 << 17)
#define I2C_HEADER_READ (1 << 19)
#define I2C_CNFG (0x00 / 4)
#define CMD1_WRITE (0 << 6)
#define CMD1_READ (1 << 6)
#define NORMAL_MODE_GO (1 << 9)
#define PACKET_MODE_GO (1 << 10)
#define NEW_MASTER_FSM (1 << 11)
#define DEBOUNCE_CNT_4T (2 << 12)
#define I2C_CMD_ADDR0 (0x04 / 4)
#define ADDR0_WRITE 0
#define ADDR0_READ 1
#define I2C_CMD_DATA1 (0x0C / 4)
#define I2C_CMD_DATA2 (0x10 / 4)
#define I2C_STATUS (0x1C / 4)
#define I2C_STATUS_NOACK (0xF << 0)
#define I2C_STATUS_BUSY (1 << 8)
#define I2C_TX_FIFO (0x50 / 4)
#define I2C_RX_FIFO (0x54 / 4)
#define I2C_FIFO_CONTROL (0x5C / 4)
#define RX_FIFO_FLUSH (1 << 0)
#define TX_FIFO_FLUSH (1 << 1)
#define I2C_FIFO_STATUS (0x60 / 4)
#define RX_FIFO_FULL_CNT (0xF << 0)
#define TX_FIFO_EMPTY_CNT (0xF << 4)
#define I2C_INT_EN (0x64 / 4)
#define I2C_INT_STATUS (0x68 / 4)
#define I2C_INT_SOURCE (0x70 / 4)
#define RX_FIFO_DATA_REQ (1 << 0)
#define TX_FIFO_DATA_REQ (1 << 1)
#define ARB_LOST (1 << 2)
#define NO_ACK (1 << 3)
#define RX_FIFO_UNDER (1 << 4)
#define TX_FIFO_OVER (1 << 5)
#define ALL_PACKETS_COMPLETE (1 << 6)
#define PACKET_COMPLETE (1 << 7)
#define BUS_CLEAR_DONE (1 << 11)
#define I2C_CLK_DIVISOR (0x6C / 4)
#define I2C_BUS_CLEAR_CONFIG (0x84 / 4)
#define BC_ENABLE (1 << 0)
#define BC_TERMINATE (1 << 1)
#define I2C_BUS_CLEAR_STATUS (0x88 / 4)
#define I2C_CONFIG_LOAD (0x8C / 4)
#define MSTR_CONFIG_LOAD (1 << 0)
#define TIMEOUT_CONFIG_LOAD (1 << 2)
static const u64 i2c_addrs[] = {
0x7000C000, // I2C_1.
0x7000C400, // I2C_2.
0x7000C500, // I2C_3.
0x7000C700, // I2C_4.
0x7000D000, // I2C_5.
0x7000D100 // I2C_6.
}; };
static void _i2c_wait(vu32 *base) static void _i2c_load_cfg_wait(vu32 *base)
{ {
base[I2C_CONFIG_LOAD] = 0x25; base[I2C_CONFIG_LOAD] = (1 << 5) | TIMEOUT_CONFIG_LOAD | MSTR_CONFIG_LOAD;
for (u32 i = 0; i < 20; i++) for (u32 i = 0; i < 20; i++)
{ {
usleep(1); usleep(1);
if (!(base[I2C_CONFIG_LOAD] & 1)) if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD))
break; break;
} }
} }
static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size) static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
{ {
if (size > 4) if (size > 4)
return 0; return 0;
@@ -47,46 +111,58 @@ static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
memcpy(&tmp, buf, size); memcpy(&tmp, buf, size);
vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000); vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000);
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
// Set device address and send mode.
base[I2C_CMD_ADDR0] = dev_addr << 1 | ADDR0_WRITE;
base[I2C_CMD_DATA1] = tmp; //Set value. base[I2C_CMD_DATA1] = tmp; //Set value.
base[I2C_CNFG] = ((size - 1) << 1) | 0x2800; //Set size and send mode. // Set size and send mode.
_i2c_wait(base); //Kick transaction. base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE;
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200; // Load configuration.
_i2c_load_cfg_wait(base);
u32 timeout = get_tmr_ms() + 1500; // Initiate transaction on normal mode.
while (base[I2C_STATUS] & 0x100) base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u64 timeout = get_tmr_ms() + 100;
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{ {
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
return 0; return 0;
} }
if (base[I2C_STATUS] << 28) if (base[I2C_STATUS] & I2C_STATUS_NOACK)
return 0; return 0;
return 1; return 1;
} }
static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x) static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
{ {
if (size > 8) if (size > 4)
return 0; return 0;
vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000); vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000);
base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode). // Set device address and recv mode.
base[I2C_CNFG] = ((size - 1) << 1) | 0x2840; // Set size and recv mode. base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ;
_i2c_wait(base); // Kick transaction.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200; // Set size and recv mode.
base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ;
u32 timeout = get_tmr_ms() + 1500; // Load configuration.
while (base[I2C_STATUS] & 0x100) _i2c_load_cfg_wait(base);
// Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u64 timeout = get_tmr_ms() + 100;
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{ {
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
return 0; return 0;
} }
if (base[I2C_STATUS] << 28) if (base[I2C_STATUS] & I2C_STATUS_NOACK)
return 0; return 0;
u32 tmp = base[I2C_CMD_DATA1]; // Get LS value. u32 tmp = base[I2C_CMD_DATA1]; // Get LS value.
@@ -106,50 +182,52 @@ void i2c_init()
{ {
vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000); vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000);
base[I2C_CLK_DIVISOR_REGISTER] = 0x50001; base[I2C_CLK_DIVISOR] = (5 << 16) | 1; // SF mode Div: 6, HS mode div: 2.
base[I2C_BUS_CLEAR_CONFIG] = 0x90003; base[I2C_BUS_CLEAR_CONFIG] = (9 << 16) | BC_TERMINATE | BC_ENABLE;
_i2c_wait(base);
// Load configuration.
_i2c_load_cfg_wait(base);
for (u32 i = 0; i < 10; i++) for (u32 i = 0; i < 10; i++)
{ {
if (base[INTERRUPT_STATUS_REGISTER] & 0x800) if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE)
break; break;
} }
(vu32)base[I2C_BUS_CLEAR_STATUS]; (vu32)base[I2C_BUS_CLEAR_STATUS];
base[INTERRUPT_STATUS_REGISTER] = base[INTERRUPT_STATUS_REGISTER]; base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
} }
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size) int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size)
{ {
u8 tmp[4]; u8 tmp[4];
if (size > 3) if (size > 3)
return 0; return 0;
tmp[0] = y; tmp[0] = reg;
memcpy(tmp + 1, buf, size); memcpy(tmp + 1, buf, size);
return _i2c_send_pkt(idx, x, tmp, size + 1); return _i2c_send_single(i2c_idx, dev_addr, tmp, size + 1);
} }
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y) int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
{ {
int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1); int res = _i2c_send_single(i2c_idx, dev_addr, (u8 *)&reg, 1);
if (res) if (res)
res = _i2c_recv_pkt(idx, buf, size, x); res = _i2c_recv_single(i2c_idx, buf, size, dev_addr);
return res; return res;
} }
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b) int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val)
{ {
return i2c_send_buf_small(idx, x, y, &b, 1); return i2c_send_buf_small(i2c_idx, dev_addr, reg, &val, 1);
} }
u8 i2c_recv_byte(u32 idx, u32 x, u32 y) u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg)
{ {
u8 tmp = 0; u8 tmp = 0;
i2c_recv_buf_small(&tmp, 1, idx, x, y); i2c_recv_buf_small(&tmp, 1, i2c_idx, dev_addr, reg);
return tmp; return tmp;
} }

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -26,21 +27,10 @@
#define I2C_5 4 #define I2C_5 4
#define I2C_6 5 #define I2C_6 5
#define I2C_CNFG 0x00
#define I2C_CMD_ADDR0 0x01
#define I2C_CMD_DATA1 0x03
#define I2C_CMD_DATA2 0x04
#define I2C_STATUS 0x07
#define INTERRUPT_STATUS_REGISTER 0x1A
#define I2C_CLK_DIVISOR_REGISTER 0x1B
#define I2C_BUS_CLEAR_CONFIG 0x21
#define I2C_BUS_CLEAR_STATUS 0x22
#define I2C_CONFIG_LOAD 0x23
void i2c_init(); void i2c_init();
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size); int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size);
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y); int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b); int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val);
u8 i2c_recv_byte(u32 idx, u32 x, u32 y); u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg);
#endif #endif

View File

@@ -51,6 +51,18 @@
#define PINMUX_AUX_GPIO_PE6 0x248 #define PINMUX_AUX_GPIO_PE6 0x248
#define PINMUX_AUX_GPIO_PH6 0x250 #define PINMUX_AUX_GPIO_PH6 0x250
#define PINMUX_AUX_GPIO_PZ1 0x280 #define PINMUX_AUX_GPIO_PZ1 0x280
/* Only in T210B01 */
#define PINMUX_AUX_SDMMC2_DAT0 0x294
#define PINMUX_AUX_SDMMC2_DAT1 0x298
#define PINMUX_AUX_SDMMC2_DAT2 0x29C
#define PINMUX_AUX_SDMMC2_DAT3 0x2A0
#define PINMUX_AUX_SDMMC2_DAT4 0x2A4
#define PINMUX_AUX_SDMMC2_DAT5 0x2A8
#define PINMUX_AUX_SDMMC2_DAT6 0x2AC
#define PINMUX_AUX_SDMMC2_DAT7 0x2B0
#define PINMUX_AUX_SDMMC2_CLK 0x2B4
#define PINMUX_AUX_SDMMC2_CMD 0x2BC
/*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */ /*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */
#define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x)) #define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x))
#define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x)) #define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x))
@@ -78,7 +90,8 @@
#define PINMUX_OPEN_DRAIN (1 << 11) #define PINMUX_OPEN_DRAIN (1 << 11)
#define PINMUX_SCHMT (1 << 12) #define PINMUX_SCHMT (1 << 12)
#define PINMUX_DRIVE_1X (0 << 13) #define PINMUX_DRIVE_MASK (3 << 13)
#define PINMUX_DRIVE_1X (0 << 13)
#define PINMUX_DRIVE_2X (1 << 13) #define PINMUX_DRIVE_2X (1 << 13)
#define PINMUX_DRIVE_3X (2 << 13) #define PINMUX_DRIVE_3X (2 << 13)
#define PINMUX_DRIVE_4X (3 << 13) #define PINMUX_DRIVE_4X (3 << 13)

View File

@@ -35,6 +35,7 @@ enum FatalReason
Fatal_FatfsMount, Fatal_FatfsMount,
Fatal_FatfsFileOpen, Fatal_FatfsFileOpen,
Fatal_FatfsMemExhaustion, Fatal_FatfsMemExhaustion,
Fatal_InvalidEnum,
Fatal_Max Fatal_Max
}; };

View File

@@ -38,6 +38,7 @@ static inline uintptr_t _GetIoMapping(u64 io_addr, u64 io_size)
u64 vaddr; u64 vaddr;
u64 aligned_addr = (io_addr & ~0xFFFul); u64 aligned_addr = (io_addr & ~0xFFFul);
u64 aligned_size = io_size + (io_addr - aligned_addr); u64 aligned_size = io_size + (io_addr - aligned_addr);
if (emuMMC_ctx.fs_ver >= FS_VER_10_0_0) { if (emuMMC_ctx.fs_ver >= FS_VER_10_0_0) {
u64 out_size; u64 out_size;
if (svcQueryIoMapping(&vaddr, &out_size, aligned_addr, aligned_size) != 0) { if (svcQueryIoMapping(&vaddr, &out_size, aligned_addr, aligned_size) != 0) {
@@ -48,6 +49,7 @@ static inline uintptr_t _GetIoMapping(u64 io_addr, u64 io_size)
fatal_abort(Fatal_IoMappingLegacy); fatal_abort(Fatal_IoMappingLegacy);
} }
} }
return (uintptr_t)(vaddr + (io_addr - aligned_addr)); return (uintptr_t)(vaddr + (io_addr - aligned_addr));
} }

View File

@@ -18,8 +18,7 @@ for i in range(6):
if i < len(section_names): if i < len(section_names):
section["Name"] = section_names[i] section["Name"] = section_names[i]
section["OutOffset"], section["DecompressedSize"], section["CompressedSize"], section["Attribute"] = unpack( section["OutOffset"], section["DecompressedSize"], section["CompressedSize"], section["Attribute"] = unpack("IIII", section_bytes)
"IIII", section_bytes)
sections.append(section) sections.append(section)
print(section) print(section)

View File

@@ -1,47 +1,75 @@
TARGETS := exosphere.bin warmboot.bin program.lz4 ATMOSPHERE_BUILD_CONFIGS :=
CLEAN_TARGETS := exosphere-clean program-clean boot_code-clean warmboot-clean all: release
SUBFOLDERS := $(MODULES) define ATMOSPHERE_ADD_TARGET
all: exosphere.bin warmboot.bin ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
clean: $(CLEAN_TARGETS) $(strip $1): exosphere$(strip $2).bin warmboot$(strip $2).bin mariko_fatal$(strip $2).bin
@rm -f exosphere.bin
exosphere.bin: program.lz4 boot_code.lz4 exosphere$(strip $2).bin: loader_stub/loader_stub$(strip $2).bin
$(MAKE) -C loader_stub @cp loader_stub/loader_stub$(strip $2).bin exosphere$(strip $2).bin
@cp loader_stub/loader_stub.bin exosphere.bin @printf LENY >> exosphere$(strip $2).bin
@printf LENY >> exosphere.bin @echo "Built exosphere$(strip $2).bin..."
@echo "Built exosphere.bin..."
program.lz4: build_program warmboot$(strip $2).bin: warmboot/warmboot$(strip $2).bin
@cp program/program.lz4 program.lz4 @cp warmboot/warmboot$(strip $2).bin warmboot$(strip $2).bin
@cp program/boot_code.lz4 boot_code.lz4 @echo "Built warmboot$(strip $2).bin..."
build_program: mariko_fatal$(strip $2).bin: mariko_fatal/mariko_fatal$(strip $2).bin
$(MAKE) -C program @cp mariko_fatal/mariko_fatal$(strip $2).bin mariko_fatal$(strip $2).bin
@echo "Built mariko_fatal$(strip $2).bin..."
warmboot.bin: build_warmboot check_program_$(strip $1):
@cp warmboot/warmboot.bin warmboot.bin @$$(MAKE) -C program $(strip $1)
build_warmboot: check_warmboot_$(strip $1):
$(MAKE) -C warmboot @$$(MAKE) -C warmboot $(strip $1)
boot_code.lz4: program.lz4 check_mariko_fatal_$(strip $1):
@$$(MAKE) -C mariko_fatal $(strip $1)
exosphere-clean: loader_stub/loader_stub$(strip $2).bin: check_program_$(strip $1)
$(MAKE) -C loader_stub clean @$$(MAKE) -C loader_stub $(strip $1)
@rm -f exosphere.bin
program-clean: warmboot/warmboot$(strip $2).bin: check_warmboot_$(strip $1)
$(MAKE) -C program clean
@rm -f program.lz4
warmboot-clean: mariko_fatal/mariko_fatal$(strip $2).bin: check_mariko_fatal_$(strip $1)
$(MAKE) -C warmboot clean
@rm -f warmboot.bin
boot_code-clean: clean-$(strip $1): clean-program-$(strip $1) clean-loader_stub-$(strip $1) clean-warmboot-$(strip $1) clean-mariko_fatal-$(strip $1)
@rm -f boot_code.lz4 @rm -rf exosphere$(strip $2).bin warmboot$(strip $2).bin mariko_fatal$(strip $2).bin
.PHONY: all clean build_program $(CLEAN_TARGETS) clean-program-$(strip $1):
@$$(MAKE) -C program clean-$(strip $1)
clean-loader_stub-$(strip $1):
@$$(MAKE) -C loader_stub clean-$(strip $1)
clean-warmboot-$(strip $1):
@$$(MAKE) -C warmboot clean-$(strip $1)
clean-mariko_fatal-$(strip $1):
@$$(MAKE) -C mariko_fatal clean-$(strip $1)
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, release, ))
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug))
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit))
clean: clean-program clean-loader_stub clean-warmboot
@rm -rf exosphere*.bin warmboot*.bin mariko_fatal*.bin
clean-program:
@$(MAKE) -C program clean
clean-loader_stub:
@$(MAKE) -C loader_stub clean
clean-warmboot:
@$(MAKE) -C warmboot clean
clean-mariko_fatal:
@$(MAKE) -C mariko_fatal clean
.PHONY: all clean clean-program clean-loader_stub clean-warmboot $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),check_program_$(config) check_warmboot_$(strip $1) clean-$(config) clean-program-$(config) clean-loader_stub-$(config) clean-warmboot-$(config))

View File

@@ -7,28 +7,24 @@ export ATMOSPHERE_CPU := arm-cortex-a57
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# pull in common atmosphere configuration # pull in common atmosphere configuration
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional # no real need to edit anything past this point unless you need to add additional
# rules for different file extensions # rules for different file extensions
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR))) ifneq ($(__RECURSIVE__),1)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
export TOPDIR := $(CURDIR) $(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(TOPDIR)/../program
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c) CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp) CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s) SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
BINFILES :=
BINFILES := program.lz4 boot_code.lz4
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C # use CXX for linking C++ projects, CC for standard C
@@ -44,70 +40,116 @@ else
endif endif
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC) export OFILES := $(OFILES_SRC) program.lz4.o boot_code.lz4.o
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES))))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I. -I.
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib -L$(dir)/$(ATMOSPHERE_LIBRARY_DIR)) export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
.PHONY: $(BUILD) clean all check_program export TOPDIR := $(CURRENT_DIRECTORY)
OUTPUT_BASE := $(TOPDIR)/$(notdir $(TOPDIR))
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
all: $(BUILD) check_program
$(BUILD): check_program ATMOSPHERE_BUILD_CONFIGS :=
all: release
define ATMOSPHERE_ADD_TARGET
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
$(strip $1): check_libexo_$(strip $1) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1)
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(OUTPUT_BASE)$(strip $2) $(3) \
ATMOSPHERE_BUILD_TARGET_IDENTIFIER=$(strip $1)\
ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX=$(strip $2)\
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
LIBEXOSPHERE_NAME=exosphere$(strip $2) \
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
-f $$(THIS_MAKEFILE)
check_libexo_$(strip $1):
@$$(MAKE) --no-print-directory -C $$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere $$(ATMOSPHERE_ARCH_NAME)-$(strip $1)
clean-$(strip $1):
@echo clean $(strip $1) ...
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).elf $$(OUTPUT_BASE)$(strip $2).lz4 boot_code$(strip $2).lz4
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, release, , \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug, \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_DEBUGGING" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit, \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_AUDITING" \
))
$(ATMOSPHERE_BUILD_DIR)/%:
@[ -d $@ ] || mkdir -p $@ @[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
check_program:
@$(MAKE) -C ../program all
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
clean: clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf .PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
else else
.PHONY: all
DEPENDS := $(OFILES:.o=.d) DEPENDS := $(OFILES:.o=.d)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# main targets # main targets
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
all : $(OUTPUT).bin
$(OUTPUT).bin : $(OUTPUT).elf $(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@ $(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
@echo built ... $(notdir $@) @echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES) ../../../libraries/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/libexosphere.a $(OUTPUT).elf : $(OFILES)
$(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/lib$(LIBEXOSPHERE_NAME).a
program.lz4.o: program_lz4.h
program_lz4.h: $(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4
@echo $(notdir $<)
@rm -rf tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
@mkdir -p tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
@cp $(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4 tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)/program.lz4
@bin2s -a 8 -H program_lz4.h tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)/program.lz4 | $(AS) -o program.lz4.o
@rm -rf tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
$(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4:
@$(MAKE) __RECURSIVE__=0 --no-print-directory -C $(TOPDIR)/../program $(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
boot_code.lz4.o: boot_code_lz4.h
boot_code_lz4.h: $(TOPDIR)/../program/boot_code$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4
@echo $(notdir $<)
@rm -rf tmp_boot_code_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
@mkdir -p tmp_boot_code_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
@cp $(TOPDIR)/../program/boot_code$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4 tmp_boot_code_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)/boot_code.lz4
@bin2s -a 8 -H boot_code_lz4.h tmp_boot_code_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)/boot_code.lz4 | $(AS) -o boot_code.lz4.o
@rm -rf tmp_boot_code_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
$(TOPDIR)/../program/boot_code$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4: $(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4
%.elf: %.elf:
@echo linking $(notdir $@) @echo linking $(notdir $@)
$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ $(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst) @$(NM) -CSn $@ > $(notdir $*.lst)
$(OFILES_SRC) : $(HFILES_BIN) $(OFILES_SRC) : program_lz4.h boot_code_lz4.h
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h: %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
%.lz4.o %_lz4.h: %.lz4
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS) -include $(DEPENDS)

View File

@@ -24,7 +24,6 @@ namespace ams::secmon::loader {
/* Uncompress the program image. */ /* Uncompress the program image. */
Uncompress(secmon::MemoryRegionPhysicalTzramFullProgramImage.GetPointer(), secmon::MemoryRegionPhysicalTzramFullProgramImage.GetSize(), program_lz4, program_lz4_size); Uncompress(secmon::MemoryRegionPhysicalTzramFullProgramImage.GetPointer(), secmon::MemoryRegionPhysicalTzramFullProgramImage.GetSize(), program_lz4, program_lz4_size);
/* Copy the boot image to the end of IRAM */ /* Copy the boot image to the end of IRAM */
u8 *relocated_boot_code = secmon::MemoryRegionPhysicalIramBootCodeImage.GetEndPointer<u8>() - boot_code_lz4_size; u8 *relocated_boot_code = secmon::MemoryRegionPhysicalIramBootCodeImage.GetEndPointer<u8>() - boot_code_lz4_size;
std::memcpy(relocated_boot_code, boot_code_lz4, boot_code_lz4_size); std::memcpy(relocated_boot_code, boot_code_lz4, boot_code_lz4_size);
@@ -32,7 +31,6 @@ namespace ams::secmon::loader {
/* Uncompress the boot image. */ /* Uncompress the boot image. */
Uncompress(secmon::MemoryRegionPhysicalIramBootCodeImage.GetPointer(), secmon::MemoryRegionPhysicalIramBootCodeImage.GetSize(), relocated_boot_code, boot_code_lz4_size); Uncompress(secmon::MemoryRegionPhysicalIramBootCodeImage.GetPointer(), secmon::MemoryRegionPhysicalIramBootCodeImage.GetSize(), relocated_boot_code, boot_code_lz4_size);
/* Jump to the boot image. */ /* Jump to the boot image. */
reinterpret_cast<void (*)()>(secmon::MemoryRegionPhysicalIramBootCodeImage.GetAddress())(); reinterpret_cast<void (*)()>(secmon::MemoryRegionPhysicalIramBootCodeImage.GetAddress())();

View File

@@ -0,0 +1,141 @@
#---------------------------------------------------------------------------------
# Define the atmosphere board and cpu
#---------------------------------------------------------------------------------
export ATMOSPHERE_BOARD := nx-hac-001
export ATMOSPHERE_CPU := arm-cortex-a57
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(__RECURSIVE__),1)
#---------------------------------------------------------------------------------
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
BINFILES :=
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES))))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I.
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
export TOPDIR := $(CURRENT_DIRECTORY)
OUTPUT_BASE := $(TOPDIR)/$(notdir $(TOPDIR))
#---------------------------------------------------------------------------------
ATMOSPHERE_BUILD_CONFIGS :=
all: release
define ATMOSPHERE_ADD_TARGET
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
$(strip $1): check_libexo_$(strip $1) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1)
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(OUTPUT_BASE)$(strip $2) $(3) \
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
LIBEXOSPHERE_NAME=exosphere$(strip $2) \
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
-f $$(THIS_MAKEFILE)
check_libexo_$(strip $1):
@$$(MAKE) --no-print-directory -C $$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere $$(ATMOSPHERE_ARCH_NAME)-$(strip $1)
clean-$(strip $1):
@echo clean $(strip $1) ...
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).elf
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, release, , \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug, \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_DEBUGGING" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit, \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_AUDITING" \
))
$(ATMOSPHERE_BUILD_DIR)/%:
@[ -d $@ ] || mkdir -p $@
#---------------------------------------------------------------------------------
clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
$(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/lib$(LIBEXOSPHERE_NAME).a
%.elf:
@echo linking $(notdir $@)
$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
diskio.o ff.o: CFLAGS += -Wno-error
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h: %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@@ -0,0 +1,227 @@
OUTPUT_ARCH(aarch64)
ENTRY(_start)
MEMORY
{
NULL : ORIGIN = 0, LENGTH = 4K
mariko_tzram : ORIGIN = 0x1F00D0000, LENGTH = 128K
}
SECTIONS
{
/* =========== CODE section =========== */
PROVIDE(__start__ = ORIGIN(mariko_tzram));
. = __start__;
__code_start = . ;
.crt0 :
{
KEEP (*(.crt0 .crt0.*))
KEEP (fatal_crt0_cpp.o(.text*))
*(.crt0.rodata*)
fatal_crt0_cpp.o(.rodata*)
*(.crt0.data*)
fatal_crt0_cpp.o(.data*)
. = ALIGN(8);
} >mariko_tzram
.preinit_array ALIGN(8) :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
} >mariko_tzram
.init_array ALIGN(8) :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
} >mariko_tzram
.fini_array ALIGN(8) :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
} >mariko_tzram
.ctors ALIGN(8) :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >mariko_tzram
.dtors ALIGN(8) :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >mariko_tzram
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
. = ALIGN(8);
} >mariko_tzram
.init :
{
KEEP( *(.init) )
. = ALIGN(8);
} >mariko_tzram
.plt :
{
*(.plt)
*(.iplt)
. = ALIGN(8);
} >mariko_tzram
.fini :
{
KEEP( *(.fini) )
. = ALIGN(8);
} >mariko_tzram
/* =========== RODATA section =========== */
. = ALIGN(8);
__rodata_start = . ;
.rodata :
{
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(8);
} >mariko_tzram
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >mariko_tzram
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >mariko_tzram
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >mariko_tzram
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >mariko_tzram
.hash : { *(.hash) } >mariko_tzram
/* =========== DATA section =========== */
. = ALIGN(8);
__data_start = . ;
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >mariko_tzram
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >mariko_tzram
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >mariko_tzram
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >mariko_tzram
.preinit_array ALIGN(8) :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
} >mariko_tzram
.init_array ALIGN(8) :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
} >mariko_tzram
.fini_array ALIGN(8) :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
} >mariko_tzram
.ctors ALIGN(8) :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >mariko_tzram
.dtors ALIGN(8) :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >mariko_tzram
__got_start__ = .;
.got : { *(.got) *(.igot) } >mariko_tzram
.got.plt : { *(.got.plt) *(.igot.plt) } >mariko_tzram
__got_end__ = .;
.data ALIGN(8) :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
} >mariko_tzram
__bss_start__ = .;
.bss ALIGN(8) :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(16);
} >mariko_tzram
__bss_end__ = .;
__end__ = ABSOLUTE(.) ;
/* ==================
==== Metadata ====
================== */
/* Discard sections that difficult post-processing */
/DISCARD/ : { *(.group .comment .note .interp) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
}

View File

@@ -0,0 +1,7 @@
%rename link old_link
*link:
%(old_link) -T %:getenv(TOPDIR /mariko_fatal.ld) --gc-sections --nmagic -nostdlib -nostartfiles
*startfile:
crti%O%s crtbegin%O%s

View File

@@ -0,0 +1,31 @@
/*
* 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 <exosphere.hpp>
namespace ams::diag {
void AbortImpl() {
AMS_SECMON_LOG("AbortImpl was called\n");
AMS_LOG_FLUSH();
reg::Write(0x4, 0xAAAAAAAA);
/* TODO: Reboot */
AMS_INFINITE_LOOP();
}
#include <exosphere/diag/diag_detailed_assertion_impl.inc>
}

View File

@@ -0,0 +1,38 @@
/*
* 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/>.
*/
.section .crt0.text.start, "ax", %progbits
.align 6
.global _start
_start:
/* Set the stack pointer to a temporary location. */
ldr x20, =0x1F00FC000
mov sp, x20
/* Save any arguments we may have. */
stp x0, x1, [sp, #-16]!
/* Initialize all memory to expected state. */
ldr x0, =__bss_start__
ldr x1, =__bss_end__
bl _ZN3ams6secmon5fatal10InitializeEmm
/* Restore any arguments we may have. */
ldp x0, x1, [sp], #16
/* Jump to the fatal program. */
ldr x16, =_ZN3ams6secmon5fatal4MainEv
br x16

View File

@@ -0,0 +1,30 @@
/*
* 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 <exosphere.hpp>
extern "C" void __libc_init_array();
namespace ams::secmon::fatal {
void Initialize(uintptr_t bss_start, size_t bss_end) {
/* Clear bss. */
std::memset(reinterpret_cast<void *>(bss_start), 0, bss_end - bss_start);
/* Call init array. */
__libc_init_array();
}
}

View File

@@ -0,0 +1,352 @@
/*
* 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 <exosphere.hpp>
namespace ams::secmon::fatal {
namespace {
/* Definitions. */
constexpr size_t PageDirectorySize = mmu::PageSize;
constexpr size_t PageTableSize = mmu::PageSize;
static_assert(PageDirectorySize == mmu::PageSize);
using DeviceVirtualAddress = u64;
constexpr size_t AsidCount = 0x80;
constexpr size_t PhysicalAddressBits = 34;
constexpr size_t PhysicalAddressMask = (1ul << PhysicalAddressBits) - 1ul;
constexpr size_t DeviceVirtualAddressBits = 34;
constexpr size_t DeviceVirtualAddressMask = (1ul << DeviceVirtualAddressBits) - 1ul;
constexpr size_t DevicePageBits = 12;
constexpr size_t DevicePageSize = (1ul << DevicePageBits);
static_assert(DevicePageSize == mmu::PageSize);
constexpr size_t DeviceLargePageBits = 22;
constexpr size_t DeviceLargePageSize = (1ul << DeviceLargePageBits);
static_assert(DeviceLargePageSize % DevicePageSize == 0);
constexpr size_t DeviceRegionBits = 32;
constexpr size_t DeviceRegionSize = (1ul << DeviceRegionBits);
static_assert(DeviceRegionSize % DeviceLargePageSize == 0);
constexpr const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
constexpr size_t TableCount = (1ul << DeviceVirtualAddressBits) / DeviceRegionSize;
consteval u32 EncodeAsidRegisterValue(u8 asid) {
u32 value = 0x80000000u;
for (size_t t = 0; t < TableCount; t++) {
value |= (asid << (BITSIZEOF(u8) * t));
}
return value;
}
constexpr u8 SdmmcAsid = 1;
constexpr u8 DcAsid = 2;
constexpr u32 SdmmcAsidRegisterValue = EncodeAsidRegisterValue(SdmmcAsid);
constexpr u32 DcAsidRegisterValue = EncodeAsidRegisterValue(DcAsid);
constexpr dd::PhysicalAddress DcL0PageTablePhysical = MemoryRegionPhysicalDramDcL0DevicePageTable.GetAddress();
constexpr dd::PhysicalAddress SdmmcL0PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L0DevicePageTable.GetAddress();
constexpr dd::PhysicalAddress SdmmcL1PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L1DevicePageTable.GetAddress();
/* Types. */
class EntryBase {
protected:
enum Bit : u32 {
Bit_Table = 28,
Bit_NonSecure = 29,
Bit_Writeable = 30,
Bit_Readable = 31,
};
private:
u32 value;
protected:
constexpr ALWAYS_INLINE u32 SelectBit(Bit n) const {
return (this->value & (1u << n));
}
constexpr ALWAYS_INLINE bool GetBit(Bit n) const {
return this->SelectBit(n) != 0;
}
static constexpr ALWAYS_INLINE u32 EncodeBit(Bit n, bool en) {
return en ? (1u << n) : 0;
}
static constexpr ALWAYS_INLINE u32 EncodeValue(bool r, bool w, bool ns, dd::PhysicalAddress addr, bool t) {
return EncodeBit(Bit_Readable, r) | EncodeBit(Bit_Writeable, w) | EncodeBit(Bit_NonSecure, ns) | EncodeBit(Bit_Table, t) | static_cast<u32>(addr >> DevicePageBits);
}
ALWAYS_INLINE void SetValue(u32 v) {
/* Prevent re-ordering around entry modifications. */
__asm__ __volatile__("" ::: "memory");
this->value = v;
__asm__ __volatile__("" ::: "memory");
}
public:
static constexpr ALWAYS_INLINE u32 EncodePtbDataValue(dd::PhysicalAddress addr) {
return EncodeValue(true, true, true, addr, false);
}
public:
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBit(Bit_NonSecure); }
constexpr ALWAYS_INLINE bool IsWriteable() const { return this->GetBit(Bit_Writeable); }
constexpr ALWAYS_INLINE bool IsReadable() const { return this->GetBit(Bit_Readable); }
constexpr ALWAYS_INLINE bool IsValid() const { return this->IsWriteable() || this->IsReadable(); }
constexpr ALWAYS_INLINE u32 GetAttributes() const { return this->SelectBit(Bit_NonSecure) | this->SelectBit(Bit_Writeable) | this->SelectBit(Bit_Readable); }
constexpr ALWAYS_INLINE dd::PhysicalAddress GetPhysicalAddress() const { return (static_cast<u64>(this->value) << DevicePageBits) & PhysicalAddressMask; }
ALWAYS_INLINE void Invalidate() { this->SetValue(0); }
};
class PageDirectoryEntry : public EntryBase {
public:
constexpr ALWAYS_INLINE bool IsTable() const { return this->GetBit(Bit_Table); }
ALWAYS_INLINE void SetTable(bool r, bool w, bool ns, dd::PhysicalAddress addr) {
AMS_ASSERT(util::IsAligned(addr, DevicePageSize));
this->SetValue(EncodeValue(r, w, ns, addr, true));
}
ALWAYS_INLINE void SetLargePage(bool r, bool w, bool ns, dd::PhysicalAddress addr) {
AMS_ASSERT(util::IsAligned(addr, DeviceLargePageSize));
this->SetValue(EncodeValue(r, w, ns, addr, false));
}
};
class PageTableEntry : public EntryBase {
public:
ALWAYS_INLINE void SetPage(bool r, bool w, bool ns, dd::PhysicalAddress addr) {
AMS_ASSERT(util::IsAligned(addr, DevicePageSize));
this->SetValue(EncodeValue(r, w, ns, addr, true));
}
};
/* Memory controller access functionality. */
void WriteMcRegister(size_t offset, u32 value) {
reg::Write(MC + offset, value);
}
u32 ReadMcRegister(size_t offset) {
return reg::Read(MC + offset);
}
/* Memory controller utilities. */
void SmmuSynchronizationBarrier() {
ReadMcRegister(MC_SMMU_CONFIG);
}
void InvalidatePtc() {
WriteMcRegister(MC_SMMU_PTC_FLUSH_0, 0);
}
void InvalidatePtc(dd::PhysicalAddress address) {
WriteMcRegister(MC_SMMU_PTC_FLUSH_1, (static_cast<u64>(address) >> 32));
WriteMcRegister(MC_SMMU_PTC_FLUSH_0, (address & 0xFFFFFFF0u) | 1u);
}
enum TlbFlushVaMatch : u32 {
TlbFlushVaMatch_All = 0,
TlbFlushVaMatch_Section = 2,
TlbFlushVaMatch_Group = 3,
};
static constexpr ALWAYS_INLINE u32 EncodeTlbFlushValue(bool match_asid, u8 asid, dd::PhysicalAddress address, TlbFlushVaMatch match) {
return ((match_asid ? 1u : 0u) << 31) | ((asid & 0x7F) << 24) | (((address & 0xFFC00000u) >> DevicePageBits)) | (match);
}
void InvalidateTlb() {
return WriteMcRegister(MC_SMMU_TLB_FLUSH, EncodeTlbFlushValue(false, 0, 0, TlbFlushVaMatch_All));
}
void InvalidateTlb(u8 asid) {
return WriteMcRegister(MC_SMMU_TLB_FLUSH, EncodeTlbFlushValue(true, asid, 0, TlbFlushVaMatch_All));
}
void InvalidateTlbSection(u8 asid, dd::PhysicalAddress address) {
return WriteMcRegister(MC_SMMU_TLB_FLUSH, EncodeTlbFlushValue(true, asid, address, TlbFlushVaMatch_Section));
}
void SetTable(u8 asid, dd::PhysicalAddress address) {
/* Write the table address. */
{
WriteMcRegister(MC_SMMU_PTB_ASID, asid);
WriteMcRegister(MC_SMMU_PTB_DATA, EntryBase::EncodePtbDataValue(address));
SmmuSynchronizationBarrier();
}
/* Ensure consistency. */
InvalidatePtc();
InvalidateTlb(asid);
SmmuSynchronizationBarrier();
}
void MapImpl(dd::PhysicalAddress phys_addr, size_t size, DeviceVirtualAddress address, u8 asid, void *l0_table, dd::PhysicalAddress l0_phys, void *l1_table, dd::PhysicalAddress l1_phys) {
/* Validate L0. */
AMS_ABORT_UNLESS(l0_table != nullptr);
AMS_ABORT_UNLESS(l0_phys != 0);
/* Cache permissions. */
const bool read = true;
const bool write = true;
/* Walk the directory. */
u64 remaining = size;
while (remaining > 0) {
const size_t l1_index = (address % DeviceRegionSize) / DeviceLargePageSize;
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
/* Get and validate l1. */
PageDirectoryEntry *l1 = static_cast<PageDirectoryEntry *>(l0_table);
AMS_ASSERT(l1 != nullptr);
/* Setup an l1 table/entry, if needed. */
if (!l1[l1_index].IsTable()) {
/* Check that an entry doesn't already exist. */
AMS_ASSERT(!l1[l1_index].IsValid());
/* If we can make an l1 entry, do so. */
if (l2_index == 0 && util::IsAligned(phys_addr, DeviceLargePageSize) && remaining >= DeviceLargePageSize) {
/* Set the large page. */
l1[l1_index].SetLargePage(read, write, true, phys_addr);
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
/* Synchronize. */
InvalidatePtc(l0_phys + l1_index * sizeof(PageDirectoryEntry));
InvalidateTlbSection(asid, address);
SmmuSynchronizationBarrier();
/* Advance. */
phys_addr += DeviceLargePageSize;
address += DeviceLargePageSize;
remaining -= DeviceLargePageSize;
continue;
} else {
/* Make an l1 table. */
AMS_ABORT_UNLESS(l1_table != nullptr);
AMS_ABORT_UNLESS(l1_phys != 0);
/* Clear the l1 table. */
std::memset(l1_table, 0, mmu::PageSize);
hw::FlushDataCache(l1_table, mmu::PageSize);
/* Set the l1 table. */
l1[l1_index].SetTable(true, true, true, l1_phys);
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
/* Synchronize. */
InvalidatePtc(l0_phys + l1_index * sizeof(PageDirectoryEntry));
InvalidateTlbSection(asid, address);
SmmuSynchronizationBarrier();
}
}
/* If we get to this point, l1 must be a table. */
AMS_ASSERT(l1[l1_index].IsTable());
AMS_ABORT_UNLESS(l1_table != nullptr);
AMS_ABORT_UNLESS(l1_phys != 0);
/* Map l2 entries. */
{
PageTableEntry *l2 = static_cast<PageTableEntry *>(l1_table);
const size_t remaining_in_entry = (PageTableSize / sizeof(PageTableEntry)) - l2_index;
const size_t map_count = std::min<size_t>(remaining_in_entry, remaining / DevicePageSize);
/* Set the entries. */
for (size_t i = 0; i < map_count; ++i) {
AMS_ASSERT(!l2[l2_index + i].IsValid());
l2[l2_index + i].SetPage(read, write, true, phys_addr + DevicePageSize * i);
}
hw::FlushDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry));
/* Invalidate the page table cache. */
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
InvalidatePtc(l1_phys + i * sizeof(PageTableEntry));
}
/* Synchronize. */
InvalidateTlbSection(asid, address);
SmmuSynchronizationBarrier();
/* Advance. */
phys_addr += map_count * DevicePageSize;
address += map_count * DevicePageSize;
remaining -= map_count * DevicePageSize;
}
}
}
}
void InitializeDevicePageTableForSdmmc1() {
/* Configure sdmmc to use our new page table. */
WriteMcRegister(MC_SMMU_SDMMC1A_ASID, SdmmcAsidRegisterValue);
SmmuSynchronizationBarrier();
/* Ensure consistency. */
InvalidatePtc();
InvalidateTlb();
SmmuSynchronizationBarrier();
/* Clear the L0 Page Table. */
std::memset(MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>(), 0, mmu::PageSize);
hw::FlushDataCache(MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>(), mmu::PageSize);
/* Set the page table for the sdmmc asid. */
SetTable(SdmmcAsid, SdmmcL0PageTablePhysical);
/* Map the appropriate region into the asid. */
MapImpl(MemoryRegionPhysicalDramSdmmcMappedData.GetAddress(), MemoryRegionPhysicalDramSdmmcMappedData.GetSize(), MemoryRegionVirtualDramSdmmcMappedData.GetAddress(),
SdmmcAsid,
MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>(), SdmmcL0PageTablePhysical,
MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), SdmmcL1PageTablePhysical);
}
void InitializeDevicePageTableForDc() {
/* Configure dc to use our new page table. */
WriteMcRegister(MC_SMMU_DC_ASID, DcAsidRegisterValue);
SmmuSynchronizationBarrier();
/* Ensure consistency. */
InvalidatePtc();
InvalidateTlb();
SmmuSynchronizationBarrier();
/* Clear the L0 Page Table. */
std::memset(MemoryRegionVirtualDramDcL0DevicePageTable.GetPointer<void>(), 0, mmu::PageSize);
hw::FlushDataCache(MemoryRegionVirtualDramDcL0DevicePageTable.GetPointer<void>(), mmu::PageSize);
/* Set the page table for the dc asid. */
SetTable(DcAsid, DcL0PageTablePhysical);
/* Map the appropriate region into the asid. */
static_assert(util::IsAligned(MemoryRegionDramDcFramebuffer.GetAddress(), DeviceLargePageSize));
static_assert(util::IsAligned(MemoryRegionDramDcFramebuffer.GetSize(), DeviceLargePageSize));
MapImpl(MemoryRegionDramDcFramebuffer.GetAddress(), MemoryRegionDramDcFramebuffer.GetSize(), MemoryRegionDramDcFramebuffer.GetAddress(),
DcAsid,
MemoryRegionVirtualDramDcL0DevicePageTable.GetPointer<void>(), DcL0PageTablePhysical,
nullptr, 0);
}
}

View File

@@ -0,0 +1,24 @@
/*
* 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 <exosphere.hpp>
namespace ams::secmon::fatal {
void InitializeDevicePageTableForSdmmc1();
void InitializeDevicePageTableForDc();
}

View File

@@ -0,0 +1,602 @@
/*
* 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 <exosphere.hpp>
#include "fatal_device_page_table.hpp"
#include "fatal_registers_di.hpp"
#include "fatal_display.hpp"
#include "fatal_print.hpp"
namespace ams::secmon::fatal {
namespace {
#include "fatal_display_config.inc"
}
namespace {
/* Helpful defines. */
constexpr int DsiWaitForCommandMilliSecondsMax = 250;
constexpr int DsiWaitForCommandCompletionMilliSeconds = 5;
constexpr int DsiWaitForHostControlMilliSecondsMax = 150;
constexpr inline int I2cAddressMax77620Pmic = 0x3C;
constexpr size_t GPIO_PORT3_CNF_0 = 0x200;
constexpr size_t GPIO_PORT3_OE_0 = 0x210;
constexpr size_t GPIO_PORT3_OUT_0 = 0x220;
constexpr size_t GPIO_PORT6_CNF_1 = 0x504;
constexpr size_t GPIO_PORT6_OE_1 = 0x514;
constexpr size_t GPIO_PORT6_OUT_1 = 0x524;
/* Globals. */
constexpr inline const uintptr_t PMC = secmon::MemoryRegionVirtualDevicePmc .GetAddress();
constexpr inline const uintptr_t g_disp1_regs = secmon::MemoryRegionVirtualDeviceDisp1 .GetAddress();
constexpr inline const uintptr_t g_dsi_regs = secmon::MemoryRegionVirtualDeviceDsi .GetAddress();
constexpr inline const uintptr_t g_clk_rst_regs = secmon::MemoryRegionVirtualDeviceClkRst .GetAddress();
constexpr inline const uintptr_t g_gpio_regs = secmon::MemoryRegionVirtualDeviceGpio .GetAddress();
constexpr inline const uintptr_t g_apb_misc_regs = secmon::MemoryRegionVirtualDeviceApbMisc.GetAddress();
constexpr inline const uintptr_t g_mipi_cal_regs = secmon::MemoryRegionVirtualDeviceMipiCal.GetAddress();
constinit u32 *g_frame_buffer = nullptr;
inline void DoRegisterWrites(uintptr_t base_address, const RegisterWrite *reg_writes, size_t num_writes) {
for (size_t i = 0; i < num_writes; i++) {
reg::Write(base_address + reg_writes[i].offset, reg_writes[i].value);
}
}
inline void DoSocDependentRegisterWrites(uintptr_t base_address, const RegisterWrite *reg_writes_erista, size_t num_writes_erista, const RegisterWrite *reg_writes_mariko, size_t num_writes_mariko) {
switch (GetSocType()) {
case fuse::SocType_Erista: DoRegisterWrites(base_address, reg_writes_erista, num_writes_erista); break;
case fuse::SocType_Mariko: DoRegisterWrites(base_address, reg_writes_mariko, num_writes_mariko); break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
inline void DoSleepOrRegisterWrites(uintptr_t base_address, const SleepOrRegisterWrite *reg_writes, size_t num_writes) {
for (size_t i = 0; i < num_writes; i++) {
switch (reg_writes[i].kind) {
case SleepOrRegisterWriteKind_Write:
reg::Write(base_address + sizeof(u32) * reg_writes[i].offset, reg_writes[i].value);
break;
case SleepOrRegisterWriteKind_Sleep:
util::WaitMicroSeconds(reg_writes[i].offset * UINT64_C(1000));
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}
void WaitDsiTrigger() {
const u32 timeout = util::GetMicroSeconds() + (DsiWaitForCommandMilliSecondsMax * 1000u);
while (true) {
if (util::GetMicroSeconds() >= timeout) {
break;
}
if (reg::Read(g_dsi_regs + sizeof(u32) * DSI_TRIGGER) == 0) {
break;
}
}
util::WaitMicroSeconds(DsiWaitForCommandCompletionMilliSeconds * 1000u);
}
void WaitDsiHostControl() {
const u32 timeout = util::GetMicroSeconds() + (DsiWaitForHostControlMilliSecondsMax * 1000u);
while (true) {
if (util::GetMicroSeconds() >= timeout) {
break;
}
if ((reg::Read(g_dsi_regs + sizeof(u32) * DSI_HOST_CONTROL) & DSI_HOST_CONTROL_IMM_BTA) == 0) {
break;
}
}
}
void EnableBacklightForVendor2050ForAula(int brightness) {
/* Enable FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_ENABLE, 2);
/* Configure DSI_LINE_TYPE as FOUR */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 9);
/* Set and wait for FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS, 2);
while ((reg::Read(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS) & 2) != 0) { /* ... */ }
/* Configure display brightness. */
const u32 brightness_val = ((0x7FF * brightness) / 100);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x339);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, (brightness_val & 0x700) | ((brightness_val & 0xFF) << 16) | 0x51);
/* Set and wait for FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS, 2);
while ((reg::Read(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS) & 2) != 0) { /* ... */ }
/* Set client sync point block reset. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_INCR_SYNCPT_CNTRL, 1);
util::WaitMicroSeconds(300'000ul);
/* Clear client sync point block resest. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_INCR_SYNCPT_CNTRL, 0);
util::WaitMicroSeconds(300'000ul);
/* Clear DSI_LINE_TYPE config. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 0);
/* Disable FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_ENABLE, 0);
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS, 2);
}
void EnableBacklightForGeneric(int brightness) {
AMS_UNUSED(brightness);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x1);
}
#define DO_REGISTER_WRITES(base_address, writes) DoRegisterWrites(base_address, writes, util::size(writes))
#define DO_SOC_DEPENDENT_REGISTER_WRITES(base_address, writes) DoSocDependentRegisterWrites(base_address, writes##Erista, util::size(writes##Erista), writes##Mariko, util::size(writes##Mariko))
#define DO_SLEEP_OR_REGISTER_WRITES(base_address, writes) DoSleepOrRegisterWrites(base_address, writes, util::size(writes))
void InitializeFrameBuffer() {
if (g_frame_buffer != nullptr) {
std::memset(g_frame_buffer, 0, FrameBufferSize);
hw::FlushDataCache(g_frame_buffer, FrameBufferSize);
} else {
/* Clear the frame buffer. */
g_frame_buffer = secmon::MemoryRegionDramDcFramebuffer.GetPointer<u32>();
std::memset(g_frame_buffer, 0, FrameBufferSize);
hw::FlushDataCache(g_frame_buffer, FrameBufferSize);
/* Attach the frame buffer to DC. */
InitializeDevicePageTableForDc();
}
}
[[maybe_unused]] void FinalizeFrameBuffer() {
/* We don't actually support finalizing the framebuffer, so do nothing here. */
}
constexpr const char *GetErrorDescription(u32 error_desc) {
switch (error_desc) {
case 0x100:
return "Instruction Abort";
case 0x101:
return "Data Abort";
case 0x102:
return "PC Misalignment";
case 0x103:
return "SP Misalignment";
case 0x104:
return "Trap";
case 0x106:
return "SError";
case 0x301:
return "Bad SVC";
case 0xF00:
return "Kernel Panic";
case 0xFFD:
return "Stack overflow";
case 0xFFE:
return "std::abort() called";
default:
return "Unknown";
}
}
void PrintSuggestedErrorFix(const ams::impl::FatalErrorContext *f_ctx) {
/* Try to recognize certain errors automatically, and suggest fixes for them. */
const char *suggestion = nullptr;
constexpr u64 ProgramIdAmsMitm = UINT64_C(0x010041544D530000);
constexpr u64 ProgramIdBoot = UINT64_C(0x0100000000000005);
if (f_ctx->error_desc == 0xFFE) {
if (f_ctx->program_id == ProgramIdAmsMitm) {
/* When a user has archive bits set improperly, attempting to create an automatic backup will fail */
/* to create the file path with error 0x202 */
if (f_ctx->gprs[0] == fs::ResultPathNotFound().GetValue()) {
/* When the archive bit error is occurring, it manifests as failure to create automatic backup. */
/* Thus, we can search the stack for the automatic backups path. */
const char * const automatic_backups_prefix = "automatic_backups/X" /* ..... */;
const int prefix_len = std::strlen(automatic_backups_prefix);
for (size_t i = 0; i + prefix_len < f_ctx->stack_dump_size; ++i) {
if (std::memcmp(&f_ctx->stack_dump[i], automatic_backups_prefix, prefix_len) == 0) {
suggestion = "The atmosphere directory may improperly have archive bits set.\n"
"Please try running an archive bit fixer tool (for example, the one in Hekate).\n";
break;
}
}
} else if (f_ctx->gprs[0] == fs::ResultExFatUnavailable().GetValue()) {
/* When a user installs non-exFAT firm but has an exFAT formatted SD card, this error will */
/* be returned on attempt to access the SD card. */
suggestion = "Your console has non-exFAT firmware installed, but your SD card\n"
"is formatted as exFAT. Format your SD card as FAT32, or manually\n"
"flash exFAT firmware to package2.\n";
}
} else if (f_ctx->program_id == ProgramIdBoot) {
/* 9.x -> 10.x updated the API for SvcQueryIoMapping. */
/* This can cause the kernel to reject incorrect-ABI calls by boot when a partial update is applied */
/* (older kernel in package2, for some reason). */
for (size_t i = 0; i < 8; ++i) {
if (f_ctx->gprs[i] == svc::ResultNotFound().GetValue()) {
suggestion = "A partial update may have been improperly performed.\n"
"To fix, try manually flashing latest package2 to MMC.\n"
"\n"
"For help doing this, seek support in the ReSwitched or\n"
"Nintendo Homebrew discord servers.\n";
break;
}
}
}
} else if (f_ctx->error_desc == 0xF00) { /* Kernel Panic */
suggestion = "Please contact SciresM#0524 on Discord, or create an issue on the Atmosphere\n"
"GitHub issue tracker. Thank you very much for helping to test mesosphere.\n";
}
/* If we found a suggestion, print it. */
if (suggestion != nullptr) {
Print("%s", suggestion);
}
}
void FinalizeDisplay() {
/* TODO: What other configuration is needed, if any? */
/* Configure LCD pinmux tristate + passthrough. */
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_INT, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_PWM, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_RST, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
if (fuse::GetHardwareType() == fuse::HardwareType_Aula) {
/* Configure LCD backlight. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x4);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x4);
} else {
/* Configure LCD power, VDD. */
reg::SetBits(g_gpio_regs + GPIO_PORT3_CNF_0, 0x3);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OE_0, 0x3);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x1);
util::WaitMicroSeconds(10'000ul);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x2);
util::WaitMicroSeconds(10'000ul);
/* Configure LCD backlight. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x7);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x7);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x2);
}
/* Disable the LCD backlight. */
if (GetLcdVendor() == 0x2050) {
/* TODO: We're not sure display is alive. How to manage this? */
/* This is probably incorrect backlight disable for hw-type 5. */
reg::ClearBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x1);
} else {
reg::ClearBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x1);
}
/* Disable backlight RST/Voltage. */
reg::ClearBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x4);
if (GetLcdVendor() == 0x2050) {
util::WaitMicroSeconds(30'000ul);
} else {
util::WaitMicroSeconds(10'000ul);
reg::ClearBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x2);
util::WaitMicroSeconds(10'000ul);
reg::ClearBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x1);
util::WaitMicroSeconds(10'000ul);
}
/* Cut clock to DSI. */
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_H_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_H_SET_SET_MIPI_CAL_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_H_SET_SET_DSI_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_H_CLR, CLK_RST_REG_BITS_ENUM(CLK_ENB_H_CLR_CLR_CLK_ENB_MIPI_CAL, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_H_CLR_CLR_CLK_ENB_DSI, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_L_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_HOST1X_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_DISP1_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_L_CLR, CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLR_CLR_CLK_ENB_HOST1X, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLR_CLR_CLK_ENB_DISP1, ENABLE));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_PAD_CONTROL_0, (DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF)));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_POWER_CONTROL, 0);
}
}
void InitializeDisplay() {
/* Ensure that the display is finalized. */
FinalizeDisplay();
/* Setup the framebuffer. */
InitializeFrameBuffer();
/* Get the hardware type. */
const auto hw_type = fuse::GetHardwareType();
/* Turn on DSI/voltage rail. */
{
if (GetSocType() == fuse::SocType_Mariko) {
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, 0x18, 0x3A);
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, 0x18, 0x3A);
}
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, 0x23, 0xD0);
}
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_H_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_H_CLR_CLR_MIPI_CAL_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_H_CLR_CLR_DSI_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_H_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_H_SET_SET_CLK_ENB_MIPI_CAL, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_H_SET_SET_CLK_ENB_DSI, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_L_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_L_CLR_CLR_HOST1X_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_L_CLR_CLR_DISP1_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_L_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_L_SET_SET_CLK_ENB_HOST1X, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_L_SET_SET_CLK_ENB_DISP1, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_X_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_X_SET_SET_CLK_ENB_UART_FST_MIPI_CAL, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_UART_FST_MIPI_CAL_UART_FST_MIPI_CAL_CLK_DIVISOR, 10),
CLK_RST_REG_BITS_ENUM (CLK_SOURCE_UART_FST_MIPI_CAL_UART_FST_MIPI_CAL_CLK_SRC, PLLP_OUT3));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_W_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_W_SET_SET_CLK_ENB_DSIA_LP, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_DSIA_LP_DSIA_LP_CLK_DIVISOR, 10),
CLK_RST_REG_BITS_ENUM (CLK_SOURCE_DSIA_LP_DSIA_LP_CLK_SRC, PLLP_OUT0));
/* Set IO_DPD_REQ to DPD_OFF. */
reg::ReadWrite(PMC + APBDEV_PMC_IO_DPD_REQ, PMC_REG_BITS_ENUM(IO_DPD_REQ_CODE, DPD_OFF));
reg::ReadWrite(PMC + APBDEV_PMC_IO_DPD2_REQ, PMC_REG_BITS_ENUM(IO_DPD2_REQ_CODE, DPD_OFF));
/* Configure LCD pinmux tristate + passthrough. */
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_INT, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_PWM, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_RST, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
if (hw_type == fuse::HardwareType_Aula) {
/* Configure LCD backlight. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x4);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x4);
} else {
/* Configure LCD power, VDD. */
reg::SetBits(g_gpio_regs + GPIO_PORT3_CNF_0, 0x3);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OE_0, 0x3);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x1);
util::WaitMicroSeconds(10'000ul);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x2);
util::WaitMicroSeconds(10'000ul);
/* Configure LCD backlight. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x7);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x7);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x2);
}
/* Configure display interface and display. */
reg::Write(g_mipi_cal_regs + MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0);
if (GetSocType() == fuse::SocType_Mariko) {
reg::Write(g_mipi_cal_regs + MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0);
reg::Write(g_apb_misc_regs + APB_MISC_GP_DSI_PAD_CONTROL, 0);
}
/* Execute configs. */
DO_SOC_DEPENDENT_REGISTER_WRITES(g_clk_rst_regs, DisplayConfigPlld01);
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigDc01);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init01);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init02);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init03);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init04);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init05);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsiPhyTiming);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init06);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsiPhyTiming);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init07);
util::WaitMicroSeconds(10'000ul);
/* Enable backlight reset. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x4);
util::WaitMicroSeconds(60'000ul);
if (hw_type == fuse::HardwareType_Aula) {
reg::Write(g_dsi_regs + sizeof(u32) * DSI_BTA_TIMING, 0x40103);
} else {
reg::Write(g_dsi_regs + sizeof(u32) * DSI_BTA_TIMING, 0x50204);
}
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x337);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
WaitDsiTrigger();
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x406);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
WaitDsiTrigger();
reg::Write(g_dsi_regs + sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC);
WaitDsiHostControl();
util::WaitMicroSeconds(5'000ul);
/* Parse LCD vendor. */
{
u32 host_response[3];
for (size_t i = 0; i < util::size(host_response); i++) {
host_response[i] = reg::Read(g_dsi_regs + sizeof(u32) * DSI_RD_DATA);
}
/* The last word from host response is:
Bits 0-7: FAB
Bits 8-15: REV
Bits 16-23: Minor REV
*/
u32 lcd_vendor;
if ((host_response[2] & 0xFF) == 0x10) {
lcd_vendor = 0;
} else {
lcd_vendor = (host_response[2] >> 8) & 0xFF00;
}
lcd_vendor = (lcd_vendor & 0xFFFFFF00) | (host_response[2] & 0xFF);
AMS_ASSERT(lcd_vendor == GetLcdVendor());
}
/* LCD vendor specific configuration. */
switch (GetLcdVendor()) {
case 0x10: /* Japan Display Inc screens. */
DO_SLEEP_OR_REGISTER_WRITES(g_dsi_regs, DisplayConfigJdiSpecificInit01);
break;
case 0xF20: /* Innolux first revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(180'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x739);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x751548B1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x143209);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
case 0xF30: /* AUO first revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(180'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x739);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x711148B1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x143209);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
case 0x2050: /* Unknown (hardware type 5) screen. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(180'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0xA015);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x205315);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x339);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x51);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
case 0x1020: /* Innolux second revision screen. */
case 0x1030: /* AUO second revision screen. */
case 0x1040: /* Unknown second revision screen. */
default:
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(120'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
}
util::WaitMicroSeconds(20'000ul);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_clk_rst_regs, DisplayConfigPlld02);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init08);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsiPhyTiming);
DO_SLEEP_OR_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init09);
reg::Write(g_disp1_regs + sizeof(u32) * DC_DISP_DISP_CLOCK_CONTROL, SHIFT_CLK_DIVIDER(4));
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init10);
util::WaitMicroSeconds(10'000ul);
/* Configure MIPI CAL. */
DO_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal01);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal02);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init11);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal03);
DO_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal04);
if (GetSocType() == fuse::SocType_Mariko) {
/* On Mariko the above configurations are executed twice, for some reason. */
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal02);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init11);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal03);
DO_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal04);
}
util::WaitMicroSeconds(10'000ul);
/* Write DISP1, FrameBuffer config. */
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigDc02);
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigFrameBuffer);
if (GetLcdVendor() != 0x2050) {
util::WaitMicroSeconds(35'000ul);
}
}
void ShowDisplay(const ams::impl::FatalErrorContext *f_ctx, const Result save_result) {
/* Initialize the console. */
InitializeConsole(g_frame_buffer);
{
Print("%s\n", "A fatal error occurred when running Atmosph\xe8re.");
Print("Program ID: %016" PRIx64 "\n", f_ctx->program_id);
Print("Error Desc: %s (0x%x)\n", GetErrorDescription(f_ctx->error_desc), f_ctx->error_desc);
Print("\n");
if (R_SUCCEEDED(save_result)) {
Print("Report saved to /atmosphere/fatal_errors/report_%016" PRIx64 ".bin", f_ctx->report_identifier);
} else {
Print("Failed to save report to the SD card! (%08x)\n", save_result.GetValue());
}
PrintSuggestedErrorFix(f_ctx);
Print("\nPress POWER to reboot.\n");
}
/* Ensure the device will see consistent data. */
hw::FlushDataCache(g_frame_buffer, FrameBufferSize);
/* Enable backlight. */
constexpr auto DisplayBrightness = 100;
if (GetLcdVendor() == 0x2050) {
EnableBacklightForVendor2050ForAula(DisplayBrightness);
} else {
EnableBacklightForGeneric(DisplayBrightness);
}
}
}

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 <exosphere.hpp>
namespace ams::secmon::fatal {
constexpr inline size_t FrameBufferHeight = 768;
constexpr inline size_t FrameBufferWidth = 1280;
constexpr inline size_t FrameBufferSize = FrameBufferHeight * FrameBufferWidth * sizeof(u32);
void InitializeDisplay();
void ShowDisplay(const ams::impl::FatalErrorContext *f_ctx, const Result save_result);
}

View File

@@ -0,0 +1,682 @@
/*
* 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/>.
*/
struct RegisterWrite {
u32 offset;
u32 value;
};
enum SleepOrRegisterWriteKind : u16 {
SleepOrRegisterWriteKind_Write = 0,
SleepOrRegisterWriteKind_Sleep = 1,
};
struct SleepOrRegisterWrite {
SleepOrRegisterWriteKind kind;
u16 offset;
u32 value;
};
constexpr const RegisterWrite DisplayConfigPlld01Erista[] = {
{CLK_RST_CONTROLLER_CLK_SOURCE_DISP1, 0x40000000},
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4830A001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000020},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002D0AAA},
};
constexpr const RegisterWrite DisplayConfigPlld01Mariko[] = {
{CLK_RST_CONTROLLER_CLK_SOURCE_DISP1, 0x40000000},
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4830A001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000000},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002DFC00},
};
constexpr const SleepOrRegisterWrite DisplayConfigDc01[] = {
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_REG_ACT_CONTROL, 0x54},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_DISP_DC_MCCIF_FIFOCTRL, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_MEM_HIGH_PRIORITY, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE},
{SleepOrRegisterWriteKind_Write, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL},
{SleepOrRegisterWriteKind_Write, DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9}, // 9: SYNCPT
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{SleepOrRegisterWriteKind_Write, 0x4E4, 0},
{SleepOrRegisterWriteKind_Write, DC_COM_CRC_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}
};
constexpr const RegisterWrite DisplayConfigDsi01Init01[] = {
{sizeof(u32) * DSI_WR_DATA, 0x0},
{sizeof(u32) * DSI_INT_ENABLE, 0x0},
{sizeof(u32) * DSI_INT_STATUS, 0x0},
{sizeof(u32) * DSI_INT_MASK, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_0, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_1, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_2, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_3, 0x0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init02Erista[] = {
{sizeof(u32) * DSI_INIT_SEQ_DATA_15, 0x0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init02Mariko[] = {
{sizeof(u32) * DSI_INIT_SEQ_DATA_15_MARIKO, 0x0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init03[] = {
{sizeof(u32) * DSI_DCS_CMDS, 0},
{sizeof(u32) * DSI_PKT_SEQ_0_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_1_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_2_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_3_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_4_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_5_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_0_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_1_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_2_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_3_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_4_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_5_HI, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init04Erista[] = {
/* No register writes. */
};
constexpr const RegisterWrite DisplayConfigDsi01Init04Mariko[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
{sizeof(u32) * DSI_PAD_CONTROL_2, 0},
{sizeof(u32) * DSI_PAD_CONTROL_3, 0},
{sizeof(u32) * DSI_PAD_CONTROL_4, 0},
{sizeof(u32) * DSI_PAD_CONTROL_5_MARIKO, 0},
{sizeof(u32) * DSI_PAD_CONTROL_6_MARIKO, 0},
{sizeof(u32) * DSI_PAD_CONTROL_7_MARIKO, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init05[] = {
{sizeof(u32) * DSI_PAD_CONTROL_CD, 0},
{sizeof(u32) * DSI_SOL_DELAY, 0x18},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x1E0},
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_INIT_SEQ_CONTROL, 0},
{sizeof(u32) * DSI_PKT_LEN_0_1, 0},
{sizeof(u32) * DSI_PKT_LEN_2_3, 0},
{sizeof(u32) * DSI_PKT_LEN_4_5, 0},
{sizeof(u32) * DSI_PKT_LEN_6_7, 0},
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init06[] = {
{sizeof(u32) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(u32) * DSI_PHY_TIMING_2, 0x30109},
{sizeof(u32) * DSI_BTA_TIMING, 0x190A14},
{sizeof(u32) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{sizeof(u32) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(u32) * DSI_TO_TALLY, 0},
{sizeof(u32) * DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, 0},
{sizeof(u32) * DSI_POWER_CONTROL, 0},
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init07[] = {
{sizeof(u32) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(u32) * DSI_PHY_TIMING_2, 0x30118},
{sizeof(u32) * DSI_BTA_TIMING, 0x190A14},
{sizeof(u32) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{sizeof(u32) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(u32) * DSI_TO_TALLY, 0},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x40},
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_TX_CRC, 0},
{sizeof(u32) * DSI_INIT_SEQ_CONTROL, 0}
};
constexpr const RegisterWrite DisplayConfigDsiPhyTimingErista[] = {
{sizeof(u32) * DSI_PHY_TIMING_0, 0x6070601},
};
constexpr const RegisterWrite DisplayConfigDsiPhyTimingMariko[] = {
{sizeof(u32) * DSI_PHY_TIMING_0, 0x6070603},
};
constexpr const SleepOrRegisterWrite DisplayConfigJdiSpecificInit01[] = {
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x9483FFB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xBD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x1939},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAD8},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAEB},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAEBAAAA},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAAA},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAEB},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAEBAAAA},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAA},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x1BD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2739},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFD8},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2BD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xF39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFD8},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xBD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x6D915},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x1105},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Sleep, 180, 0},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2905},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
constexpr const RegisterWrite DisplayConfigPlld02Erista[] = {
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4810c001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000020},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002D0AAA},
};
constexpr const RegisterWrite DisplayConfigPlld02Mariko[] = {
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4810c001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000000},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002DFC00},
};
constexpr const RegisterWrite DisplayConfigDsi01Init08[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const SleepOrRegisterWrite DisplayConfigDsi01Init09[] = {
{SleepOrRegisterWriteKind_Write, DSI_PHY_TIMING_1, 0x40A0E05},
{SleepOrRegisterWriteKind_Write, DSI_PHY_TIMING_2, 0x30172},
{SleepOrRegisterWriteKind_Write, DSI_BTA_TIMING, 0x190A14},
{SleepOrRegisterWriteKind_Write, DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)},
{SleepOrRegisterWriteKind_Write, DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)},
{SleepOrRegisterWriteKind_Write, DSI_TO_TALLY, 0},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_0_LO, 0x40000208},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_2_LO, 0x40000308},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_4_LO, 0x40000308},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_1_LO, 0x40000308},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_3_LO, 0x3F3B2B08},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_3_HI, 0x2CC},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_5_LO, 0x3F3B2B08},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_5_HI, 0x2CC},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_0_1, 0xCE0000},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_2_3, 0x87001A2},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_4_5, 0x190},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_6_7, 0x190},
{SleepOrRegisterWriteKind_Write, DSI_HOST_CONTROL, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init10[] = {
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_CONTROL, 0},
{sizeof(u32) * DSI_SOL_DELAY, 6},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x1E0},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}
};
constexpr const RegisterWrite DisplayConfigDsi01Init11Erista[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
{sizeof(u32) * DSI_PAD_CONTROL_2, 0},
{sizeof(u32) * DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
{sizeof(u32) * DSI_PAD_CONTROL_4, 0}
};
constexpr const RegisterWrite DisplayConfigDsi01Init11Mariko[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
{sizeof(u32) * DSI_PAD_CONTROL_2, 0},
{sizeof(u32) * DSI_PAD_CONTROL_3, 0},
{sizeof(u32) * DSI_PAD_CONTROL_4, 0x77777},
{sizeof(u32) * DSI_PAD_CONTROL_5_MARIKO, 0x77777},
{sizeof(u32) * DSI_PAD_CONTROL_6_MARIKO, DSI_PAD_PREEMP_PD_CLK(0x1) | DSI_PAD_PREEMP_PU_CLK(0x1) | DSI_PAD_PREEMP_PD(0x01) | DSI_PAD_PREEMP_PU(0x1)},
{sizeof(u32) * DSI_PAD_CONTROL_7_MARIKO, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal01[] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 1},
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal02Erista[] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0x300},
};
constexpr const RegisterWrite DisplayConfigMipiCal02Mariko[] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal03Erista[] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal03Mariko[] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal04[] = {
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILD_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILE_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILF_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001},
};
constexpr const SleepOrRegisterWrite DisplayConfigDc02[] = {
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{SleepOrRegisterWriteKind_Write, 0x4E4, 0},
{SleepOrRegisterWriteKind_Write, DC_COM_CRC_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
/* Set Display timings */
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_TIMING_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_REF_TO_SYNC, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1.
{SleepOrRegisterWriteKind_Write, DC_DISP_SYNC_WIDTH, 0x10048},
{SleepOrRegisterWriteKind_Write, DC_DISP_BACK_PORCH, 0x90048},
{SleepOrRegisterWriteKind_Write, DC_DISP_ACTIVE, 0x50002D0},
{SleepOrRegisterWriteKind_Write, DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd.
/* End of Display timings */
{SleepOrRegisterWriteKind_Write, DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_ENABLE(1), 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_CLOCK_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX},
{SleepOrRegisterWriteKind_Write, DC_DISP_FRONT_PORCH, 0xA0088},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{SleepOrRegisterWriteKind_Write, DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0}
};
constexpr u32 DisplayConfigFrameBufferAddress = 0xC0000000;
constexpr const SleepOrRegisterWrite DisplayConfigFrameBuffer[] = {
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C.
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B.
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A.
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_POSITION, 0}, //(0,0)
{SleepOrRegisterWriteKind_Write, DC_WIN_H_INITIAL_DDA, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_V_INITIAL_DDA, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes.
{SleepOrRegisterWriteKind_Write, DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)},
{SleepOrRegisterWriteKind_Write, DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels.
{SleepOrRegisterWriteKind_Write, DC_WIN_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{SleepOrRegisterWriteKind_Write, DC_WIN_BUFFER_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WINBUF_SURFACE_KIND, 0}, //Regular surface.
{SleepOrRegisterWriteKind_Write, DC_WINBUF_START_ADDR, DisplayConfigFrameBufferAddress}, //Framebuffer address.
{SleepOrRegisterWriteKind_Write, DC_WINBUF_ADDR_H_OFFSET, 0},
{SleepOrRegisterWriteKind_Write, DC_WINBUF_ADDR_V_OFFSET, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, WIN_ENABLE}, //Enable window AD.
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display.
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update.
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request.
};
constexpr const RegisterWrite DisplayConfigDc01Fini01[] = {
{sizeof(u32) * DC_DISP_FRONT_PORCH, 0xA0088},
{sizeof(u32) * DC_CMD_INT_MASK, 0},
{sizeof(u32) * DC_CMD_STATE_ACCESS, 0},
{sizeof(u32) * DC_CMD_INT_ENABLE, 0},
{sizeof(u32) * DC_CMD_CONT_SYNCPT_VSYNC, 0},
{sizeof(u32) * DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(u32) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(u32) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
};
constexpr const RegisterWrite DisplayConfigDsi01Fini01[] = {
{sizeof(u32) * DSI_POWER_CONTROL, 0},
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Fini02[] = {
{sizeof(u32) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(u32) * DSI_PHY_TIMING_2, 0x30118},
{sizeof(u32) * DSI_BTA_TIMING, 0x190A14},
{sizeof(u32) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
{sizeof(u32) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(u32) * DSI_TO_TALLY, 0},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x40},
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_TX_CRC, 0},
{sizeof(u32) * DSI_INIT_SEQ_CONTROL, 0}
};
constexpr const SleepOrRegisterWrite DisplayConfigJdiSpecificFini01[] = {
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x9483FFB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2139},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x191919D5},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x4F0F41B1},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xF179A433},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2D81},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
constexpr const SleepOrRegisterWrite DisplayConfigAuoRev1SpecificFini01[] = {
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x9483FFB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2C39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x191919D5},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2C39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x191919D6},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x711148B1},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x71143209},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x114D31},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Sleep, 5, 0},
};

View File

@@ -0,0 +1,97 @@
/*
* 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 <exosphere.hpp>
#include "fatal_sdmmc.hpp"
#include "fatal_save_context.hpp"
#include "fatal_sound.hpp"
#include "fatal_display.hpp"
namespace ams::secmon::fatal {
namespace {
constexpr inline int I2cAddressMax77620Pmic = 0x3C;
ALWAYS_INLINE const ams::impl::FatalErrorContext *GetFatalErrorContext() {
return MemoryRegionVirtualTzramMarikoProgramFatalErrorContext.GetPointer<ams::impl::FatalErrorContext>();
}
}
void Main() {
/* Set library register addresses. */
actmon::SetRegisterAddress(MemoryRegionVirtualDeviceActivityMonitor.GetAddress());
clkrst::SetRegisterAddress(MemoryRegionVirtualDeviceClkRst.GetAddress());
flow::SetRegisterAddress(MemoryRegionVirtualDeviceFlowController.GetAddress());
fuse::SetRegisterAddress(MemoryRegionVirtualDeviceFuses.GetAddress());
gic::SetRegisterAddress(MemoryRegionVirtualDeviceGicDistributor.GetAddress(), MemoryRegionVirtualDeviceGicCpuInterface.GetAddress());
i2c::SetRegisterAddress(i2c::Port_1, MemoryRegionVirtualDeviceI2c1.GetAddress());
i2c::SetRegisterAddress(i2c::Port_5, MemoryRegionVirtualDeviceI2c5.GetAddress());
pinmux::SetRegisterAddress(MemoryRegionVirtualDeviceApbMisc.GetAddress(), MemoryRegionVirtualDeviceGpio.GetAddress());
pmc::SetRegisterAddress(MemoryRegionVirtualDevicePmc.GetAddress());
se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress(), MemoryRegionVirtualDeviceSecurityEngine2.GetAddress());
uart::SetRegisterAddress(MemoryRegionVirtualDeviceUart.GetAddress());
wdt::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
util::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
/* Ensure that the log library is initialized. */
log::Initialize();
AMS_SECMON_LOG("%s\n", "Fatal start.");
/* Save the fatal error context. */
const auto *f_ctx = GetFatalErrorContext();
Result result = SaveFatalErrorContext(f_ctx);
if (R_SUCCEEDED(result)) {
AMS_SECMON_LOG("Saved fatal error context to /atmosphere/fatal_reports/report_%016" PRIx64 ".bin!\n", f_ctx->report_identifier);
} else {
AMS_SECMON_LOG("Failed to save fatal error context: %08x\n", result.GetValue());
}
/* Ensure that i2c-1/i2c-5 are usable for communicating with the audio device/pmic. */
clkrst::EnableI2c1Clock();
clkrst::EnableI2c5Clock();
i2c::Initialize(i2c::Port_1);
i2c::Initialize(i2c::Port_5);
/* Shut down audio. */
{
StopSound();
}
/* Display the fatal error. */
{
AMS_SECMON_LOG("Showing Display, LCD Vendor = %04x\n", GetLcdVendor());
InitializeDisplay();
ShowDisplay(f_ctx, result);
}
/* Ensure we have nothing waiting to be logged. */
AMS_LOG_FLUSH();
/* Wait for power button to be pressed. */
while (!pmic::IsPowerButtonPressed()) {
util::WaitMicroSeconds(100);
}
/* Reboot. */
pmic::ShutdownSystem(true);
/* Wait for our reboot to complete. */
AMS_INFINITE_LOOP();
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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 <exosphere.hpp>
#include "fatal_display.hpp"
#include "fatal_print.hpp"
namespace ams::secmon::fatal {
namespace {
#include "fatal_font.inc"
constexpr inline const u32 TextColor = 0xFFA0A0A0;
constexpr inline const size_t ConsoleWidth = FrameBufferWidth / FontWidth;
constexpr inline const size_t ConsoleHeight = FrameBufferHeight / FontHeight;
constinit u32 *g_frame_buffer = nullptr;
constinit size_t g_col = 1;
constinit size_t g_row = 0;
void SetPixel(size_t x, size_t y, u32 color) {
g_frame_buffer[(FrameBufferWidth - x) * FrameBufferHeight + y] = color;
}
void PutCarriageReturn() {
g_col = 1;
}
void PutNewLine() {
g_col = 1;
++g_row;
/* TODO: Support scrolling? */
}
void PutCharImpl(const char c) {
/* Get the character data for the font. */
const u8 * cdata = FontData + c * (FontHeight * util::DivideUp(FontWidth, BITSIZEOF(u8)));
/* Determine where to start drawing. */
const size_t x = g_col * FontWidth;
const size_t y = g_row * FontHeight;
for (size_t cur_y = 0; cur_y < FontHeight; ++cur_y) {
size_t cur_x = 0;
int wbits = FontWidth;
while (wbits > 0) {
const auto bits = *(cdata++);
SetPixel(x + cur_x + 0, y + cur_y, FontDrawTable[(bits >> 4) & 0xF][0] & TextColor);
SetPixel(x + cur_x + 1, y + cur_y, FontDrawTable[(bits >> 4) & 0xF][1] & TextColor);
SetPixel(x + cur_x + 2, y + cur_y, FontDrawTable[(bits >> 4) & 0xF][2] & TextColor);
SetPixel(x + cur_x + 3, y + cur_y, FontDrawTable[(bits >> 4) & 0xF][3] & TextColor);
SetPixel(x + cur_x + 4, y + cur_y, FontDrawTable[(bits >> 0) & 0xF][0] & TextColor);
SetPixel(x + cur_x + 5, y + cur_y, FontDrawTable[(bits >> 0) & 0xF][1] & TextColor);
SetPixel(x + cur_x + 6, y + cur_y, FontDrawTable[(bits >> 0) & 0xF][2] & TextColor);
SetPixel(x + cur_x + 7, y + cur_y, FontDrawTable[(bits >> 0) & 0xF][3] & TextColor);
cur_x += BITSIZEOF(u8);
wbits -= BITSIZEOF(u8);
}
}
}
void PutChar(const char c) {
switch (c) {
case '\r':
PutCarriageReturn();
break;
case '\n':
PutNewLine();
break;
default:
PutCharImpl(c);
if ((++g_col) >= ConsoleWidth) {
PutNewLine();
}
}
}
}
void InitializeConsole(u32 *frame_buffer) {
/* Setup the console variables. */
g_frame_buffer = frame_buffer;
g_col = 1;
g_row = 0;
/* Clear the console. */
std::memset(g_frame_buffer, 0, FrameBufferSize);
}
void Print(const char *fmt, ...) {
/* Generate the string. */
char log_str[1_KB];
{
std::va_list vl;
va_start(vl, fmt);
util::TVSNPrintf(log_str, sizeof(log_str), fmt, vl);
va_end(vl);
}
/* Print each character. */
const size_t len = std::strlen(log_str);
for (size_t i = 0; i < len; ++i) {
PutChar(log_str[i]);
}
/* Flush the console. */
hw::FlushDataCache(g_frame_buffer, FrameBufferSize);
}
}

View File

@@ -0,0 +1,24 @@
/*
* 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 <exosphere.hpp>
namespace ams::secmon::fatal {
void InitializeConsole(u32 *frame_buffer);
void Print(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
}

View File

@@ -0,0 +1,352 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer
* 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 <exosphere.hpp>
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
#define SYNCPT_CNTRL_NO_STALL (1 << 8)
#define SYNCPT_CNTRL_SOFT_RESET (1 << 0)
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
#define SYNCPT_VSYNC_ENABLE (1 << 8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
#define DC_CMD_DISPLAY_COMMAND 0x32
#define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
#define DISP_CTRL_MODE_MASK (3 << 5)
#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
#define PW0_ENABLE (1 << 0)
#define PW1_ENABLE (1 << 2)
#define PW2_ENABLE (1 << 4)
#define PW3_ENABLE (1 << 6)
#define PW4_ENABLE (1 << 8)
#define PM0_ENABLE (1 << 16)
#define PM1_ENABLE (1 << 18)
#define DC_CMD_INT_STATUS 0x37
#define DC_CMD_INT_MASK 0x38
#define DC_CMD_INT_ENABLE 0x39
#define DC_CMD_STATE_ACCESS 0x40
#define READ_MUX (1 << 0)
#define WRITE_MUX (1 << 2)
#define DC_CMD_STATE_CONTROL 0x41
#define GENERAL_ACT_REQ (1 << 0)
#define WIN_A_ACT_REQ (1 << 1)
#define WIN_B_ACT_REQ (1 << 2)
#define WIN_C_ACT_REQ (1 << 3)
#define CURSOR_ACT_REQ (1 << 7)
#define GENERAL_UPDATE (1 << 8)
#define WIN_A_UPDATE (1 << 9)
#define WIN_B_UPDATE (1 << 10)
#define WIN_C_UPDATE (1 << 11)
#define CURSOR_UPDATE (1 << 15)
#define NC_HOST_TRIG (1 << 24)
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
#define WINDOW_A_SELECT (1 << 4)
#define WINDOW_B_SELECT (1 << 5)
#define WINDOW_C_SELECT (1 << 6)
#define DC_CMD_REG_ACT_CONTROL 0x043
#define DC_COM_CRC_CONTROL 0x300
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define DC_COM_DSC_TOP_CTL 0x33E
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE (1 << 29)
#define SOR1_TIMING_CYA (1 << 27)
#define SOR1_ENABLE (1 << 26)
#define SOR_ENABLE (1 << 25)
#define CURSOR_ENABLE (1 << 16)
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
#define DC_DISP_REF_TO_SYNC 0x406
#define DC_DISP_SYNC_WIDTH 0x407
#define DC_DISP_BACK_PORCH 0x408
#define DC_DISP_ACTIVE 0x409
#define DC_DISP_FRONT_PORCH 0x40A
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
#define DISP_DATA_FORMAT_DF2S (4 << 0)
#define DISP_DATA_FORMAT_DF3S (5 << 0)
#define DISP_DATA_FORMAT_DFSPI (6 << 0)
#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
#define DISP_ALIGNMENT_MSB (0 << 8)
#define DISP_ALIGNMENT_LSB (1 << 8)
#define DISP_ORDER_RED_BLUE (0 << 9)
#define DISP_ORDER_BLUE_RED (1 << 9)
#define DC_DISP_DISP_COLOR_CONTROL 0x430
#define DITHER_CONTROL_MASK (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
#define BASE_COLOR_SIZE_MASK (0xf << 0)
#define BASE_COLOR_SIZE_666 (0 << 0)
#define BASE_COLOR_SIZE_111 (1 << 0)
#define BASE_COLOR_SIZE_222 (2 << 0)
#define BASE_COLOR_SIZE_333 (3 << 0)
#define BASE_COLOR_SIZE_444 (4 << 0)
#define BASE_COLOR_SIZE_555 (5 << 0)
#define BASE_COLOR_SIZE_565 (6 << 0)
#define BASE_COLOR_SIZE_332 (7 << 0)
#define BASE_COLOR_SIZE_888 (8 << 0)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC1_H_QUALIFIER_NONE (1 << 16)
#define SC0_H_QUALIFIER_NONE (1 << 0)
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
#define DE_SELECT_ACTIVE (1 << 0)
#define DE_SELECT_ACTIVE_IS (2 << 0)
#define DE_CONTROL_ONECLK (0 << 2)
#define DE_CONTROL_NORMAL (1 << 2)
#define DE_CONTROL_EARLY_EXT (2 << 2)
#define DE_CONTROL_EARLY (3 << 2)
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
#define DC_DISP_SD_BL_PARAMETERS 0x4D7
#define DC_DISP_SD_BL_CONTROL 0x4DC
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_WIN_CSC_YOF 0x611
#define DC_WIN_CSC_KYRGB 0x612
#define DC_WIN_CSC_KUR 0x613
#define DC_WIN_CSC_KVR 0x614
#define DC_WIN_CSC_KUG 0x615
#define DC_WIN_CSC_KVG 0x616
#define DC_WIN_CSC_KUB 0x617
#define DC_WIN_CSC_KVB 0x618
#define DC_WIN_AD_WIN_OPTIONS 0xB80
#define DC_WIN_BD_WIN_OPTIONS 0xD80
#define DC_WIN_CD_WIN_OPTIONS 0xF80
// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION (1 << 0)
#define V_DIRECTION (1 << 2)
#define SCAN_COLUMN (1 << 4)
#define COLOR_EXPAND (1 << 6)
#define CSC_ENABLE (1 << 18)
#define WIN_ENABLE (1 << 30)
#define DC_WIN_COLOR_DEPTH 0x703
#define WIN_COLOR_DEPTH_P1 0x0
#define WIN_COLOR_DEPTH_P2 0x1
#define WIN_COLOR_DEPTH_P4 0x2
#define WIN_COLOR_DEPTH_P8 0x3
#define WIN_COLOR_DEPTH_B4G4R4A4 0x4
#define WIN_COLOR_DEPTH_B5G5R5A 0x5
#define WIN_COLOR_DEPTH_B5G6R5 0x6
#define WIN_COLOR_DEPTH_AB5G5R5 0x7
#define WIN_COLOR_DEPTH_B8G8R8A8 0xC
#define WIN_COLOR_DEPTH_R8G8B8A8 0xD
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE
#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF
#define WIN_COLOR_DEPTH_YCbCr422 0x10
#define WIN_COLOR_DEPTH_YUV422 0x11
#define WIN_COLOR_DEPTH_YCbCr420P 0x12
#define WIN_COLOR_DEPTH_YUV420P 0x13
#define WIN_COLOR_DEPTH_YCbCr422P 0x14
#define WIN_COLOR_DEPTH_YUV422P 0x15
#define WIN_COLOR_DEPTH_YCbCr422R 0x16
#define WIN_COLOR_DEPTH_YUV422R 0x17
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
#define WIN_COLOR_DEPTH_YUV422RA 0x19
#define DC_WIN_BUFFER_CONTROL 0x702
#define DC_WIN_POSITION 0x704
#define DC_WIN_SIZE 0x705
#define H_SIZE(x) (((x) & 0x1fff) << 0)
#define V_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_PRESCALED_SIZE 0x706
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_H_INITIAL_DDA 0x707
#define DC_WIN_V_INITIAL_DDA 0x708
#define DC_WIN_DDA_INC 0x709
#define H_DDA_INC(x) (((x) & 0xffff) << 0)
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
#define DC_WIN_DV_CONTROL 0x70E
// The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808
#define DC_WINBUF_SURFACE_KIND 0x80B
#define PITCH (0 << 0)
#define TILED (1 << 0)
#define BLOCK (2 << 0)
#define BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
/*! Display serial interface registers. */
#define _DSIREG(reg) ((reg) * 4)
#define DSI_INCR_SYNCPT_CNTRL 0x1
#define DSI_RD_DATA 0x9
#define DSI_WR_DATA 0xA
#define DSI_POWER_CONTROL 0xB
#define DSI_POWER_CONTROL_ENABLE 1
#define DSI_INT_ENABLE 0xC
#define DSI_INT_STATUS 0xD
#define DSI_INT_MASK 0xE
#define DSI_HOST_CONTROL 0xF
#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21)
#define DSI_HOST_CONTROL_CRC_RESET (1 << 20)
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
#define DSI_HOST_CONTROL_RAW (1 << 6)
#define DSI_HOST_CONTROL_HS (1 << 5)
#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4)
#define DSI_HOST_CONTROL_IMM_BTA (1 << 3)
#define DSI_HOST_CONTROL_PKT_BTA (1 << 2)
#define DSI_HOST_CONTROL_CS (1 << 1)
#define DSI_HOST_CONTROL_ECC (1 << 0)
#define DSI_CONTROL 0x10
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
#define DSI_SOL_DELAY 0x11
#define DSI_MAX_THRESHOLD 0x12
#define DSI_TRIGGER 0x13
#define DSI_TRIGGER_HOST (1 << 1)
#define DSI_TRIGGER_VIDEO (1 << 0)
#define DSI_TX_CRC 0x14
#define DSI_STATUS 0x15
#define DSI_INIT_SEQ_CONTROL 0x1A
#define DSI_INIT_SEQ_DATA_0 0x1B
#define DSI_INIT_SEQ_DATA_1 0x1C
#define DSI_INIT_SEQ_DATA_2 0x1D
#define DSI_INIT_SEQ_DATA_3 0x1E
#define DSI_PKT_SEQ_0_LO 0x23
#define DSI_PKT_SEQ_0_HI 0x24
#define DSI_PKT_SEQ_1_LO 0x25
#define DSI_PKT_SEQ_1_HI 0x26
#define DSI_PKT_SEQ_2_LO 0x27
#define DSI_PKT_SEQ_2_HI 0x28
#define DSI_PKT_SEQ_3_LO 0x29
#define DSI_PKT_SEQ_3_HI 0x2A
#define DSI_PKT_SEQ_4_LO 0x2B
#define DSI_PKT_SEQ_4_HI 0x2C
#define DSI_PKT_SEQ_5_LO 0x2D
#define DSI_PKT_SEQ_5_HI 0x2E
#define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37
#define DSI_PHY_TIMING_0 0x3C
#define DSI_PHY_TIMING_1 0x3D
#define DSI_PHY_TIMING_2 0x3E
#define DSI_BTA_TIMING 0x3F
#define DSI_TIMEOUT_0 0x44
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
#define DSI_TIMEOUT_1 0x45
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
#define DSI_TO_TALLY 0x46
#define DSI_PAD_CONTROL_0 0x4B
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
#define DSI_PAD_CONTROL_CD 0x4c
#define DSI_VIDEO_MODE_CONTROL 0x4E
#define DSI_PAD_CONTROL_1 0x4F
#define DSI_PAD_CONTROL_2 0x50
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
#define DSI_PAD_CONTROL_4 0x52
#define DSI_PAD_CONTROL_5_MARIKO 0x53
#define DSI_PAD_CONTROL_6_MARIKO 0x54
#define DSI_PAD_CONTROL_7_MARIKO 0x55
#define DSI_INIT_SEQ_DATA_15 0x5F
#define DSI_INIT_SEQ_DATA_15_MARIKO 0x62

View File

@@ -0,0 +1,68 @@
/*
* 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 <exosphere.hpp>
#include "fatal_save_context.hpp"
#include "fatal_sdmmc.hpp"
#include "fs/fatal_fs_api.hpp"
namespace ams::secmon::fatal {
Result SaveFatalErrorContext(const ams::impl::FatalErrorContext *ctx) {
/* Initialize the sdmmc driver. */
R_TRY(InitializeSdCard());
/* Get the connection status. */
#if defined(AMS_BUILD_FOR_DEBUGGING) || defined(AMS_BUILD_FOR_AUDITING)
{
sdmmc::SpeedMode speed_mode;
sdmmc::BusWidth bus_width;
R_TRY(CheckSdCardConnection(std::addressof(speed_mode), std::addressof(bus_width)));
AMS_SECMON_LOG("Sd Card Connection:\n");
AMS_SECMON_LOG(" Speed Mode: %u\n", static_cast<u32>(speed_mode));
AMS_SECMON_LOG(" Bus Width: %u\n", static_cast<u32>(bus_width));
}
#endif
/* Mount the SD card. */
R_UNLESS(fs::MountSdCard(), fs::ResultPartitionNotFound());
/* Unmount the SD card once we're done. */
ON_SCOPE_EXIT { fs::UnmountSdCard(); };
/* Create and open the file. */
fs::FileHandle file;
{
/* Generate the file path. */
char path[0x40];
util::TSNPrintf(path, sizeof(path), "/atmosphere/fatal_errors/report_%016" PRIx64 ".bin", ctx->report_identifier);
/* Create the file. */
R_TRY(fs::CreateFile(path, sizeof(*ctx)));
/* Open the file. */
R_TRY(fs::OpenFile(std::addressof(file), path, fs::OpenMode_ReadWrite));
}
/* Ensure we close the file when done with it. */
ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Write the context to the file. */
R_TRY(fs::WriteFile(file, 0, ctx, sizeof(*ctx), fs::WriteOption::Flush));
return ResultSuccess();
}
}

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 <exosphere.hpp>
namespace ams::secmon::fatal {
Result SaveFatalErrorContext(const ams::impl::FatalErrorContext *ctx);
}

View File

@@ -0,0 +1,108 @@
/*
* 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 <exosphere.hpp>
#include "fatal_device_page_table.hpp"
namespace ams::secmon::fatal {
namespace {
constexpr inline auto Port = sdmmc::Port_SdCard0;
ALWAYS_INLINE u8 *GetSdCardWorkBuffer() {
return MemoryRegionVirtualDramSdmmcMappedData.GetPointer<u8>() + MemoryRegionVirtualDramSdmmcMappedData.GetSize() - mmu::PageSize;
}
ALWAYS_INLINE u8 *GetSdCardDmaBuffer() {
return MemoryRegionVirtualDramSdmmcMappedData.GetPointer<u8>();
}
constexpr inline size_t SdCardDmaBufferSize = MemoryRegionVirtualDramSdmmcMappedData.GetSize() - mmu::PageSize;
constexpr inline size_t SdCardDmaBufferSectors = SdCardDmaBufferSize / sdmmc::SectorSize;
static_assert(util::IsAligned(SdCardDmaBufferSize, sdmmc::SectorSize));
}
Result InitializeSdCard() {
/* Map main memory for the sdmmc device. */
InitializeDevicePageTableForSdmmc1();
/* Initialize sdmmc library. */
sdmmc::Initialize(Port);
sdmmc::SetSdCardWorkBuffer(Port, GetSdCardWorkBuffer(), sdmmc::SdCardWorkBufferSize);
//sdmmc::Deactivate(Port);
R_TRY(sdmmc::Activate(Port));
return ResultSuccess();
}
Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) {
return sdmmc::CheckSdCardConnection(out_sm, out_bw, Port);
}
Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count) {
/* Validate that our buffer is valid. */
AMS_ASSERT(size >= sector_count * sdmmc::SectorSize);
/* Repeatedly read sectors. */
u8 *dst_u8 = static_cast<u8 *>(dst);
void * const dma_buffer = GetSdCardDmaBuffer();
while (sector_count > 0) {
/* Read sectors into the DMA buffer. */
const size_t cur_sectors = std::min(sector_count, SdCardDmaBufferSectors);
const size_t cur_size = cur_sectors * sdmmc::SectorSize;
R_TRY(sdmmc::Read(dma_buffer, cur_size, Port, sector_index, cur_sectors));
/* Copy data from the DMA buffer to the output. */
std::memcpy(dst_u8, dma_buffer, cur_size);
/* Advance. */
dst_u8 += cur_size;
sector_index += cur_sectors;
sector_count -= cur_sectors;
}
return ResultSuccess();
}
Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size) {
/* Validate that our buffer is valid. */
AMS_ASSERT(size >= sector_count * sdmmc::SectorSize);
/* Repeatedly read sectors. */
const u8 *src_u8 = static_cast<const u8 *>(src);
void * const dma_buffer = GetSdCardDmaBuffer();
while (sector_count > 0) {
/* Copy sectors into the DMA buffer. */
const size_t cur_sectors = std::min(sector_count, SdCardDmaBufferSectors);
const size_t cur_size = cur_sectors * sdmmc::SectorSize;
std::memcpy(dma_buffer, src_u8, cur_size);
/* Write sectors to the sd card. */
R_TRY(sdmmc::Write(Port, sector_index, cur_sectors, dma_buffer, cur_size));
/* Advance. */
src_u8 += cur_size;
sector_index += cur_sectors;
sector_count -= cur_sectors;
}
return ResultSuccess();
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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 <exosphere.hpp>
namespace ams::secmon::fatal {
Result InitializeSdCard();
Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw);
Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count);
Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size);
}

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