Compare commits

..

369 Commits

Author SHA1 Message Date
Michael Scire
e6bddf8782 i2c: correct missing destruction 2020-11-14 03:37:17 -08:00
Michael Scire
d8bd3d16bb ams.mitm: provide different boot0-protection for custom public key 2020-11-10 23:25:24 -08:00
Michael Scire
80f567d46a wec: whoops 2020-11-10 18:32:21 -08:00
Michael Scire
b6580b3170 updater: don't overwrite custom-public-key BCTs 2020-11-10 16:53:19 -08:00
Michael Scire
df8ceb9b06 pinmux: whoops 2020-11-10 16:30:36 -08:00
Michael Scire
c5656d39d2 boot/powctl/i2c: more miscellaneous fixes 2020-11-10 05:50:13 -08:00
Michael Scire
62ff502979 boot: various bugfixes (b/w logo displays now) 2020-11-10 05:02:41 -08:00
Michael Scire
f135ee74f8 powctl: implement max17050 driver 2020-11-10 02:23:05 -08:00
Michael Scire
8c3e536e94 powctl: add battery driver logic (missing impl) 2020-11-10 01:27:35 -08:00
Michael Scire
35573c4d85 powctl: implement max17050 custom parameter init 2020-11-09 23:14:31 -08:00
Michael Scire
e6ef753bb6 powctl: implement full bq24193 driver 2020-11-09 21:50:41 -08:00
Michael Scire
eade15b34e i2c: add register acccessor helpers 2020-11-09 17:34:47 -08:00
Michael Scire
b9c5dab18a powctl: add ChargerDriver body (needs impl) 2020-11-09 17:09:25 -08:00
Michael Scire
d0a45b8f21 pinmux: implement updated initial config api 2020-11-09 02:01:29 -08:00
Michael Scire
e0ce035323 boot: update/refactor display management to support hw type 5/display 0x1040/0x2050 2020-11-08 17:56:49 -08:00
Michael Scire
2562700f34 dd: implement DeviceAddressSpaceType api 2020-11-08 15:27:55 -08:00
Michael Scire
e93c3cbf58 boot: refactor battery checking to use new powctl apis 2020-11-08 04:16:50 -08:00
Michael Scire
cd7d7894f1 powctl: implement client api (needs board-specific impl) 2020-11-02 18:13:36 -08:00
Michael Scire
aa63b1eab7 pwm: implement driver for boot sysmodule 2020-11-01 23:04:19 -08:00
Michael Scire
4cc4f5fdb0 gpio: add missing driver functions for boot 2020-11-01 23:04:01 -08:00
Michael Scire
22ae1d5bd3 i2c: implement remaining required driver logic 2020-11-01 00:52:02 -07:00
Michael Scire
43f7b10c0f i2c: command list format, get boot down to linker errors 2020-10-31 22:52:43 -07:00
Michael Scire
48784da42a i2c/gpio: hook up open session for sf interface 2020-10-31 21:50:21 -07:00
Michael Scire
f27d6f2fd8 i2c: implement driver init api 2020-10-31 20:14:41 -07:00
Michael Scire
6f7502dfef i2c: finish I2cBusAccessor 2020-10-31 19:14:43 -07:00
Michael Scire
2d2b11a2d2 i2c: implement BusAccessor::WriteHeader 2020-10-31 18:24:26 -07:00
Michael Scire
2744a614de i2c: implement BusAccessor except Send/Receive/WriteHeader 2020-10-31 17:58:38 -07:00
Michael Scire
27be1a548c boot: add rgltr/clkrst overrides, skel I2cBusAccessor 2020-10-31 16:34:06 -07:00
Michael Scire
91b2a233c4 i2c: add auto-generated bus/device map 2020-10-31 14:20:01 -07:00
Michael Scire
7636dd2d44 i2c: begin skeleton device driver framework 2020-10-31 04:55:11 -07:00
Michael Scire
c867975eb8 gpio: remove copy-pasted unused file 2020-10-31 03:23:30 -07:00
Michael Scire
5bc4abb92f gpio: implement more of server library for boot sysmodule client usage 2020-10-31 03:22:01 -07:00
Michael Scire
e1dccef7d1 wec: implement wec driver components for boot sysmodule 2020-10-31 00:47:45 -07:00
Michael Scire
17fa05a789 gpio: add (most of) driver framework for boot sysmodule usage 2020-10-30 23:57:21 -07:00
Michael Scire
5b617f4d2f ddsf: implement namespace 2020-10-30 15:36:11 -07: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
SciresM
ac04e02a08 Meso build targets (#1196)
* meso: commit wip (thanks fincs) rewrite to support build targets

* meso: commit mostly-working build system

* meso: correct .o dependencies in kernel/kldr

* libstratosphere: fix building after PCH related build changes

Co-authored-by: fincs <fincs@devkitpro.org>
2020-10-27 13:55:19 -07:00
Michael Scire
1c71d12d9d ams.mitm: avoid inadvertently breaking ftpd/file listers 2020-10-27 10:28:51 -07:00
Michael Scire
37738699f2 docs: edit terminology to be hip to the jive 2020-10-26 16:14:25 -07:00
Michael Scire
e973ef7533 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "10e9e0e8"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "10e9e0e8"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-10-26 16:03:40 -07:00
Michael Scire
2ee2a4f1ac docs/fatal error: update for 0.15.0 2020-10-26 16:00:34 -07:00
Michael Scire
2a2bffeb35 ams: fix building debug elf zip 2020-10-15 09:47:06 -07:00
Michael Scire
d04046ecaf ams: bump version to 0.15.0 (release slated for post-crown-tundra) 2020-10-15 09:41:49 -07:00
Michael Scire
f24171dc41 ams: build experimental zip in addition to standard one 2020-10-15 09:41:01 -07:00
Michael Scire
5b02c77400 ams: fix updater misbehavior before 0.15.0 releases 2020-10-14 12:28:26 -07:00
Michael Scire
2e7214b6fa kern: perform rescheduling on dispatch re-enable (closes #1169) 2020-10-13 23:07:51 -07:00
Michael Scire
d52179c708 util: follow 90fd771 to its natural conclusion (generic base rbtree) 2020-10-12 01:06:19 -07:00
Michael Scire
388f9e6455 kern: minor behavioral fixes to condvar/address arbiter 2020-10-12 01:06:19 -07:00
SciresM
c547c7f0e7 Note that we are a python 2 project. 2020-10-09 17:37:51 -07:00
Michael Scire
4138abbefa erpt: fix attachment-in-save paths (closes #1124, #1145) 2020-09-23 19:49:20 -07:00
Michael Scire
1275eb0bf3 erpt: add fixed-width format option 2020-09-23 17:52:08 -07:00
Michael Scire
5ac9e45d86 erpt: support older erpt binaries 2020-09-23 17:36:46 -07:00
Michael Scire
feba788bc6 erpt.py: remove idaapi usage 2020-09-23 16:05:27 -07:00
Michael Scire
f4d10a4481 set.mitm: much more aggressively cache locale (#1160) 2020-09-23 02:01:07 -07:00
Michael Scire
ff310a0647 fusee: try to alleviate a little suffering 2020-09-22 13:54:23 -07:00
Michael Scire
85505db9b7 loader: adjust thread priority for applet-hbl 2020-09-22 12:01:28 -07:00
Michael Scire
48b4dd48a4 ams: expose reboot payload for kernel panic 2020-09-18 00:43:55 -07:00
Michael Scire
8d46d901d9 ams: make mesosphere usage user-visible in display version 2020-09-17 21:18:44 -07:00
Michael Scire
1930880270 fusee: change ncm from opt-in to opt-out 2020-09-17 21:04:43 -07:00
Michael Scire
fa0df994ba git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "f6dac1e6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "f6dac1e6"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-17 08:34:48 -07:00
Michael Scire
909a1767a6 ams: bump version to 0.14.4 2020-09-17 08:34:02 -07:00
Michael Scire
dbe59fd041 kern: fix KCodeMemory SVCs when Owner process != Generator process 2020-09-17 08:26:08 -07:00
Michael Scire
9b65daf439 kern: default to release config 2020-09-17 08:26:08 -07:00
Michael Scire
4acdc899f5 kern: generate fatal error on panic 2020-09-17 08:26:08 -07:00
Michael Scire
76957e502d kern: add build-define for logging to iram ringbuffer 2020-09-17 08:26:08 -07:00
Michael Scire
909397233c sm: Fix atmosphere-extension interaction with official JIT sysmodule usage 2020-09-17 08:24:47 -07:00
Michael Scire
211a828730 ro: fix process handle leak when using JitPlugin NROs 2020-09-17 08:17:11 -07:00
Michael Scire
28ceedb533 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "6a814ebb"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "exo2"
  commit:   "6a814ebb"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-14 18:21:38 -07:00
Michael Scire
f551ca4461 emummc: manually fix .gitrepo 2020-09-14 18:17:32 -07:00
Michael Scire
2cf5c65bc5 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "48dbf480"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "48dbf480"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-14 18:14:05 -07:00
Michael Scire
47d0d5c6ab ams: support 10.2.0 (bump vers to 0.14.3) 2020-09-14 18:13:18 -07:00
Michael Scire
fd0e3e2160 docs: update changelog 2020-09-14 18:12:48 -07:00
Michael Scire
074364753f loader: improve verification terminology 2020-09-08 15:34:22 -07:00
Michael Scire
b7d99b732a ro: rename ModuleType to reflect reality 2020-09-08 15:05:15 -07:00
Michael Scire
1cccb6efc4 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "04ef9bf8"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "04ef9bf8"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-07 10:52:49 -07:00
Michael Scire
f4cd4bcf03 ams: bump version to 0.14.2 2020-09-07 10:51:15 -07:00
Michael Scire
e36fe62fca kern: lps driver fixes, sleep confirmed working on 1.0.0 2020-09-07 10:43:35 -07:00
Michael Scire
870b589379 kern: fix c/p error 2020-09-07 10:43:35 -07:00
Michael Scire
acdce230da kern: add debug logging on smmu error interrupt 2020-09-07 10:43:35 -07:00
Michael Scire
34dc062c11 kern: finish 1.x lps driver 2020-09-07 10:43:35 -07:00
Michael Scire
ab2568ddfb kern: add most of 1.x lps driver 2020-09-07 10:43:35 -07:00
Michael Scire
4dc728824f kern: skeleton legacy lps driver 2020-09-07 10:43:35 -07:00
Michael Scire
cc6b8ea4d1 exo/kern: 1.0.0 requires access to bpmp smmu regs, userland (am) needs to map bpmp exception vectors 2020-09-07 10:43:35 -07:00
Michael Scire
49af4fae32 kern: begin 1.0.0 backwards compat changes (kips run, full boot fails) 2020-09-07 10:43:35 -07:00
Michael Scire
e8ffbe630f kern: support 2-pool layout on 2.x-4.x instead of modern 4-pool layout 2020-09-07 10:43:35 -07:00
Michael Scire
ce95af89ef kern: change terminology metadata -> management 2020-09-07 10:43:35 -07:00
Michael Scire
546e2de300 kern: pool management should be within carveout 2020-09-07 10:43:35 -07:00
Michael Scire
11b120b667 kern: fix phys/virt pool management mixup 2020-09-07 10:43:35 -07:00
Michael Scire
4da1fe545c kern: fix linear mapped dram -> pool partition check 2020-09-07 10:43:35 -07:00
Michael Scire
1983f86875 kern: revamp KMemoryRegionType to better encode derivation hierarchies 2020-09-07 10:43:35 -07:00
Michael Scire
d50c7c5c79 kern: PMC must be user-mappable for 1.0.0 compat 2020-09-07 10:43:35 -07:00
Michael Scire
496f93ccdb kern: expose mesosphere meta over GetInfo instead of GetSystemInfo 2020-09-07 10:43:35 -07:00
Michael Scire
25ba61adae loader: extend memory region descriptors a touch more gracefully 2020-09-07 10:43:35 -07:00
Michael Scire
79c9bed528 kern/pm: support for 5.x under mesosphere 2020-09-07 10:43:35 -07:00
Michael Scire
657470830f loader: support MapRegion capability as an atmosphere extension (normally kips-only) 2020-09-07 10:43:35 -07:00
Michael Scire
cd62d83586 fusee: fix sleep/wake on 6.x 2020-09-07 10:43:35 -07:00
Michael Scire
bb11c57e7d kern: fix warn-errors 2020-09-07 10:43:35 -07:00
Michael Scire
bb1cdd8c87 fusee: fixes for sd meso on lower firmwares 2020-09-07 10:43:35 -07:00
Michael Scire
ff9b9fc5ff fusee: change meso loading to parse INI from Nintendo's kernel 2020-09-07 10:43:35 -07:00
Michael Scire
99b5458539 sm: fix deadlock semantics surrounding mitm installation 2020-09-07 10:40:57 -07:00
Michael Scire
fac502aaa3 kern: fix KTypedAddress, strengthen assertions 2020-08-18 15:17:40 -07:00
Michael Scire
47f2e93a42 kern: add version bounds checking 2020-08-18 15:17:40 -07:00
Michael Scire
56ec55f3c4 kern: avoid hardcoding maximum board memory size 2020-08-18 15:17:40 -07:00
Michael Scire
1a262c1063 kern: improve resource region size definitions/calculations 2020-08-18 15:17:40 -07:00
Michael Scire
79201428b0 kern: resolve NonSecure definition TODO 2020-08-18 15:17:40 -07:00
Michael Scire
a75c16226e kern: correct thread termination atomicity 2020-08-18 15:17:40 -07:00
Michael Scire
e5d30217d3 kern: fix reference leak in KThread::GetThreadFromId callers 2020-08-18 15:17:40 -07:00
Michael Scire
f77a4fbf98 kern: non-loop cas-weak -> cas-strong 2020-08-18 15:17:40 -07:00
Michael Scire
717265a54c kern: fix bug in KScheduler::ClearPreviousThread 2020-08-18 15:17:40 -07:00
fincs
3ace441b1c arm64: set -march in cpu specific configuration 2020-08-18 15:17:40 -07:00
fincs
2effe130e3 kern: use size instead of phys addr as sentinel value in InitializeCore linear mapping logic 2020-08-18 15:17:40 -07:00
fincs
2cedf2bcf0 kern: remove accidentally copypasted code 2020-08-18 15:17:40 -07:00
fincs
68e29b56b6 kern: add stubbed KDevicePageTable implementation for systems without iommu 2020-08-18 15:17:40 -07:00
fincs
8e688de570 kern: move SetupPoolPartitionMemoryRegions into board specific implementation 2020-08-18 15:17:40 -07:00
fincs
b917ea283e kern: make GetTargetFirmware a compile-time constant when not building for Switch 2020-08-18 15:17:40 -07:00
Michael Scire
3c85e37667 kern: use std::atomic_ref instead of reinterpret_cast to std::atomic 2020-08-18 15:17:40 -07:00
Michael Scire
48e8562033 kern: use common GIC implementation for arm/arm64 2020-08-18 15:17:40 -07:00
Michael Scire
f07bd0e337 kern: correct flushing of init arguments 2020-08-18 15:17:40 -07:00
Michael Scire
4a35904d73 kern: simplify SetupForIpcClient cleanup 2020-08-18 15:17:40 -07:00
Michael Scire
b8c2782ede kern: SvcLegacyGetFutureThreadInfo 2020-08-18 15:17:40 -07:00
Michael Scire
3ec9a9e59f kern: rename CacheHelper operation for accuracy 2020-08-18 15:17:40 -07:00
Michael Scire
595c6dbe8f kern: KPageTableBase::WriteDebugMemory stores/invalidates cache 2020-08-18 15:17:40 -07:00
Michael Scire
b5f2698bf0 kern: fix multicore instruction cache invalidation 2020-08-18 15:17:40 -07:00
Michael Scire
f058536b59 kern: add tracing for irq/scheduling 2020-08-18 15:17:40 -07:00
Michael Scire
8e5c0a9663 kern: cleanup some KMemoryManager functions 2020-08-18 15:17:40 -07:00
Michael Scire
1b63002f91 kern: refactor KMemoryLayout 2020-08-18 15:17:40 -07:00
Michael Scire
90fd771fce IntrusiveRedBlackTree: refactor to add ->GetPrev(), ->GetNext() to BaseNode inheritors 2020-08-18 15:17:40 -07:00
Michael Scire
c3fa3bd5d6 kern: N reduced the slabheap gap size in 10.0.0 2020-08-18 15:17:40 -07:00
Michael Scire
cda15f08d8 kern: mark KThread/KProcess.GetId() final to save virtual calls 2020-08-18 15:17:40 -07:00
Michael Scire
e5b7eb89e5 kern: fix built-in usage for libc 2020-08-18 15:17:40 -07:00
Michael Scire
e1bd6fb874 kern: fix missing scheduler updates in KLightLock/Exception, fix RequestScheduleOnInterrupt 2020-08-18 15:17:40 -07:00
Michael Scire
920b017677 kern: implement svc trace 2020-08-18 15:17:40 -07:00
Michael Scire
f9d68db3f6 kern: SvcChangeKernelTraceState 2020-08-18 15:17:40 -07:00
Michael Scire
89f1c0ce33 kern: remove stray log in SetHeapSize 2020-08-18 15:17:40 -07:00
Michael Scire
e435f56367 exo: build with -Wextra 2020-08-17 14:39:18 -07:00
Michael Scire
73798cb812 kern: build with -Wextra 2020-08-17 14:20:24 -07:00
Michael Scire
d3014f6ed9 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "2d522dc6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "2d522dc6"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-15 09:20:46 -07:00
Michael Scire
35fffade4e libstrat: fix building of source/os/* 2020-08-15 09:20:11 -07:00
Michael Scire
2c6b7ce6c2 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "5a60240f"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "5a60240f"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-14 17:37:03 -07:00
Michael Scire
7658c07492 strat: fix inclusion/ordering for some c headers 2020-08-14 17:33:49 -07:00
Michael Scire
51b5c3d87d ams: avoid UB infinite loops 2020-08-13 17:28:29 -07:00
Michael Scire
874208b44a sf: handle serialization errors more accurately and gracefully 2020-08-11 16:40:57 -07:00
Michael Scire
44c5cb9789 ams: add support for cpu-extension specific source files 2020-08-11 11:43:34 -07:00
Michael Scire
420bc7df9b ams: update build system to add generic-fallback support 2020-08-11 11:22:56 -07:00
Michael Scire
ee3e0fa537 fatal: use TimeSpan for timing 2020-08-03 19:52:53 -07:00
Aurora Wright
501280b6e5 fatal: Fix autoreboot logic 2020-08-03 19:44:14 -07:00
Michael Scire
ee5a095c1a git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "cac5957d"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "cac5957d"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-02 15:03:17 -07:00
Michael Scire
3726def6ec ams: dump version to 0.14.1 2020-08-02 15:02:43 -07:00
Michael Scire
29358dc593 kernel_ldr: use unoptimized memcpy before mmu bringup (closes #1102)
Before the MMU is up, all reads/writes must be aligned; the optimized
memcpy implementation does not guarantee all reads/writes it performs
are aligned.

This commit splits the libc impl to be separate for kernel/kernel_ldr,
and so now only kernel will use the optimized impl. This is safe,
as the MMU is brought up before kernel begins executing.
2020-08-02 14:40:28 -07:00
Michael Scire
a82914d58e git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "f288b81b"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "f288b81b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-01 15:37:27 -07:00
Michael Scire
0508b5d31b target firmware: I am remarkably bad at this 2020-08-01 15:36:50 -07:00
Michael Scire
235c070a37 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "4e80a401"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "4e80a401"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-01 15:36:09 -07:00
Michael Scire
82f757459e target firmware: fix typo 2020-08-01 15:35:38 -07:00
Michael Scire
b2b47da8c1 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "27c71f4e"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "27c71f4e"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-01 15:34:13 -07:00
Michael Scire
bc364029b2 docs: update changelog 2020-08-01 15:30:25 -07:00
Michael Scire
ac9832c5ce docs: update roadmap 2020-08-01 15:29:59 -07:00
Michael Scire
b65707efd9 ams: add support for 10.1.1 2020-08-01 15:29:59 -07:00
hexkyz
98ca5e2927 fusee: re-design and fix emummc handling 2020-08-01 17:20:56 +01:00
Michael Scire
91bbdf2baf TimeSpan: fix FromDays 2020-07-31 14:52:00 -07:00
Michael Scire
3fd4002bc9 kern: complete final SVC stubs (KernelDebug/Trace debug-impl still TODO) 2020-07-31 14:50:52 -07:00
Michael Scire
5d462c626c kern: SvcReturnFromException 2020-07-31 14:50:52 -07:00
Michael Scire
8cd81b3092 kern: fix dynamic calculation of slab heap size 2020-07-31 14:50:52 -07:00
Michael Scire
5c4fbf5c67 kern SvcGetDebugThreadContext, SvcSetDebugThreadContext 2020-07-31 14:50:52 -07:00
Michael Scire
3afd723b92 kern: SvcGetDebugThreadParam 2020-07-31 14:50:52 -07:00
Michael Scire
e1f3bb10a5 kern: clean up majority of TODOs 2020-07-31 14:50:52 -07:00
Michael Scire
bea550ebce kern: resolve final non-user-exception MESOSPHERE_UNIMPLEMENTED 2020-07-31 14:50:52 -07:00
Michael Scire
85f533e6c4 kern: SvcGetDebugEventInfo64From32 2020-07-31 14:50:52 -07:00
Michael Scire
c9f8252577 kern: resolve MESOSPHERE_UNIMPLEMENTEDs other than UserException 2020-07-31 14:50:52 -07:00
Michael Scire
325802e29d kern: Add real SvcBreak implementation 2020-07-31 14:50:52 -07:00
Michael Scire
4c3c910774 kern: SvcBreakDebugProcess, SvcTerminateDebugProcess 2020-07-31 14:50:52 -07:00
Michael Scire
b88e09de5b kern: SvcSetHardwareBreakPoint 2020-07-31 14:50:52 -07:00
Michael Scire
b143f1e05f kern: Svc(Legacy)ContinueDebugEvent 2020-07-31 14:50:52 -07:00
Michael Scire
3289b45408 kern: Add 4.x InitialProcessIdRange to SvcGetInfo 2020-07-31 14:50:52 -07:00
Michael Scire
91fa0d651f kern: SvcQueryPhysicalAddress 2020-07-31 14:50:52 -07:00
Michael Scire
9bc2c0c0c5 kern: style parity for return in GetThreadList 2020-07-31 14:50:52 -07:00
Michael Scire
96c3dfee14 kern: SvcGetThreadList 2020-07-31 14:50:52 -07:00
Michael Scire
51084c0837 kern: SvcGetLastThreadInfo, SvcGetDebugFutureThreadInfo 2020-07-31 14:50:52 -07:00
Michael Scire
0993ae0685 kern: SvcFlushDataCache, SvcFlushEntireDataCache 2020-07-31 14:50:52 -07:00
Michael Scire
e4b30f4022 kern: build without unwind tables for lto 2020-07-31 14:50:52 -07:00
Michael Scire
f6f43300e0 kern: SvcReadDebugProcessMemory, SvcWriteDebugProcessMemory 2020-07-31 14:50:52 -07:00
Michael Scire
1ffe08672d kern: fix EL0 TLB conflict handler 2020-07-31 14:50:52 -07:00
Michael Scire
f866f37cdc kern: panic on failure-to-open auto object in debug config 2020-07-31 14:50:52 -07:00
Michael Scire
008bfc27f3 kern: automatic PC alignment on ERET is implementation defined 2020-07-31 14:50:52 -07:00
Michael Scire
7352d87b20 kern: switch memset to optimized impl 2020-07-31 14:50:52 -07:00
Michael Scire
9ddb4194b3 kern: use optimized memcmp/memcpy implementations 2020-07-31 14:50:52 -07:00
Michael Scire
3f17a34b67 SvcQueryDebugProcessMemory 2020-07-31 14:50:52 -07:00
Michael Scire
5de853b662 kern: fix ARM vs THUMB mode selection on 32-bit entry 2020-07-31 14:50:52 -07:00
Michael Scire
36a3909a24 kern: fix whoops in light ipc 2020-07-31 14:50:52 -07:00
Michael Scire
8922bbd108 kern: SendSyncRequestLight, ReplyAndReceiveLight 2020-07-31 14:50:52 -07:00
Michael Scire
b6cb561c47 kern: fix slab heap atomics 2020-07-31 14:50:52 -07:00
Michael Scire
2db6760461 kern: fix bug in server handle cleanup 2020-07-31 14:50:52 -07:00
Michael Scire
bb7f320f7f kern: fix nonsensical copy/pasted comments in QueryMemory 2020-07-31 14:50:52 -07:00
Michael Scire
94a170c437 kern: QueryMemory64From32, QueryProcessMemory64From32 2020-07-31 14:50:52 -07:00
Michael Scire
7cf0432569 kern: add KCodeMemory code left out of previous commit 2020-07-31 14:50:52 -07:00
Michael Scire
39b22cee8c kern: implement KCodeMemory (and SVCs) 2020-07-31 14:50:52 -07:00
Michael Scire
3fb3beeaff kern: SvcGetSystemTick 2020-07-31 14:50:52 -07:00
Michael Scire
4bb9ef061a kern: implement SvcGetThreadContext3 2020-07-31 14:50:52 -07:00
Michael Scire
f70ee67753 kern: correct behavior when setting activity/core mask for pinned thread 2020-07-31 14:50:52 -07:00
Michael Scire
787964f7e7 kern: implement thread pinning/SvcSynchronizePreemptionState 2020-07-31 14:50:52 -07:00
Michael Scire
b1f38be3ae kern: fix building under release config 2020-07-31 14:50:52 -07:00
Michael Scire
9dc3e025fc kern: Map L1/L2 blocks when possible 2020-07-31 14:50:52 -07:00
Michael Scire
4ac94e9179 kern: improve KLightLock accuracy 2020-07-31 14:50:52 -07:00
Michael Scire
1448068b69 kern: fix assertion in KThread::(Try)Suspend 2020-07-31 14:50:52 -07:00
Michael Scire
0af44d2875 kern: fix bug in page table mapping calculations 2020-07-31 14:50:52 -07:00
Michael Scire
a4d376cc0f kern: fix hardware timer task corruption on core migration 2020-07-31 14:50:52 -07:00
Michael Scire
840ab0785c kern: SvcMapPhysicalMemoryUnsafe, SvcUnmapPhysicalMemoryUnsafe 2020-07-31 14:50:52 -07:00
Michael Scire
583899ede3 kern: General system stability improvements to enhance the user's experience. 2020-07-31 14:50:52 -07:00
Michael Scire
2ad9927a88 kern: Fix bug in thread core migration 2020-07-31 14:50:52 -07:00
Michael Scire
893b046111 kern: update interrupt manager 2020-07-31 14:50:52 -07:00
Michael Scire
3a01fd1ebc svc: add BreakReason flags 2020-07-31 14:50:52 -07:00
Michael Scire
1b9acc4a6a kern: SvcUnmapPhysicalMemory, cleanup thread pinning 2020-07-31 14:50:52 -07:00
Michael Scire
cbecda2a27 kern: SvcQueryProcessMemory64, notification SvcBreaks 2020-07-31 14:50:52 -07:00
Michael Scire
5ecc80a5f6 kern: implement SvcMapPhysicalMemory 2020-07-31 14:50:52 -07:00
Michael Scire
695b82b945 kern: finish SvcGetInfo 2020-07-31 14:50:52 -07:00
Michael Scire
fd9b986938 kern: Implement SecureMemory (system resource) 2020-07-31 14:50:52 -07:00
Michael Scire
9231646f33 kern: implement SvcSleepSystem 2020-07-31 14:50:52 -07:00
Michael Scire
418de7b0dc kern: SvcInvalidateProcessDataCache 2020-07-31 14:50:52 -07:00
Michael Scire
46935fea80 kern: fix resource leak bugs 2020-07-31 14:50:52 -07:00
Michael Scire
11d5353827 kern: SvcMapProcessCodeMemory, SvcUnmapProcessCodeMemory 2020-07-31 14:50:52 -07:00
Michael Scire
240e6227e9 kern: Fix bug when reducing heap size 2020-07-31 14:50:52 -07:00
Michael Scire
1d4d637818 kern SvcGetCurrentProcessorNumber, SvcSetProcessActivity, half of SvcSetThreadActivity 2020-07-31 14:50:52 -07:00
Michael Scire
23eed522d3 kern: SvcGetThreadCoreMask, SvcSetThreadCoreMask 2020-07-31 14:50:52 -07:00
Michael Scire
c622539b95 kern: SvcSetMemoryPermission 2020-07-31 14:50:52 -07:00
Michael Scire
d87a9f011c kern: implement transfer memory (and SVCs) 2020-07-31 14:50:52 -07:00
Michael Scire
28aab09b5d kern: implement process exit 2020-07-31 14:50:52 -07:00
Michael Scire
3917ecad46 kern: add SvcFlushProcessDataCache, SvcStoreProcessDataCache 2020-07-31 14:50:52 -07:00
Michael Scire
ab96255a5d kern: implement SvcSetMemoryAttribute 2020-07-31 14:50:52 -07:00
Michael Scire
185baa7c4d boot2: work around pcv<->fs<->settings race condition 2020-07-31 14:50:52 -07:00
Michael Scire
eecf59dd00 kern: fix bugs in interrupt permittance, DpcManager init 2020-07-31 14:50:52 -07:00
Michael Scire
afe7e41de8 kern: SvcGetProcessInfo, SvcTerminateProcess 2020-07-31 14:50:52 -07:00
Michael Scire
632a75eee7 kern: KConditionVariable::SignalImpl 2020-07-31 14:50:52 -07:00
Michael Scire
7aa3120f60 kern: fully implement KSharedMemory (and Svcs) 2020-07-31 14:50:52 -07:00
Michael Scire
81db43932d kern: add SvcStartProcess 2020-07-31 14:50:52 -07:00
Michael Scire
51311a7332 kern: add KProcess::Initialize (for non-kip processes) 2020-07-31 14:50:52 -07:00
Michael Scire
8759cb4da3 kern: implement first half of SvcCreateProcess 2020-07-31 14:50:52 -07:00
Michael Scire
fb6e85b291 kern: implement SvcMapProcessMemory, SvcUnmapProcessMemory 2020-07-31 14:50:52 -07:00
Michael Scire
3cf793f87e kern: implement KThread::Finalize 2020-07-31 14:50:52 -07:00
Michael Scire
3265927ed7 kern: KDevicePageTable::Finalize, InfoType_RandomEntropy 2020-07-31 14:50:52 -07:00
Michael Scire
0c82709af4 kern: fix attribute checks in device unmap 2020-07-31 14:50:52 -07:00
Michael Scire
058f223b97 kern: finish SvcGetSystemInfo 2020-07-31 14:50:52 -07:00
Michael Scire
43ad4eb794 kern: fix asid tlb invalidation 2020-07-31 14:50:52 -07:00
Michael Scire
dea1235e12 kern: dump page table on user exception 2020-07-31 14:50:52 -07:00
Michael Scire
266001ded4 kern: implement ResourceLimit Svcs 2020-07-31 14:50:52 -07:00
Michael Scire
ea6000b372 kern: add ResourceLimit to svcGetInfo 2020-07-31 14:50:52 -07:00
Michael Scire
4fca870f2f kern: fix incorrect cache routines, implement SvcSetProcessMemoryPermission 2020-07-31 14:50:52 -07:00
Michael Scire
26df56cd87 kern: implement SvcCancelSynchronization 2020-07-31 14:50:52 -07:00
Michael Scire
5b8a20dbf7 kern: fix bug in SvcSetThreadPriority 2020-07-31 14:50:52 -07:00
Michael Scire
94f9cc1626 kern: SvcCreateSession, KDebug finalization 2020-07-31 14:50:52 -07:00
Michael Scire
36eb78a3ce kern: implement SvcDebugActiveProcess, svcGetDebugEvent, SvcWaitProcessWideKeyAtomic 2020-07-31 14:50:52 -07:00
Michael Scire
1c5b58ce66 fusee: add support for booting mesosphere 2020-07-31 14:50:52 -07:00
Michael Scire
0bd14b7114 kern: fix bug in KPageTableBase::SetupForIpcServer 2020-07-31 14:50:52 -07:00
Michael Scire
75e6999668 kern: implement SvcSetThreadPriority 2020-07-31 14:50:52 -07:00
Michael Scire
5fa59ec888 kern: fix kscheduler interrupt api, adjust debug logging 2020-07-31 14:50:52 -07:00
Michael Scire
fae2daf77c kern: fix bug in up/downcasting of scoped auto objects 2020-07-31 14:50:52 -07:00
Michael Scire
8d507aa5a1 kern: implement SvcSignalToAddress, SvcWaitForAddress 2020-07-31 14:50:52 -07:00
Michael Scire
a0cc22302c kern: add KAddressArbiter::WaitIfEqual 2020-07-31 14:50:52 -07:00
Michael Scire
01a7606f95 kern: implement SvcSetHeapSize 2020-07-31 14:50:52 -07:00
Michael Scire
9c4c058307 kern: implement all device address space svcs 2020-07-31 14:50:52 -07:00
Michael Scire
9beb05da50 kern: retrieve target firmware from exosphere instead of hardcoding 2020-07-31 14:50:52 -07:00
Michael Scire
2ca6772475 kern: implement DetachDeviceAddressSpace, skeleton other das funcs in KDevicePageTable 2020-07-31 14:50:52 -07:00
Michael Scire
0d3aa13f70 kern: add infra (but not impl) for all DeviceAddressSpace svcs 2020-07-31 14:50:52 -07:00
Michael Scire
863515a3b5 kern: qualify inherited KAutoObjectWithListContainer accessor typenames 2020-07-31 14:50:52 -07:00
Michael Scire
fe035736ca kern: implement SvcGetProcessList 2020-07-31 14:50:52 -07:00
Michael Scire
cfddb75398 kern: add SvcCreateDeviceAddressSpace, SvcAttachDeviceAddressSpace 2020-07-31 14:50:52 -07:00
Michael Scire
04f325cf5a kern: implement SvcCreateInterruptEvent 2020-07-31 14:50:52 -07:00
Michael Scire
b35380a942 kern: implement SvcCreateEvent, SvcSignalEvent, SvcClearEvent, SvcResetSignal 2020-07-31 14:50:52 -07:00
Michael Scire
93be2ffcba kern: add SvcCreatePort, SvcConnectToPort 2020-07-31 14:50:52 -07:00
Michael Scire
9f79710cb7 kern: add SvcReadWriteRegister 2020-07-31 14:50:52 -07:00
Michael Scire
ef1763334b kern: patch svc tables via asm, instead of relying on compiler to be nice 2020-07-31 14:50:52 -07:00
Michael Scire
d9e9fbe3c2 kern: Implement QueryIoMapping logic for < 8.0.0 2020-07-31 14:50:52 -07:00
Michael Scire
ff022115ca kern: Support older SVC ABIs 2020-07-31 14:50:52 -07:00
Michael Scire
3d2eb8e903 Daybreak: support installing non-exfat update if only exfat firm is missing/corrupt 2020-07-27 15:42:17 -07:00
Hthh
65b42497d7 Fix building with devkitarm-rules 1.1.0 2020-07-26 22:46:01 -07:00
Michael Scire
46bd03c06d fs: correct retry loop again 2020-07-20 13:33:09 -07:00
Michael Scire
9482fafabd fs: fix retry bug in OpenContentStorageFileSystem 2020-07-20 13:18:48 -07:00
Michael Scire
762db93f4a libs: add libexosphere to targets 2020-07-20 13:12:43 -07:00
Michael Scire
5c3cd7d610 Update makefile 2020-07-17 08:25:35 -07:00
Adubbz
48a38847c2 daybreak: Added support for factory resetting (#1083)
* daybreak: ui code cleanup

(cherry picked from commit a31c246337d245abd1a827d17941f4ea48c25ca2)

* daybreak: snprintf fixes

(cherry picked from commit e62a7fcaec4552c91984ac4575d09beab046e910)

* daybreak: support resetting to factory settings

(cherry picked from commit 1c0e196eae91cfd85f63064c36cc288a0ea0363f)
2020-07-17 08:25:35 -07:00
misson20000
9382ff0939 Add stack overflow detection to fatal error code 2020-07-15 20:45:47 -07:00
hexkyz
f71ad5ac2c fusee/sept: ensure proper array initialization in exception handling 2020-07-14 18:58:19 +01:00
hexkyz
fef8a4918e sept: add missing include 2020-07-14 18:31:27 +01:00
hexkyz
72afe34cf9 fusee/sept: fix error printing 2020-07-14 18:12:31 +01:00
Michael Scire
51dd668c7c loader: fix typo 2020-07-13 17:44:20 -07:00
Michael Scire
c01753370a ams: update to know about 10.1.0 2020-07-13 17:34:48 -07:00
Michael Scire
33434e21ef kern: Prepare to commit cardinal sin 2020-07-13 17:00:51 -07:00
Michael Scire
18698bf1d3 kern: add SvcQueryIoMapping (NOTE: pre-10.x, ABI needs update) 2020-07-13 13:24:32 -07:00
Michael Scire
57867d6ced kern: fix/add InfoType_(Total/Used)(NonSystem/)MemorySize 2020-07-13 12:17:28 -07:00
Michael Scire
35c1959131 kern: assert correctness for complete class hierarchy 2020-07-13 11:11:30 -07:00
Michael Scire
a4e3eae4b6 svc/ipc: fix handle count accessors 2020-07-13 11:00:46 -07:00
Michael Scire
84d8634938 kern: fix bugs in Receive/Exchange ipc buffers 2020-07-13 10:02:01 -07:00
Michael Scire
095fc6b996 kern: fix UpdateLock perms for ipc 2020-07-12 22:22:54 -07:00
Michael Scire
bc767742f7 kern: fix unaligned map alias buffers 2020-07-12 18:53:45 -07:00
Michael Scire
e2e5a2ccc2 kern: fix bugs in MapAlias ipc mappings 2020-07-12 18:17:29 -07:00
Michael Scire
a8d4b10b17 kern: implement IPC KPageTable functionality 2020-07-12 15:42:47 -07:00
Michael Scire
3c8d8161cc kern: fix bug in ToMessageBuffer pointer transfer selection 2020-07-11 02:06:44 -07:00
Michael Scire
4a7ce9dd75 kern/KScheduler: implement special yields 2020-07-11 00:48:26 -07:00
Michael Scire
ca9327a120 kern: implement SvcSleepThread for ns > 0 2020-07-10 23:30:15 -07:00
Michael Scire
f37eda6b86 kern: implement KPageTableBase::CopyHeapToHeap(WithoutCheckDestination) 2020-07-10 21:37:56 -07:00
Michael Scire
c72bdec328 kern: add KPageTableBase::CopyMemory Linear <-> User and Linear <-> Kernel 2020-07-10 20:09:06 -07:00
Michael Scire
4a767c9082 kern: mostly implement thread exit 2020-07-10 18:39:53 -07:00
Michael Scire
c8f71007ec kern/ipc: fix bug in SendMessage 2020-07-10 16:57:11 -07:00
Michael Scire
4ff10f3ce0 kern/ipc: implement remaining KServerSession reply code 2020-07-10 16:46:55 -07:00
Michael Scire
d52655eaf1 kern: add SvcExitThread, SvcSendAsyncRequestWithUserBuffer, SvcReplyAndReceiveWithUserBuffer 2020-07-10 15:31:23 -07:00
Michael Scire
1b429918de kern/ipc: implement most of reply 2020-07-10 13:42:36 -07:00
Michael Scire
b29dc76b20 kern/ipc: implement SendReply, declare SendMessage 2020-07-10 12:49:52 -07:00
Michael Scire
4db9d95958 os: fix building with new svc defs 2020-07-10 11:57:40 -07:00
Michael Scire
2ec4ed3568 kern/ipc: add Atmosphere's mitm pid passthrough logic 2020-07-10 11:55:33 -07:00
Michael Scire
4e226b523e ipc/receive: trivially correct result return codeflow 2020-07-10 11:55:33 -07:00
Michael Scire
9fa6d12586 kern/ipc: finish Receive part of ReplyAndReceive 2020-07-10 11:55:33 -07:00
Michael Scire
804aa0e55d ipc: add MapAlias processing logic for Receive 2020-07-10 11:55:33 -07:00
Michael Scire
9d57783aa8 ipc::Reply -> implement Pointer handling logic 2020-07-10 11:55:33 -07:00
Michael Scire
a510a1138d ipc::Reply -> add raw data copy logic 2020-07-10 11:55:33 -07:00
Michael Scire
4e667bc7c1 kern: implement remaining non-KServerSession:: part of Reply/Receive 2020-07-10 11:55:33 -07:00
Michael Scire
84b1be1d58 kern: partially implement Receive half of ReplyAndReceive 2020-07-10 11:55:33 -07:00
Michael Scire
1b2203d102 kern: implement SvcSendSyncRequest(WithUserBuffer) 2020-07-10 11:55:33 -07:00
Michael Scire
4f12449acf kern: implement SvcArbitrateLock, SvcArbitrateUnlock 2020-07-10 11:55:33 -07:00
Michael Scire
f4fd4cbbb2 kern: skeleton SvcReplyAndReceive 2020-07-10 11:55:33 -07:00
Michael Scire
be98aaa185 kern: partially implement SvcSignalProcessWideKey 2020-07-10 11:55:33 -07:00
Michael Scire
7f4c6ae9e7 kern: implement SvcCreateThread, SvcStartThread 2020-07-10 11:55:33 -07:00
Michael Scire
9503aae522 kern: implement SvcMapMemory 2020-07-10 11:55:33 -07:00
Michael Scire
78da7422ae kern: implement SvcAcceptSession 2020-07-10 11:55:33 -07:00
Michael Scire
f52232f0f2 kern: implement SvcWaitSynchronization 2020-07-10 11:55:33 -07:00
Michael Scire
16c9c53a4a kern: implement KEvent, KWritableEvent, KServerSession::OnClientClosed 2020-07-10 11:55:33 -07:00
Michael Scire
d0d8914f28 kern: implement SvcCloseHandle 2020-07-10 11:55:33 -07:00
Michael Scire
7400a8ff68 kern: SvcConnectToNamedPort 2020-07-10 11:55:33 -07:00
Michael Scire
a2eb93fde8 kern: svcOutputDebugString, svcGetThreadPriority, svcGetThreadId 2020-07-10 11:55:33 -07:00
Michael Scire
1a0696f8a3 kern: implement SvcUnmapMemory, more of SvcGetInfo 2020-07-10 11:55:33 -07:00
Michael Scire
faad5609b9 ncm: safer access patterns for FirmwareVariationInfo 2020-07-10 11:49:44 -07:00
Michael Scire
ad551c3b55 ncm: loosen FirmwareVariation restrictions. 2020-07-10 11:46:53 -07:00
Adubbz
c2408395d8 daybreak: address nitpicks (#1081)
* daybreak: address nitpicks

* daybreak: append / to paths

* daybreak: more label tweaks

* daybreak: even more label changes
2020-07-10 06:44:32 -07:00
Adubbz
084dd3232e daybreak: various ux improvements (#1080) 2020-07-09 04:33:52 -07:00
VolcaEM
8d6e076b77 ncm: Mark two variables as const (#1078)
ncm: Mark two variables as const
2020-07-08 21:48:41 -07:00
Michael Scire
9bd6916646 ams: bump version to 0.14.0, add emummc info configitem 2020-07-08 17:36:52 -07:00
Michael Scire
f168542931 ams: distribute daybreak in release zips 2020-07-08 17:11:52 -07:00
Michael Scire
852c039f70 ncm: rights ids were added in 2.0.0 2020-07-08 16:02:47 -07:00
Michael Scire
bffd553b80 sf: correct deprecated spl interface definition 2020-07-08 15:42:15 -07:00
Michael Scire
2d9f5b6942 sf: support service objects which must themselves be shared pointers 2020-07-08 15:07:40 -07:00
Michael Scire
aa2d1e15ab exo: integrate multiple PRs' split_program changes 2020-07-07 20:28:42 -07:00
Adubbz
0cac10a2f0 daybreak: sort folders alphabetically and only display success message on success (#1075)
(cherry picked from commit f6893b1fff4219d81a6ecc87361fb383096fc990)
2020-07-07 20:06:21 -07:00
Michael Scire
499f29d2f0 ncm: make *ActivateContentMetaDatabase play nice with 1.0.0 2020-07-07 20:00:51 -07:00
Michael Scire
9efca346d9 docs: update roadmap 2020-07-07 18:15:06 -07:00
SciresM
9fde97cfdd sf: Change interface definition methodology (#1074)
* sf: Begin experimenting with new interface declaration format

* sf: convert fs interfaces to new format

* sf: finish conversion of libstrat to new definitions

* sf: convert loader to new format

* sf: convert spl to new format

* sf: update ncm for new format

* sf: convert pm to new format

* sf: convert ro/sm to new format

* sf: update fatal for new format

* sf: support building dmnt under new scheme

* sf: update ams.mitm for new format

* sf: correct invocation def for pointer holder

* fs: correct 10.x+ user bindings for Get*SpaceSize
2020-07-07 17:07:23 -07:00
Adubbz
94eb2195d3 Added Daybreak, a system updater homebrew (#1073)
* Implemented a system updater homebrew (titled Daybreak)

* git subrepo pull ./troposphere/daybreak/nanovg

subrepo:
  subdir:   "troposphere/daybreak/nanovg"
  merged:   "c197ba2f"
upstream:
  origin:   "https://github.com/Adubbz/nanovg-deko.git"
  branch:   "master"
  commit:   "c197ba2f"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???" (+1 squashed commits)

Squashed commits:

[232dc943] git subrepo clone https://github.com/Adubbz/nanovg-deko.git troposphere/daybreak/nanovg

subrepo:
  subdir:   "troposphere/daybreak/nanovg"
  merged:   "52bb784b"
upstream:
  origin:   "https://github.com/Adubbz/nanovg-deko.git"
  branch:   "master"
  commit:   "52bb784b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"

* daybreak: switch to using hiddbg for home blocking (+1 squashed commits)

Squashed commits:

[4bfc7b0d] daybreak: block the home button during installation
2020-07-07 17:07:00 -07:00
Michael Scire
b08ccd7341 exo: fixes, now tested working on mariko hardware 2020-07-02 14:06:42 -07:00
Michael Scire
0a53c74aad libstrat: fix bugs/compiler warnings 2020-07-02 14:02:50 -07:00
Michael Scire
70e67da1e1 fs: use access_log for other user fs/dir/file bindings 2020-07-02 14:02:50 -07:00
Michael Scire
e2b17086d4 fs: implement AccessLog, enable for File operations 2020-07-02 14:02:50 -07:00
Michael Scire
3fe7700e5c docs: update roadmap 2020-06-29 07:05:02 -07:00
Michael Scire
828b170aac exo: add mariko spare reg write during setup 2020-06-29 05:40:09 -07:00
Michael Scire
1084817d84 exo: kernel saves dbg* registers 2020-06-29 05:14:49 -07:00
Michael Scire
e16b87c843 exo: implement mariko fuse driver 2020-06-29 04:40:59 -07:00
Michael Scire
2a5d1572e1 libstrat: correct firmware comparison in meta database builder 2020-06-29 04:40:01 -07:00
Michael Scire
f7f284e5c0 exo: add note to mariko keygen for future sciresm 2020-06-28 21:14:32 -07:00
Michael Scire
bf92daf055 exo: implement remaining SE changes for mariko support 2020-06-28 21:11:29 -07:00
Michael Scire
5cb9fa510e exo: implement mariko se/tzram context save 2020-06-28 20:32:45 -07:00
Michael Scire
46c460e235 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "89f8944f"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "89f8944f"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-06-28 19:41:42 -07:00
Michael Scire
29f1eb8070 libstrat: fix dependencies for pre-compiled header 2020-06-28 19:40:56 -07:00
Michael Scire
9229696308 docs: update roadmap 2020-06-28 19:33:04 -07:00
Michael Scire
1473adf5c4 fusee/exo: correct device key management for newer consoles (closes #1053) 2020-06-28 05:39:25 -07:00
Michael Scire
a5447dd72d fs: more IndirectStorage::OperatePerEntry updates/fixes 2020-06-28 02:52:02 -07:00
Michael Scire
ecbd986529 sysupdater: minor api fixes (now verified working on hardware) 2020-06-28 01:46:51 -07:00
Michael Scire
73a6aeed15 sysupdater: implement (untested) rest of the api 2020-06-28 01:46:51 -07:00
Michael Scire
f223c27bb0 sysupdater: Add ValidateUpdate, begin implementing Async logic 2020-06-28 01:46:51 -07:00
Michael Scire
1bc271bab1 sysupdater: don't do unnecessary work when parsing update 2020-06-28 01:46:51 -07:00
Michael Scire
3324dd52ef sysupdater: make GetUpdateInformation work on hardware. 2020-06-28 01:46:51 -07:00
Michael Scire
a6218ed814 sysupdater: implement content meta mounting 2020-06-28 01:46:51 -07:00
Michael Scire
28a6bb713c sysupdater: begin implementing api 2020-06-28 01:46:51 -07:00
hexkyz
fdc7ef62f7 fusee: handle case where saving a fatal report fails (thanks @HookedBehemoth) 2020-06-26 18:36:30 +01:00
1146 changed files with 95256 additions and 17491 deletions

3
.gitignore vendored
View File

@@ -38,6 +38,9 @@
*.x86_64
*.hex
# Deko3d shaders
*.dksh
# Switch Executables
*.nso
*.nro

View File

@@ -64,13 +64,14 @@ dist-no-debug: all
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000003C
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000042
mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors
mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates
mkdir -p atmosphere-$(AMSVER)/atmosphere/config
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.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-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/sept/payload.bin
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
@@ -91,14 +92,20 @@ dist-no-debug: all
cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036/exefs.nsp
cp stratosphere/ro/ro.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/exefs.nsp
cp stratosphere/jpegdec/jpegdec.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000003C/exefs.nsp
cp stratosphere/pgl/pgl.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000042/exefs.nsp
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/flags
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/flags/boot2.flag
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags
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/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
cd atmosphere-$(AMSVER); zip -r ../atmosphere-EXPERIMENTAL-$(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)/sept/payload.bin
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
rm -r atmosphere-$(AMSVER)
mkdir out
mv atmosphere-EXPERIMENTAL-$(AMSVER).zip out/atmosphere-EXPERIMENTAL-$(AMSVER).zip
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
@@ -117,7 +124,7 @@ dist: dist-no-debug
mkdir atmosphere-$(AMSVER)-debug
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
cp fusee/fusee-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
cp fusee/fusee-secondary/fusee-secondary.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
cp sept/sept-secondary/sept-secondary.elf atmosphere-$(AMSVER)-debug/sept-secondary.elf
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf
@@ -141,6 +148,8 @@ dist: dist-no-debug
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
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
rm -r atmosphere-$(AMSVER)-debug
mv atmosphere-$(AMSVER)-debug.zip out/atmosphere-$(AMSVER)-debug.zip

View File

@@ -9,4 +9,4 @@ stage2_entrypoint = 0xF0000000
; To force-enable nogc, add nogc = 1
; To force-disable nogc, add nogc = 0
; To opt in to using Atmosphere's NCM reimplementation, add enable_ncm = 1
; To opt out of using Atmosphere's NCM reimplementation, add disable_ncm = 1

View File

@@ -4,7 +4,7 @@ Building Atmosphère is a very straightforward process that relies almost exclus
## Dependencies
+ [devkitA64](https://devkitpro.org)
+ [devkitARM](https://devkitpro.org)
+ [Python 2 or 3](https://www.python.org) (optional)
+ [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed)
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
## Instructions

View File

@@ -1,4 +1,81 @@
# Changelog
## 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.
+ 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.
+ Beginning in this release and until it is stable and well-tested, atmosphère will distribute two zips.
+ Users who wish to opt-in to mesosphere should download and extract the "cool kids" zip ("atmosphere-EXPERIMENTAL-").
+ Users who do not wish to use mesosphere should continue using the normal zip ("atmosphere-").
+ Users may detect whether mesosphere is active in system settings.
+ When mesosphere is active, the system version string will display "M.15.0" rather than "0.15.0", and so on for future releases.
+ Crash reports and the like will contain information on whether or not the user is using mesosphere, as well.
+ There are "probably" no material user-facing benefits to using mesosphere at this time.
+ Developers may be interested in the fact that mesosphere provides many newer SVC APIs even when on lower firmware versions.
+ The primary benefit to using mesosphere is that any issues you may encounter and report to me will be fixed.
+ All users who choose to opt in to using mesosphere have my deepest gratitude.
+ **Note:** If using hekate instead of fusee-primary, you will have to wait for the next hekate release for mesosphere to function, as hekate's support has not yet been included in an official release build.
+ This will be updated in the release notes when hekate provides a new release.
+ As mentioned in previous release notes, when mesosphere is stable and well-tested, it will be enabled by default and atmosphère's version will transition to 1.0.0.
+ Having been tested sufficiently over the last half-year, Atmosphere's NCM implementation is now opt-out, rather than opt in.
+ In the unlikely event that any issues are encountered, please report them to @SciresM.
+ Users interested in opting out of using our implementation should set `stratosphere!disable_ncm = 1` in BCT.ini.
+ The NCM implementation will stop being opt-out in a future update, probably around the same time that mesosphere becomes opt-out instead of opt-in.
+ Several bugs were fixed, including:
+ Loader now sets HBL's thread priority to a higher value when loading it in applet mode.
+ This fixes an extremely-slow launch ("hang") when using applet-HBL with certain games that do not suspend while inactive (e.g. Super Mario Sunshine).
+ set.mitm now caches user language configuration much more heavily.
+ This severely reduces lag in certain games which misuse the "nn::oe::GetDesiredLanguage()" API.
+ A bug was fixed that could cause erpt to fatal when loading an official save file that had error report attachments in it.
+ General system stability improvements to enhance the user's experience.
## 0.14.4
+ Several bugs were fixed involving the official jit sysmodule added in 10.0.0.
+ A Process handle leak was fixed when JitPlugin NRRs were registered with the `ro` sysmodule.
+ This prevented processes using jit from being able to exit, causing a full system freeze.
+ The `sm` atmosphere extension to not unregister services when the server's connection is closed was special-case disabled for `jit:u`.
+ This extension is normally desirable in order to allow more concurrent processes to exist (as only 0x40 sm connections may ever be concurrently open), but official jit sysmodule relies on the behavior.
+ This would cause crashes on attempts to launch a program using jit services more than once per reboot.
+ General system stability improvements to enhance the user's experience.
## 0.14.3
+ Support was added for 10.2.0.
+ General system stability improvements to enhance the user's experience.
## 0.14.2
+ A bug was fixed that could cause a deadlock when installing mitm services.
+ Fixing this required a breaking change to the client behavior when installing a mitm service, and so custom sysmodules which use mitm will need to be re-compiled to function properly.
+ A bug was fixed that caused atmosphere sysmodules to respond incorrectly when receiving invalid messages.
+ A bug was fixed that caused fatal auto-reboot timing to work improperly.
+ Support was added to fusee for loading binaries for `mesosphere`, atmosphère's reimplementation of the Nintendo Switch kernel.
+ 0.14.2 does not include mesosphere, but those who are especially interested can build and test mesosphere themselves.
+ In the future, to enable a sufficient testing period Atmosphère releases will distribute two zips for some time.
+ One zip will use mesosphere, and the other will not.
+ This will allow users who are interested to opt-in to mesosphere usage before it has been tested to be stable.
+ When mesosphere is stable and well-tested, it will be enabled by default and Atmosphère's version will transition to 1.0.0.
+ General system stability improvements to enhance the user's experience.
## 0.14.1
+ An issue was fixed in 0.14.0 that would cause a black screen on boot when the INI1's size was not aligned to 8 bytes.
+ General system stability improvements to enhance the user's experience.
## 0.14.0
+ An API (`ams:su`) was added to allow homebrew to safely install system upgrades or downgrades.
+ This is a re-implementation of the logic that `ns` uses to install gamecard system updates.
+ Nintendo (and now atmosphère) uses an installation process that can recover no matter where a failure occurs, which should significantly improve the safety of custom system update installation.
+ Support was added to `exosphère` for running on Mariko hardware.
+ **Please note**: Atmosphère still does not support Mariko, and should not be run on Mariko yet.
+ Certain stratosphere components do not handle mariko-specific logic fully correctly yet, and may initialize or interact with hardware incorrectly.
+ This will be fixed and support will be added over the remainder of the Summer.
+ A homebrew application (`daybreak`) was added that uses the system updater API (with thanks to @Adubbz for both design and implementation).
+ `daybreak` is included with atmosphère, and functions as a safer/more accurate equivalent to e.g. ChoiDujourNX.
+ Upgrades/downgrades can be installed from a folder containing the update NCAs on the SD card.
+ Because the update logic functions identically to Nintendo's, `daybreak` will be safe to use on Mariko when the rest of atmosphère has support.
+ **Please note**: Daybreak requires that meta (.cnmt) NCAs have the correct extension `.cnmt.nca`.
+ This is because gamecard system update logic uses extension to determine whether to mount the content.
+ [Several](https://gist.github.com/HookedBehemoth/df36b5970e1c5b1b512ec7bdd9043c6e) [scripts](https://gist.github.com/antiKk/279966c27fdfd9c7fe63b4ae410f89c4) have been made by community members to automatically rename folders with incorrect extensions.
+ A bug was fixed that would cause file-based emummc to throw an error (showing a hexdump) on boot.
+ Major thanks to @hexkyz for tracking down and resolving this.
+ A number of minor issues were resolved, including:
+ fusee now prints information to the screen when an error occurs, instead of getting stuck trying to initialize the display.
+ A race condition in Horizon was worked around that could prevent boot under certain circumstances.
+ A bug was fixed that would cause atmosphère modules to open ten copies of certain filesystems instead of one.
+ This could cause object exhaustion under certain circumstances.
+ For those interested in atmosphère's future development plans, the project's [roadmap](https://github.com/Atmosphere-NX/Atmosphere/blob/ac9832c5ce7be5832f6d29f6564a9c03e7efd22f/docs/roadmap.md) was updated.
+ General system stability improvements to enhance the user's experience.
## 0.13.0
+ `exosphère`, atmosphère's secure monitor re-implementation, was completely re-written.
+ `exosphère` 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.

View File

@@ -9,7 +9,7 @@ This file is located under the `/atmosphere/config/` folder on your SD card and
Atmosphère provides its own default splashscreen which is displayed at boot time. However, this can be replaced at will.
The boot splashscreen must be a BMP file, it must be 720x1280 (1280x720 rotated 90 degrees left/counterclockwise/anti-clockwise) resolution, and be in 32-bit ARGB format. You can use image editing software such as GIMP or Photoshop to export the image in this format.
Add the following lines to BCT.ini and change the value of `custom_splash` to the actual path and filename of your boot splashscreen:
```
[stage2]
@@ -29,11 +29,11 @@ nogc = X
0 = force-disable nogc, so Atmosphère will always enable the Game Card reader.
```
### NCM opt-in
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module, but currently this is not enabled by default. If you wish to enable this reimplementation add the following line to the `stratosphere` section:
### NCM opt-out
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module. If you wish to disable this reimplementation add the following line to the `stratosphere` section:
```
[stratosphere]
enable_ncm = 1
disable_ncm = 1
```
### Logging

View File

@@ -1,15 +1,10 @@
# 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.
The following descriptions were last updated on June 15th, 2020.
## system updater api
* **Description**: A planned extension api for stratosphere (tenatively `ams:su`), this will provide an interface for homebrew to safely install system upgrades or downgrades. This will allow for much more easily transitioning safely between different versions of the operating system.
* **Development Status**: Backend/implementation completed; final stages (user-facing ipc api) to be written by SciresM.
* **Estimated Time**: June 2020
The following descriptions were last updated on July 7th, 2020.
## ams-on-mariko
* **Description**: Atmosphere cannot run as-is on Mariko hardware. A large number of changes are needed in many components. Although exosphere's rewrite laid most groundwork on the secure monitor side, there is still work to do there -- and 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.
* **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
@@ -20,7 +15,7 @@ The following descriptions were last updated on June 15th, 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 semi-active development by SciresM; temporarily on pause while the System Updater API is completed.
* **Development Status**: Under active development by SciresM.
* **Estimated Time**: Mid-to-Late 2020
## tma reimplementation
@@ -47,3 +42,21 @@ The following descriptions were last updated on June 15th, 2020.
* **Description**: General system stability improvements to enhance the user's experience.
* **Development Status**: Undergoing active development by all members of the atmosphère team.
* **Estimated Time**: June 15th.
# Completed features
The following features were previously included under the planned features section and are now complete.
Please note that this is not an exhaustive list of features present in atmosphère, and only serves to indicate what from the above has been completed.
## system updater homebrew
* **Description**: A user homebrew making use of the new system updater api, so that users can actually use the new api in practice.
* **Completion Time**: July 2020
## system updater api
* **Description**: A planned extension api for stratosphere (tenatively `ams:su`), this will provide an interface for homebrew to safely install system upgrades or downgrades. This will allow for much more easily transitioning safely between different versions of the operating system.
* **Completion Time**: June 2020
## 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.
* **Completion Time**: June 2020

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/m4xw/emuMMC
branch = exo2
commit = 06ab9b895c4264ecc14d3bf9be1260e2096f6037
parent = dccd41f6d25498c191a157123a27724203d3bc37
commit = 6a814ebbe72cf5245b863b9edea9cd3801437a12
parent = f551ca4461a79908c37307db10cd8cacf8b98f17
method = rebase
cmdver = 0.4.1

View File

@@ -47,6 +47,8 @@
#include "offsets/910_exfat.h"
#include "offsets/1000.h"
#include "offsets/1000_exfat.h"
#include "offsets/1020.h"
#include "offsets/1020_exfat.h"
#include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -104,6 +106,8 @@ DEFINE_OFFSET_STRUCT(_910);
DEFINE_OFFSET_STRUCT(_910_EXFAT);
DEFINE_OFFSET_STRUCT(_1000);
DEFINE_OFFSET_STRUCT(_1000_EXFAT);
DEFINE_OFFSET_STRUCT(_1020);
DEFINE_OFFSET_STRUCT(_1020_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) {
@@ -169,6 +173,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_1000));
case FS_VER_10_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1000_EXFAT));
case FS_VER_10_2_0:
return &(GET_OFFSET_STRUCT_NAME(_1020));
case FS_VER_10_2_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT));
default:
fatal_abort(Fatal_UnknownVersion);
}

View File

@@ -68,6 +68,9 @@ enum FS_VER
FS_VER_10_0_0,
FS_VER_10_0_0_EXFAT,
FS_VER_10_2_0,
FS_VER_10_2_0_EXFAT,
FS_VER_MAX,
};

View File

@@ -0,0 +1,58 @@
/*
* 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_1020_H__
#define __FS_1020_H__
// Accessor vtable getters
#define FS_OFFSET_1020_SDMMC_ACCESSOR_GC 0x14E0F0
#define FS_OFFSET_1020_SDMMC_ACCESSOR_SD 0x14C200
#define FS_OFFSET_1020_SDMMC_ACCESSOR_NAND 0x147080
// Hooks
#define FS_OFFSET_1020_SDMMC_WRAPPER_READ 0x1427E0
#define FS_OFFSET_1020_SDMMC_WRAPPER_WRITE 0x1428C0
#define FS_OFFSET_1020_RTLD 0x634
#define FS_OFFSET_1020_RTLD_DESTINATION 0x9C
#define FS_OFFSET_1020_CLKRST_SET_MIN_V_CLK_RATE 0x141A00
// Misc funcs
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910
#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
// Misc Data
#define FS_OFFSET_1020_SD_MUTEX 0xE273E8
#define FS_OFFSET_1020_NAND_MUTEX 0xE22DA0
#define FS_OFFSET_1020_ACTIVE_PARTITION 0xE22DE0
#define FS_OFFSET_1020_SDMMC_DAS_HANDLE 0xE0AB90
// NOPs
#define FS_OFFSET_1020_SD_DAS_INIT 0x15214C
// Nintendo Paths
#define FS_OFFSET_1020_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1020_H__

View File

@@ -0,0 +1,58 @@
/*
* 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_1020_EXFAT_H__
#define __FS_1020_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_GC 0x14E0F0
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_SD 0x14C200
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_NAND 0x147080
// Hooks
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_READ 0x1427E0
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_WRITE 0x1428C0
#define FS_OFFSET_1020_EXFAT_RTLD 0x634
#define FS_OFFSET_1020_EXFAT_RTLD_DESTINATION 0x9C
#define FS_OFFSET_1020_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x141A00
// Misc funcs
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
// Misc Data
#define FS_OFFSET_1020_EXFAT_SD_MUTEX 0xE353E8
#define FS_OFFSET_1020_EXFAT_NAND_MUTEX 0xE30DA0
#define FS_OFFSET_1020_EXFAT_ACTIVE_PARTITION 0xE30DE0
#define FS_OFFSET_1020_EXFAT_SDMMC_DAS_HANDLE 0xE18B90
// NOPs
#define FS_OFFSET_1020_EXFAT_SD_DAS_INIT 0x15214C
// Nintendo Paths
#define FS_OFFSET_1020_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1020_EXFAT_H__

View File

@@ -24,23 +24,9 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(TOPDIR)/../program
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
BINFILES := program.lz4 boot_code.lz4

View File

@@ -19,10 +19,12 @@
namespace ams::diag {
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) {
AMS_UNUSED(file, line, func, expr, value, format);
ams::secmon::loader::ErrorReboot();
}
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) {
AMS_UNUSED(file, line, func, expr, value);
ams::secmon::loader::ErrorReboot();
}

View File

@@ -25,23 +25,9 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(TOPDIR)/sc7fw \
$(TOPDIR)/rebootstub
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
BINFILES := sc7fw.bin rebootstub.bin

View File

@@ -23,23 +23,9 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -23,23 +23,9 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -90,7 +90,7 @@ namespace ams::sc7fw {
reg::ReadWrite(PMC + APBDEV_PMC_DPD_ENABLE, PMC_REG_BITS_ENUM(DPD_ENABLE_ON, ENABLE));
/* Wait forever until we're asleep. */
while (true) { /* ... */ }
AMS_INFINITE_LOOP();
}
}
@@ -102,7 +102,9 @@ namespace ams::sc7fw {
NORETURN void ExceptionHandler() {
/* Write enable to MAIN_RESET. */
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
while (true) { /* ... */ }
/* Wait forever until we're reset. */
AMS_INFINITE_LOOP();
}
}

View File

@@ -48,7 +48,12 @@ namespace ams::secmon::boot {
const auto pmc = MemoryRegionVirtualDevicePmc.GetAddress();
/* Set the physical address of the warmboot binary to scratch 1. */
reg::Write(pmc + APBDEV_PMC_SCRATCH1, static_cast<u32>(MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware.GetAddress()));
if (GetSocType() == fuse::SocType_Mariko) {
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH119, static_cast<u32>(MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware.GetAddress()));
} else /* if (GetSocType() == fuse::SocType_Erista) */ {
reg::Write(pmc + APBDEV_PMC_SCRATCH1, static_cast<u32>(MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware.GetAddress()));
}
/* Configure logging by setting bits 18-19 of scratch 20. */
reg::ReadWrite(pmc + APBDEV_PMC_SCRATCH20, REG_BITS_VALUE(18, 2, 0));
@@ -66,14 +71,76 @@ namespace ams::secmon::boot {
/* The warmboot key as a parameter. The latter is a better solution, but it would be nice to take */
/* care of it here. Perhaps we should read the number of anti-downgrade fuses burnt, and translate that */
/* to the warmboot key? To be decided during the process of implementing ams-on-mariko support. */
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH32, 0x129);
}
constinit const u8 DeviceMasterKeySourceKekSource[se::AesBlockSize] = {
0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28
};
/* This function derives the master kek and device keys using the tsec root key. */
/* NOTE: Exosphere does not use this in practice, and expects the bootloader to set up keys already. */
/* NOTE: This function is currently not implemented. If implemented, it will only be a reference implementation. */
[[maybe_unused]]
void DeriveMasterKekAndDeviceKey() {
/* TODO: Decide whether to implement this. */
void DeriveMasterKekAndDeviceKeyErista(bool is_prod) {
/* NOTE: Exosphere does not use this in practice, and expects the bootloader to set up keys already. */
/* NOTE: This function is currently not implemented. If implemented, it will only be a reference implementation. */
if constexpr (false) {
/* TODO: Consider implementing this as a reference. */
}
AMS_UNUSED(is_prod);
}
/* NOTE: These are just latest-master-kek encrypted with BEK. */
/* We can get away with only including latest because exosphere supports newer-than-expected master key in engine. */
/* TODO: Update on next change of keys. */
constinit const u8 MarikoMasterKekSourceProd[se::AesBlockSize] = {
0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82
};
constinit const u8 MarikoMasterKekSourceDev[se::AesBlockSize] = {
0xF9, 0x37, 0xCF, 0x9A, 0xBD, 0x86, 0xBB, 0xA9, 0x9C, 0x9E, 0x03, 0xC4, 0xFC, 0xBC, 0x3B, 0xCE
};
constinit const u8 MasterKeySource[se::AesBlockSize] = {
0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C
};
void DeriveMasterKekAndDeviceKeyMariko(bool is_prod) {
/* Clear all keyslots other than KEK and SBK in SE1. */
for (int i = 0; i < pkg1::AesKeySlot_Count; ++i) {
if (i != pkg1::AesKeySlot_MarikoKek && i != pkg1::AesKeySlot_SecureBoot) {
se::ClearAesKeySlot(i);
}
}
/* Clear all keyslots in SE2. */
for (int i = 0; i < pkg1::AesKeySlot_Count; ++i) {
se::ClearAesKeySlot2(i);
}
/* Derive the master kek. */
se::SetEncryptedAesKey128(pkg1::AesKeySlot_MasterKek, pkg1::AesKeySlot_MarikoKek, is_prod ? MarikoMasterKekSourceProd : MarikoMasterKekSourceDev, se::AesBlockSize);
/* Derive the device master key source kek. */
se::SetEncryptedAesKey128(pkg1::AesKeySlot_DeviceMasterKeySourceKekMariko, pkg1::AesKeySlot_SecureBoot, DeviceMasterKeySourceKekSource, se::AesBlockSize);
/* Clear the KEK, now that we're done using it. */
se::ClearAesKeySlot(pkg1::AesKeySlot_MarikoKek);
}
void DeriveMasterKekAndDeviceKey(bool is_prod) {
if (GetSocType() == fuse::SocType_Mariko) {
DeriveMasterKekAndDeviceKeyMariko(is_prod);
} else /* if (GetSocType() == fuse::SocType_Erista) */ {
DeriveMasterKekAndDeviceKeyErista(is_prod);
}
}
void DeriveMasterKey() {
if (GetSocType() == fuse::SocType_Mariko) {
se::SetEncryptedAesKey128(pkg1::AesKeySlot_Master, pkg1::AesKeySlot_MasterKek, MasterKeySource, se::AesBlockSize);
} else /* if (GetSocType() == fuse::SocType_Erista) */ {
/* Nothing to do here; erista bootloader will have derived master key already. */
}
}
void SetupRandomKey(int slot, se::KeySlotLockFlags flags) {
@@ -218,6 +285,9 @@ namespace ams::secmon::boot {
/* Get the current key generation. */
const int current_generation = secmon::GetKeyGeneration();
/* Get the kek slot. */
const int kek_slot = GetSocType() == fuse::SocType_Mariko ? pkg1::AesKeySlot_DeviceMasterKeySourceKekMariko : pkg1::AesKeySlot_DeviceMasterKeySourceKekErista;
/* Iterate for all generations. */
for (int i = 0; i < pkg1::OldDeviceMasterKeyCount; ++i) {
const int generation = pkg1::KeyGeneration_4_0_0 + i;
@@ -229,7 +299,7 @@ namespace ams::secmon::boot {
se::SetEncryptedAesKey128(pkg1::AesKeySlot_Temporary, pkg1::AesKeySlot_Temporary, is_prod ? DeviceMasterKekSourcesProd[i] : DeviceMasterKekSourcesDev[i], se::AesBlockSize);
/* Decrypt the device master key source into the work block. */
se::DecryptAes128(work_block, se::AesBlockSize, pkg1::AesKeySlot_DeviceMasterKeySourceKek, DeviceMasterKeySourceSources[i], se::AesBlockSize);
se::DecryptAes128(work_block, se::AesBlockSize, kek_slot, DeviceMasterKeySourceSources[i], se::AesBlockSize);
/* If we're decrypting the current device master key, decrypt into the keyslot. */
if (generation == current_generation) {
@@ -244,14 +314,11 @@ namespace ams::secmon::boot {
}
/* Clear and lock the Device Master Key Source Kek. */
se::ClearAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKek);
se::LockAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKek, se::KeySlotLockFlags_AllLockKek);
se::ClearAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKekMariko);
se::LockAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKekMariko, se::KeySlotLockFlags_AllLockKek);
}
void DeriveAllKeys() {
/* Determine whether we're prod. */
const bool is_prod = IsProduction();
void DeriveAllKeys(bool is_prod) {
/* Get the ephemeral work block. */
u8 * const work_block = se::GetEphemeralWorkBlock();
ON_SCOPE_EXIT { util::ClearMemory(work_block, se::AesBlockSize); };
@@ -265,6 +332,9 @@ namespace ams::secmon::boot {
/* Derive the master keys. */
DeriveAllMasterKeys(is_prod, work_block);
/* Lock the master key as a kek. */
se::LockAesKeySlot(pkg1::AesKeySlot_Master, se::KeySlotLockFlags_AllLockKek);
/* Derive the device master keys. */
DeriveAllDeviceMasterKeys(is_prod, work_block);
@@ -300,16 +370,21 @@ namespace ams::secmon::boot {
/* Initialize the rng. */
se::InitializeRandom();
/* Determine whether we're production. */
const bool is_prod = IsProduction();
/* Derive the master kek and device key. */
if constexpr (false) {
DeriveMasterKekAndDeviceKey();
}
/* NOTE: This is a no-op on erista, because fusee will have set up keys. */
DeriveMasterKekAndDeviceKey(is_prod);
/* Lock the device key as only usable as a kek. */
se::LockAesKeySlot(pkg1::AesKeySlot_Device, se::KeySlotLockFlags_AllLockKek);
/* Derive all keys. */
DeriveAllKeys();
/* Derive the master key. */
DeriveMasterKey();
/* Derive all other keys. */
DeriveAllKeys(is_prod);
}
}
@@ -333,6 +408,7 @@ namespace ams::secmon::boot {
constexpr void UnmapDramImpl(u64 *l1, u64 *l2, u64 *l3) {
/* Unmap the L1 entry corresponding to to the Dram entries. */
AMS_UNUSED(l2, l3);
InvalidateL1Entries(l1, MemoryRegionDram.GetAddress(), MemoryRegionDram.GetSize());
}
@@ -348,6 +424,9 @@ namespace ams::secmon::boot {
/* Set the security engine to Per Key Secure. */
se::SetPerKeySecure();
/* Set the security engine to Context Save Secure. */
se::SetContextSaveSecure();
/* Setup the PMC registers. */
SetupPmcRegisters();

View File

@@ -42,7 +42,7 @@ namespace ams::secmon {
i2c::SetRegisterAddress(i2c::Port_5, MemoryRegionVirtualDeviceI2c5.GetAddress());
pinmux::SetRegisterAddress(MemoryRegionVirtualDeviceApbMisc.GetAddress(), MemoryRegionVirtualDeviceGpio.GetAddress());
pmc::SetRegisterAddress(MemoryRegionVirtualDevicePmc.GetAddress());
se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress());
se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress(), MemoryRegionVirtualDeviceSecurityEngine2.GetAddress());
uart::SetRegisterAddress(MemoryRegionVirtualDeviceUart.GetAddress());
wdt::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
util::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());

View File

@@ -33,8 +33,6 @@ namespace ams::secmon {
u32 mdcr_el2;
u32 mdcr_el3;
u32 spsr_el3;
u64 dbgbvcr_el1[12];
u64 dbgwvcr_el1[ 8];
};
struct CoreContext {
@@ -61,30 +59,6 @@ namespace ams::secmon {
HW_CPU_GET_MDCR_EL2 (dr.mdcr_el2);
HW_CPU_GET_MDCR_EL3 (dr.mdcr_el3);
HW_CPU_GET_SPSR_EL3 (dr.spsr_el3);
/* Save debug breakpoints. */
HW_CPU_GET_DBGBVR0_EL1(dr.dbgbvcr_el1[ 0]);
HW_CPU_GET_DBGBCR0_EL1(dr.dbgbvcr_el1[ 1]);
HW_CPU_GET_DBGBVR1_EL1(dr.dbgbvcr_el1[ 2]);
HW_CPU_GET_DBGBCR1_EL1(dr.dbgbvcr_el1[ 3]);
HW_CPU_GET_DBGBVR2_EL1(dr.dbgbvcr_el1[ 4]);
HW_CPU_GET_DBGBCR2_EL1(dr.dbgbvcr_el1[ 5]);
HW_CPU_GET_DBGBVR3_EL1(dr.dbgbvcr_el1[ 6]);
HW_CPU_GET_DBGBCR3_EL1(dr.dbgbvcr_el1[ 7]);
HW_CPU_GET_DBGBVR4_EL1(dr.dbgbvcr_el1[ 8]);
HW_CPU_GET_DBGBCR4_EL1(dr.dbgbvcr_el1[ 9]);
HW_CPU_GET_DBGBVR5_EL1(dr.dbgbvcr_el1[10]);
HW_CPU_GET_DBGBCR5_EL1(dr.dbgbvcr_el1[11]);
/* Save debug watchpoints. */
HW_CPU_GET_DBGWVR0_EL1(dr.dbgwvcr_el1[0]);
HW_CPU_GET_DBGWCR0_EL1(dr.dbgwvcr_el1[1]);
HW_CPU_GET_DBGWVR1_EL1(dr.dbgwvcr_el1[2]);
HW_CPU_GET_DBGWCR1_EL1(dr.dbgwvcr_el1[3]);
HW_CPU_GET_DBGWVR2_EL1(dr.dbgwvcr_el1[4]);
HW_CPU_GET_DBGWCR2_EL1(dr.dbgwvcr_el1[5]);
HW_CPU_GET_DBGWVR3_EL1(dr.dbgwvcr_el1[6]);
HW_CPU_GET_DBGWCR3_EL1(dr.dbgwvcr_el1[7]);
}
void RestoreDebugRegisters(const DebugRegisters &dr) {
@@ -100,30 +74,6 @@ namespace ams::secmon {
HW_CPU_SET_MDCR_EL2 (dr.mdcr_el2);
HW_CPU_SET_MDCR_EL3 (dr.mdcr_el3);
HW_CPU_SET_SPSR_EL3 (dr.spsr_el3);
/* Restore debug breakpoints. */
HW_CPU_SET_DBGBVR0_EL1(dr.dbgbvcr_el1[ 0]);
HW_CPU_SET_DBGBCR0_EL1(dr.dbgbvcr_el1[ 1]);
HW_CPU_SET_DBGBVR1_EL1(dr.dbgbvcr_el1[ 2]);
HW_CPU_SET_DBGBCR1_EL1(dr.dbgbvcr_el1[ 3]);
HW_CPU_SET_DBGBVR2_EL1(dr.dbgbvcr_el1[ 4]);
HW_CPU_SET_DBGBCR2_EL1(dr.dbgbvcr_el1[ 5]);
HW_CPU_SET_DBGBVR3_EL1(dr.dbgbvcr_el1[ 6]);
HW_CPU_SET_DBGBCR3_EL1(dr.dbgbvcr_el1[ 7]);
HW_CPU_SET_DBGBVR4_EL1(dr.dbgbvcr_el1[ 8]);
HW_CPU_SET_DBGBCR4_EL1(dr.dbgbvcr_el1[ 9]);
HW_CPU_SET_DBGBVR5_EL1(dr.dbgbvcr_el1[10]);
HW_CPU_SET_DBGBCR5_EL1(dr.dbgbvcr_el1[11]);
/* Restore debug watchpoints. */
HW_CPU_SET_DBGWVR0_EL1(dr.dbgwvcr_el1[0]);
HW_CPU_SET_DBGWCR0_EL1(dr.dbgwvcr_el1[1]);
HW_CPU_SET_DBGWVR1_EL1(dr.dbgwvcr_el1[2]);
HW_CPU_SET_DBGWCR1_EL1(dr.dbgwvcr_el1[3]);
HW_CPU_SET_DBGWVR2_EL1(dr.dbgwvcr_el1[4]);
HW_CPU_SET_DBGWCR2_EL1(dr.dbgwvcr_el1[5]);
HW_CPU_SET_DBGWVR3_EL1(dr.dbgwvcr_el1[6]);
HW_CPU_SET_DBGWCR3_EL1(dr.dbgwvcr_el1[7]);
}
constinit CoreContext g_core_contexts[NumCores] = {};

View File

@@ -16,10 +16,24 @@
#include <exosphere.hpp>
#include "secmon_error.hpp"
namespace {
namespace ams {
constexpr bool SaveSystemStateForDebug = false;
namespace {
constexpr bool SaveSystemStateForDebug = false;
constexpr bool LogSystemStateForDebug = false;
void LogU64(u64 value) {
char buffer[2 * sizeof(value)];
for (size_t i = 0; i < sizeof(value); ++i) {
buffer[sizeof(buffer) - 1 - (2 * i) - 0] = "0123456789ABCDEF"[(value >> 0) & 0xF];
buffer[sizeof(buffer) - 1 - (2 * i) - 1] = "0123456789ABCDEF"[(value >> 4) & 0xF];
value >>= 8;
}
log::SendText(buffer, sizeof(buffer));
}
}
}
namespace ams::diag {
@@ -98,6 +112,57 @@ namespace ams::secmon {
util::WaitMicroSeconds(1000);
}
ALWAYS_INLINE void LogSystemStateForDebugErrorReboot(u64 lr, u64 sp) {
log::SendText("*** Error Reboot ***\n", 21);
log::Flush();
u64 temp_reg;
__asm__ __volatile__("mrs %0, esr_el3" : "=r"(temp_reg) :: "memory");
log::SendText("ESR_EL3: ", 9);
LogU64(temp_reg);
log::SendText("\n", 1);
log::Flush();
__asm__ __volatile__("mrs %0, elr_el3" : "=r"(temp_reg) :: "memory");
log::SendText("ELR_EL3: ", 9);
LogU64(temp_reg);
log::SendText("\n", 1);
log::Flush();
__asm__ __volatile__("mrs %0, far_el3" : "=r"(temp_reg) :: "memory");
log::SendText("FAR_EL3: ", 9);
LogU64(temp_reg);
log::SendText("\n", 1);
log::Flush();
log::SendText("LR: ", 9);
LogU64(lr);
log::SendText("\n", 1);
log::Flush();
log::SendText("SP: ", 9);
LogU64(sp);
log::SendText("\n", 1);
log::Flush();
log::SendText("Stack:\n", 7);
log::Flush();
char buf[2];
for (int i = 0; i < 0x100; ++i) {
const u8 byte = *(volatile u8 *)(sp + i);
buf[0] = "0123456789ABCDEF"[(byte >> 4) & 0xF];
buf[1] = "0123456789ABCDEF"[(byte >> 0) & 0xF];
log::SendText(buf, 2);
log::Flush();
if (util::IsAligned(i + 1, 0x10)) {
log::SendText("\n", 1);
log::Flush();
}
}
}
}
void SetError(pkg1::ErrorInfo info) {
@@ -114,6 +179,14 @@ namespace ams::secmon {
SaveSystemStateForDebugErrorReboot();
}
if constexpr (LogSystemStateForDebug) {
u64 lr, sp;
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
__asm__ __volatile__("mov %0, sp" : "=r"(sp) :: "memory");
LogSystemStateForDebugErrorReboot(lr, sp);
}
/* Lockout the security engine. */
se::Lockout();

View File

@@ -41,6 +41,7 @@ namespace ams::secmon {
constexpr void UnmapBootCodeImpl(u64 *l1, u64 *l2, u64 *l3, uintptr_t boot_code, size_t boot_code_size) {
/* Unmap the L3 entries corresponding to the boot code. */
AMS_UNUSED(l1, l2);
InvalidateL3Entries(l3, boot_code, boot_code_size);
}
@@ -95,10 +96,6 @@ namespace ams::secmon {
util::ClearMemory(reinterpret_cast<void *>(address + size / 2), size / 2);
}
bool IsPhysicalMemoryAddress(uintptr_t address) {
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
}
}
void ClearBootCodeHigh() {
@@ -129,6 +126,10 @@ namespace ams::secmon {
}
}
bool IsPhysicalMemoryAddress(uintptr_t address) {
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
}
void UnmapTzram() {
/* Get the tables. */
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();

View File

@@ -18,6 +18,7 @@
namespace ams::secmon {
bool IsPhysicalMemoryAddress(uintptr_t address);
size_t GetPhysicalMemorySize();
void UnmapTzram();

View File

@@ -51,27 +51,27 @@ namespace ams::secmon {
constinit bool g_is_cold_boot = true;
constinit const se::StickyBits ExpectedSeStickyBits = {
constinit se::StickyBits ExpectedSeStickyBits = {
.se_security = (1 << 0), /* SE_HARD_SETTING */
.tzram_security = 0,
.crypto_security_perkey = (1 << pkg1::AesKeySlot_UserEnd) - 1,
.crypto_keytable_access = {
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 0: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 1: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 2: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 3: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 4: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 5: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 6: Unused keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 7: Unused keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 8: Temp keyslot. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 9: SmcTemp keyslot. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 10: Wrap1 keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 11: Wrap2 keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 12: DMaster keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Master keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 14: Unused keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Device keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 0: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 1: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 2: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 3: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 4: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 5: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 6: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 7: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 8: Temp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
(0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 9: SmcTemp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 10: Wrap1 keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(0 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 11: Wrap2 keyslot. KEY. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 12: DMaster keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Master keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 14: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Device keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
},
.rsa_security_perkey = 0,
.rsa_keytable_access = {
@@ -139,6 +139,16 @@ namespace ams::secmon {
}
void VerifySecurityEngineStickyBits() {
/* On mariko, an extra sticky bit is set. */
if (GetSocType() == fuse::SocType_Mariko) {
ExpectedSeStickyBits.se_security |= (1 << 5);
} else /* if (GetSocType() == fuse::SocType_Erista) */ {
/* Erista does not support DST_KEYTABLE_ONLY, and so all keys will have the bit clear. */
for (size_t i = 0; i < util::size(ExpectedSeStickyBits.crypto_keytable_access); ++i) {
ExpectedSeStickyBits.crypto_keytable_access[i] &= ~(1 << 7);
}
}
if (!se::ValidateStickyBits(ExpectedSeStickyBits)) {
SetError(pkg1::ErrorInfo_InvalidSecurityEngineStickyBits);
AMS_ABORT("Invalid sticky bits");
@@ -638,7 +648,7 @@ namespace ams::secmon {
reg::Read (MC + MC_SMMU_TLB_CONFIG);
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
reg::Read (MC + MC_SMMU_TLB_CONFIG);
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
@@ -897,7 +907,7 @@ namespace ams::secmon {
reg::Write(MC + MC_SMMU_PPCS1_ASID, MC_REG_BITS_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_PPCS1_ASID_PPCS1_ASID, BpmpAsid));
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
reg::Read (MC + MC_SMMU_TLB_CONFIG);
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
@@ -938,12 +948,16 @@ namespace ams::secmon {
return reg::Read(MC + MC_SECURITY_CFG3) == 0;
}
void SetupLogForBoot() {
log::Initialize();
log::SendText("OHAYO\n", 6);
log::Flush();
}
void LogExitLp0() {
/* NOTE: Nintendo only does this on dev, but we will always do it. */
if (true /* !pkg1::IsProduction() */) {
log::Initialize();
log::SendText("OHAYO\n", 6);
log::Flush();
SetupLogForBoot();
}
}
@@ -969,7 +983,7 @@ namespace ams::secmon {
InitializeConfigurationContext();
/* Initialize uart for logging. */
log::Initialize();
SetupLogForBoot();
/* Initialize the security engine. */
se::Initialize();
@@ -1017,12 +1031,16 @@ namespace ams::secmon {
/* Overwrite keys that we want to be random with random contents. */
se::InitializeRandom();
se::ConfigureAutomaticContextSave();
se::SetRandomKey(pkg1::AesKeySlot_Temporary);
se::GenerateSrk();
se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek);
/* Initialize pmc secure scratch. */
pmc::InitializeRandomScratch();
if (GetSocType() == fuse::SocType_Erista) {
pmc::InitializeRandomScratch();
}
pmc::LockSecureRegister(pmc::SecureRegister_Srk);
/* Setup secure registers. */
SetupSecureRegisters();

View File

@@ -264,6 +264,13 @@ namespace ams::secmon {
{
reg::Write(AHB_ARBC(AHB_GIZMO_TZRAM), (1u << 7));
}
/* NOTE: This is Mariko only in Nintendo's firmware. */
/* Still, it seems to have no adverse effects on Erista... */
/* TODO: Find a way to get access to SocType this early (fuse driver isn't alive yet), only write on mariko? */
{
reg::ReadWrite(AHB_ARBC(AHB_AHB_SPARE_REG), AHB_REG_BITS_VALUE(AHB_SPARE_REG_AHB_SPARE_REG, 0xE0000));
}
}
void SetupSocDmaControllersCpuMemoryControllersEnableMmuWarmboot() {

View File

@@ -22,7 +22,7 @@ SetRegisterAllowed(MC_SMMU_CONFIG); /* 0x010 */
SetRegisterAllowed(MC_SMMU_PTB_ASID); /* 0x01C */
SetRegisterAllowed(MC_SMMU_PTB_DATA); /* 0x020 */
SetRegisterAllowed(MC_SMMU_TLB_FLUSH); /* 0x030 */
SetRegisterAllowed(MC_SMMU_PTC_FLUSH); /* 0x034 */
SetRegisterAllowed(MC_SMMU_PTC_FLUSH_0); /* 0x034 */
SetRegisterAllowed(MC_EMEM_CFG); /* 0x050 */
SetRegisterAllowed(MC_EMEM_ADR_CFG); /* 0x054 */
SetRegisterAllowed(MC_EMEM_ARB_CFG); /* 0x090 */
@@ -53,7 +53,7 @@ SetRegisterAllowed(MC_SMMU_DCB_ASID); /* 0x244 */
SetRegisterAllowed(MC_SMMU_HC_ASID); /* 0x250 */
SetRegisterAllowed(MC_SMMU_HDA_ASID); /* 0x254 */
SetRegisterAllowed(MC_SMMU_ISP2_ASID); /* 0x258 */
SetRegisterAllowed(MC_SMMU_NVENC_ASID); /* 0x264 */
SetRegisterAllowed(MC_SMMU_MSENC_NVENC_ASID); /* 0x264 */
SetRegisterAllowed(MC_SMMU_NV_ASID); /* 0x268 */
SetRegisterAllowed(MC_SMMU_NV2_ASID); /* 0x26C */
SetRegisterAllowed(MC_SMMU_PPCS_ASID); /* 0x270 */

View File

@@ -257,7 +257,7 @@ namespace ams::secmon::smc {
}
int PrepareDeviceMasterKey(int generation) {
if (generation == pkg1::KeyGeneration_1_0_0) {
if (generation == pkg1::KeyGeneration_1_0_0 && GetSocType() == fuse::SocType_Erista) {
return pkg1::AesKeySlot_Device;
}
if (generation == GetKeyGeneration()) {

View File

@@ -141,6 +141,9 @@ namespace ams::secmon::smc {
{ 0xC3000006, Restriction_Normal, SmcShowError },
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
{ 0xC3000008, Restriction_Normal, SmcReadWriteRegister },
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
{ 0xC3000409, Restriction_Normal, SmcSetConfig },
};
constinit HandlerInfo g_ams_handlers[] = {

View File

@@ -15,6 +15,7 @@
*/
#include <exosphere.hpp>
#include "../secmon_error.hpp"
#include "../secmon_map.hpp"
#include "../secmon_misc.hpp"
#include "../secmon_page_mapper.hpp"
#include "../secmon_user_power_management.hpp"
@@ -157,6 +158,8 @@ namespace ams::secmon::smc {
return value.value;
}
constinit u64 g_payload_address = 0;
SmcResult GetConfig(SmcArguments &args, bool kern) {
switch (static_cast<ConfigItem>(args.r[1])) {
case ConfigItem::DisableProgramVerification:
@@ -262,6 +265,19 @@ namespace ams::secmon::smc {
/* Get whether this unit should allow writing to the calibration partition. */
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() || GetSecmonConfiguration().AllowWritingToCalibrationBinarySysmmc());
break;
case ConfigItem::ExosphereEmummcType:
/* Get what kind of emummc this unit has active. */
/* NOTE: This may return values other than 1 in the future. */
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0);
break;
case ConfigItem::ExospherePayloadAddress:
/* Gets the physical address of the reboot payload buffer, if one exists. */
if (g_payload_address != 0) {
args.r[1] = g_payload_address;
} else {
return SmcResult::NotInitialized;
}
break;
default:
return SmcResult::InvalidArgument;
}
@@ -304,6 +320,17 @@ namespace ams::secmon::smc {
return SmcResult::NotImplemented;
}
break;
case ConfigItem::ExospherePayloadAddress:
if (g_payload_address == 0) {
if (secmon::IsPhysicalMemoryAddress(args.r[2])) {
g_payload_address = args.r[2];
} else {
return SmcResult::InvalidArgument;
}
} else {
return SmcResult::Busy;
}
break;
default:
return SmcResult::InvalidArgument;
}

View File

@@ -47,6 +47,8 @@ namespace ams::secmon::smc {
ExosphereHasRcmBugPatch = 65004,
ExosphereBlankProdInfo = 65005,
ExosphereAllowCalWrites = 65006,
ExosphereEmummcType = 65007,
ExospherePayloadAddress = 65008,
};
SmcResult SmcGetConfigUser(SmcArguments &args);

View File

@@ -69,6 +69,7 @@ namespace ams::secmon::smc {
SmcResult SmcWriteAddress(SmcArguments &args) {
/* NOTE: This smc was deprecated in Atmosphère 0.13.0. */
AMS_UNUSED(args);
return SmcResult::NotImplemented;
}

View File

@@ -325,7 +325,11 @@ namespace ams::secmon::smc {
}
void SaveSecureContextForMariko() {
/* TODO: Implement this when adding ams-on-mariko support. */
/* Save security engine context to TZRAM SE carveout (inaccessible to cpu). */
se::SaveContextAutomatic();
/* Save TZRAM to shadow-TZRAM in always-on power domain. */
se::SaveTzramAutomatic();
}
void SaveSecureContext() {
@@ -488,6 +492,8 @@ namespace ams::secmon::smc {
}
SmcResult SmcPowerOffCpu(SmcArguments &args) {
AMS_UNUSED(args);
/* Get the current core id. */
const auto core_id = hw::GetCurrentCoreId();

View File

@@ -155,10 +155,27 @@ namespace ams::secmon::smc {
/* Find the access table. */
const AccessTableEntry * const entry = GetAccessTableEntry(address);
/* If we have a table, perform the write. */
/* Translate our entry into an address to access. */
uintptr_t virtual_address = 0;
if (entry != nullptr) {
/* Get the address to read or write. */
const uintptr_t virtual_address = entry->virtual_address + (address - entry->address);
virtual_address = entry->virtual_address + (address - entry->address);
} else {
/* For no clearly discernable reason, SmcReadWriteRegister returns success despite not doing the read/write */
/* when accessing the SMMU controls for the BPMP and for APB-DMA. */
/* This is "probably" to fuck with hackers who got access to the SMC and are trying to get control of the */
/* BPMP to exploit jamais vu, deja vu, or other related DMA/wake-from-sleep vulnerabilities. */
constexpr uintptr_t MC = MemoryRegionPhysicalDeviceMemoryController.GetAddress();
SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument);
/* For backwards compatibility, we'll allow access to these devices on 1.0.0. */
if (GetTargetFirmware() < TargetFirmware_2_0_0) {
virtual_address = MemoryRegionVirtualDeviceMemoryController.GetAddress() + (address - MC);
}
}
/* Perform the read or write, if we should. */
if (virtual_address != 0) {
u32 out = 0;
if (mask != ~static_cast<u32>(0)) {
@@ -169,13 +186,6 @@ namespace ams::secmon::smc {
}
args.r[1] = out;
} else {
/* For no clearly discernable reason, SmcReadWriteRegister returns success despite not doing the read/write */
/* when accessing the SMMU controls for the BPMP and for APB-DMA. */
/* This is "probably" to fuck with hackers who got access to the SMC and are trying to get control of the */
/* BPMP to exploit jamais vu, deja vu, or other related DMA/wake-from-sleep vulnerabilities. */
constexpr uintptr_t MC = MemoryRegionPhysicalDeviceMemoryController.GetAddress();
SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument);
}
return SmcResult::Success;

View File

@@ -75,6 +75,7 @@ namespace ams::secmon::smc {
u8 msg[se::RsaSize];
public:
void Set(const void *m, size_t m_size) {
AMS_UNUSED(m_size);
std::memcpy(this->msg, m, sizeof(this->msg));
}

View File

@@ -3,7 +3,11 @@ import sys, lz4
from struct import unpack as up
def lz4_compress(data):
return lz4.block.compress(data, 'high_compression', store_size=False)
try:
import lz4.block as block
except ImportError:
block = lz4.LZ4_compress
return block.compress(data, 'high_compression', store_size=False)
def split_binary(data):
A, B, START, BOOT_CODE_START, BOOT_CODE_END, PROGRAM_START, C, D = up('<QQQQQQQQ', data[:0x40])
@@ -19,7 +23,7 @@ def split_binary(data):
def main(argc, argv):
if argc != 3:
print 'Usage: %s in outdir' % argv[0]
print('Usage: %s in outdir' % argv[0])
return 1
with open(argv[1], 'rb') as f:
data = f.read()
@@ -30,4 +34,4 @@ def main(argc, argv):
return 0
if __name__ == '__main__':
sys.exit(main(len(sys.argv), sys.argv))
sys.exit(main(len(sys.argv), sys.argv))

View File

@@ -0,0 +1,108 @@
#---------------------------------------------------------------------------------
# Define the atmosphere board and cpu
#---------------------------------------------------------------------------------
export ATMOSPHERE_BOARD := nx-hac-001
export ATMOSPHERE_CPU := arm7tdmi
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
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 ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(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)
#---------------------------------------------------------------------------------
# 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)/lib -L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD) check_libexo
$(BUILD): check_libexo
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
check_libexo:
@$(MAKE) --no-print-directory -C ../../libraries/libexosphere arm
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf *.lz4
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin
$(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES) ../../../libraries/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/libexosphere.a
%.elf:
@echo linking $(notdir $@)
$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
$(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,194 @@
OUTPUT_ARCH(arm)
ENTRY(_ZN3ams10sdmmc_test5StartEv)
MEMORY
{
NULL : ORIGIN = 0, LENGTH = 4K
test_fw : ORIGIN = 0x40010000, LENGTH = 32K
}
SECTIONS
{
/* =========== CODE section =========== */
PROVIDE(__start__ = ORIGIN(test_fw));
. = __start__;
__code_start = . ;
.crt0 :
{
KEEP (*(.crt0 .crt0.*))
. = ALIGN(8);
} >test_fw
.vectors :
{
KEEP (*(.vectors .vectors.*))
. = ALIGN(8);
} >test_fw
.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);
} >test_fw
.init :
{
KEEP( *(.init) )
. = ALIGN(8);
} >test_fw
.plt :
{
*(.plt)
*(.iplt)
. = ALIGN(8);
} >test_fw
.fini :
{
KEEP( *(.fini) )
. = ALIGN(8);
} >test_fw
/* =========== RODATA section =========== */
. = ALIGN(8);
__rodata_start = . ;
.rodata :
{
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(8);
} >test_fw
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >test_fw
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >test_fw
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >test_fw
.hash : { *(.hash) } >test_fw
/* =========== DATA section =========== */
. = ALIGN(8);
__data_start = . ;
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >test_fw
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >test_fw
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >test_fw
.preinit_array ALIGN(8) :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
} >test_fw
.init_array ALIGN(8) :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
} >test_fw
.fini_array ALIGN(8) :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
} >test_fw
.ctors ALIGN(8) :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >test_fw
.dtors ALIGN(8) :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >test_fw
__got_start__ = .;
.got : { *(.got) *(.igot) } >test_fw
.got.plt : { *(.got.plt) *(.igot.plt) } >test_fw
__got_end__ = .;
.data ALIGN(8) :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
} >test_fw
__bss_start__ = .;
.bss ALIGN(8) :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(16);
} >test_fw
__bss_end__ = .;
__end__ = ABSOLUTE(.) ;
__total_size__ = (__end__ - __start__);
__stack_top__ = 0x40031000;
__stack_bottom__ = 0x40030000;
/* ==================
==== 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 /sdmmc_test.ld) --gc-sections --nmagic -nostdlib -nostartfiles
*startfile:
crti%O%s crtbegin%O%s

View File

@@ -0,0 +1,146 @@
/*
* 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::sdmmc_test {
namespace {
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
constexpr inline auto Port = sdmmc::Port_SdCard0;
alignas(8) constinit u8 g_sd_work_buffer[sdmmc::SdCardWorkBufferSize];
constexpr inline u32 SectorIndex = 0;
constexpr inline u32 SectorCount = 2;
NORETURN void PmcMainReboot() {
/* Write enable to MAIN_RESET. */
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
/* Wait forever until we're reset. */
AMS_INFINITE_LOOP();
}
void CheckResult(const Result result) {
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
if (R_FAILED(result)) {
DEBUG[1] = result.GetValue();
PmcMainReboot();
}
}
}
void Main() {
/* Perform butchered hwinit. */
/* TODO: replace with simpler, non-C logic. */
/* nx_hwinit(); */
/* Clear output buffer for debug. */
std::memset((void *)0x40038000, 0xAA, 0x400);
/* Normally, these pins get configured by boot sysmodule during initial pinmux config. */
/* However, they're required to access the SD card. */
{
const uintptr_t apb_misc = dd::QueryIoMapping(0x70000000, 0x4000);
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CLK, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN),
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CLK_PM, SDMMC1));
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CMD, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CMD_PM, SDMMC1));
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT3, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT3_PM, SDMMC1));
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT2, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT2_PM, SDMMC1));
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT1, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT1_PM, SDMMC1));
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT0, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, SDMMC1));
reg::ReadWrite(apb_misc + PINMUX_AUX_DMIC3_CLK, PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE),
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, RSVD2));
}
/* Debug signaler. */
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
DEBUG[0] = 0;
DEBUG[1] = 0xAAAAAAAA;
/* Initialize sdmmc library. */
sdmmc::Initialize(Port);
DEBUG[0] = 1;
sdmmc::SetSdCardWorkBuffer(Port, g_sd_work_buffer, sizeof(g_sd_work_buffer));
DEBUG[0] = 2;
Result result = sdmmc::Activate(Port);
DEBUG[0] = 3;
CheckResult(result);
/* Read the first two sectors from disk. */
void * const sector_dst = reinterpret_cast<void *>(0x40038000);
result = sdmmc::Read(sector_dst, SectorCount * sdmmc::SectorSize, Port, SectorIndex, SectorCount);
DEBUG[0] = 4;
CheckResult(result);
/* Get the connection status. */
sdmmc::SpeedMode speed_mode;
sdmmc::BusWidth bus_width;
result = sdmmc::CheckSdCardConnection(std::addressof(speed_mode), std::addressof(bus_width), Port);
/* Save status for debug. */
DEBUG[0] = 5;
DEBUG[1] = result.GetValue();
DEBUG[2] = static_cast<u32>(speed_mode);
DEBUG[3] = static_cast<u32>(bus_width);
/* Perform a reboot. */
PmcMainReboot();
}
NORETURN void ExceptionHandler() {
PmcMainReboot();
}
}
namespace ams::diag {
void AbortImpl() {
sdmmc_test::ExceptionHandler();
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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._ZN3ams10sdmmc_test5StartEv, "ax", %progbits
.align 3
.global _ZN3ams10sdmmc_test5StartEv
_ZN3ams10sdmmc_test5StartEv:
/* Switch to system mode, mask all interrupts, clear all flags */
msr cpsr_cxsf, #0xDF
/* Set the stack pointer. */
ldr sp, =__stack_top__
/* Set our link register to the exception handler. */
ldr lr, =_ZN3ams10sdmmc_test16ExceptionHandlerEv
/* Call init array functions. */
bl __libc_init_array
/* Invoke main. */
b _ZN3ams10sdmmc_test4MainEv
/* Infinite loop. */
2: b 2b

View File

@@ -23,23 +23,9 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -90,7 +90,9 @@ namespace ams::warmboot {
NORETURN void ExceptionHandler() {
/* Write enable to MAIN_RESET. */
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
while (true) { /* ... */ }
/* Wait forever until we're reset. */
AMS_INFINITE_LOOP();
}
}

View File

@@ -30,7 +30,7 @@ _ZN3ams8warmboot5StartEv:
/* Invoke main. */
ldr r0, =_metadata
bl _ZN3ams8warmboot4MainEPKNS0_8MetadataE
b _ZN3ams8warmboot4MainEPKNS0_8MetadataE
/* Infinite loop. */
1: b 1b

View File

@@ -17,7 +17,7 @@
#ifndef FUSEE_LOG_H
#define FUSEE_LOG_H
#define PRINT_MESSAGE_MAX_LENGTH 512
#define PRINT_MESSAGE_MAX_LENGTH 1024
#include <stdarg.h>

View File

@@ -17,17 +17,26 @@
#include <stdbool.h>
#include <stdarg.h>
#include "utils.h"
#include "display/video_fb.h"
#include "lib/log.h"
__attribute__ ((noreturn)) void generic_panic(void) {
print(SCREEN_LOG_LEVEL_ERROR, "Panic raised!");
while (true) {
/* Lock. */
}
}
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
/* Forcefully initialize the screen if logging is disabled. */
if (log_get_log_level() == SCREEN_LOG_LEVEL_NONE) {
/* Zero-fill the framebuffer and register it as printk provider. */
video_init((void *)0xC0000000);
/* Override the global logging level. */
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
}
/* Display fatal error. */
va_list args;
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
va_start(args, fmt);

View File

@@ -19,9 +19,10 @@
#include "exception_handlers.h"
#include "utils.h"
#include "lib/log.h"
#include "lib/vsprintf.h"
#define CODE_DUMP_SIZE 0x30
#define STACK_DUMP_SIZE 0x60
#define STACK_DUMP_SIZE 0x30
extern const uint32_t exception_handler_table[];
@@ -34,6 +35,40 @@ static const char *register_names[] = {
"SP", "LR", "PC", "CPSR",
};
/* Adapted from https://gist.github.com/ccbrown/9722406 */
static void hexdump(const void* data, size_t size, uintptr_t addrbase, char* strbuf) {
const uint8_t *d = (const uint8_t *)data;
char ascii[17] = {0};
ascii[16] = '\0';
for (size_t i = 0; i < size; i++) {
if (i % 16 == 0) {
strbuf += sprintf(strbuf, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
}
strbuf += sprintf(strbuf, "%02X ", d[i]);
if (d[i] >= ' ' && d[i] <= '~') {
ascii[i % 16] = d[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
strbuf += sprintf(strbuf, " ");
if ((i+1) % 16 == 0) {
strbuf += sprintf(strbuf, "| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
strbuf += sprintf(strbuf, " ");
}
for (size_t j = (i+1) % 16; j < 16; j++) {
strbuf += sprintf(strbuf, " ");
}
strbuf += sprintf(strbuf, "| %s \n", ascii);
}
}
}
}
void setup_exception_handlers(void) {
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
for (int i = 0; i < 8; i++) {
@@ -44,38 +79,40 @@ void setup_exception_handlers(void) {
}
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
uint8_t code_dump[CODE_DUMP_SIZE];
uint8_t stack_dump[STACK_DUMP_SIZE];
size_t code_dump_size;
size_t stack_dump_size;
char exception_log[0x400] = {0};
uint8_t code_dump[CODE_DUMP_SIZE] = {0};
uint8_t stack_dump[STACK_DUMP_SIZE] = {0};
size_t code_dump_size = 0;
size_t stack_dump_size = 0;
uint32_t pc = registers[15];
uint32_t cpsr = registers[16];
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
sprintf(exception_log, "An exception occured!\n");
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE);
stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
exception_names[exception_type]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n");
sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]);
sprintf(exception_log + strlen(exception_log), "\nRegisters:\n");
/* Print r0 to pc. */
for (int i = 0; i < 16; i += 2) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
register_names[i], registers[i], register_names[i+1], registers[i+1]);
}
/* Print cpsr. */
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
fatal_error("An exception occured!\n");
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
/* Print code and stack regions. */
sprintf(exception_log + strlen(exception_log), "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\n");
/* Throw fatal error with the full exception log. */
fatal_error(exception_log);
}

View File

@@ -17,7 +17,7 @@
#ifndef FUSEE_LOG_H
#define FUSEE_LOG_H
#define PRINT_MESSAGE_MAX_LENGTH 512
#define PRINT_MESSAGE_MAX_LENGTH 1024
#include <stdarg.h>

View File

@@ -24,6 +24,9 @@
#include "lib/log.h"
#include "display/video_fb.h"
#define PROGRAM_ID_AMS_MITM 0x010041544D530000ull
#define PROGRAM_ID_BOOT 0x0100000000000005ull
static uint32_t g_panic_code = 0;
static const char *get_error_desc_str(uint32_t error_desc) {
@@ -42,6 +45,10 @@ static const char *get_error_desc_str(uint32_t error_desc) {
return "SError";
case 0x301:
return "Bad SVC";
case 0xF00:
return "Kernel Panic";
case 0xFFD:
return "Stack overflow";
case 0xFFE:
return "std::abort() called";
default:
@@ -49,6 +56,61 @@ static const char *get_error_desc_str(uint32_t error_desc) {
}
}
static void _try_suggest_fix(const atmosphere_fatal_error_ctx *ctx) {
/* Try to recognize certain errors automatically, and suggest fixes for them. */
const char *suggestion = NULL;
if (ctx->error_desc == 0xFFE) {
if (ctx->program_id == PROGRAM_ID_AMS_MITM) {
/* When a user has archive bits set improperly, attempting to create an automatic backup will fail */
/* to create the file path with error 0x202 (fs::ResultPathNotFound()) */
if (ctx->gprs[0] == 0x202) {
/* 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 = strlen(automatic_backups_prefix);
for (size_t i = 0; i + prefix_len < ctx->stack_dump_size; ++i) {
if (memcmp(&ctx->stack_dump[i], automatic_backups_prefix, prefix_len) == 0) {
suggestion = "The atmosphere directory may improperly have archive\n"
"bits set. Please try running an archive bit fixer tool\n"
"(for example, the one in Hekate).\n";
break;
}
}
} else if (ctx->gprs[0] == 0x249A02) { /* fs::ResultResultExFatUnavailable() */
/* 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 (ctx->program_id == PROGRAM_ID_BOOT) {
/* 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 (ctx->gprs[i] == 0xF201) {
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 (ctx->error_desc == 0xF00) { /* Kernel Panic */
suggestion = "Please contact SciresM#0524 on Discord, or create an issue\n"
"on the Atmosphere GitHub issue tracker. Thank you very much\n"
"for helping to test mesosphere.\n";
}
if (suggestion != NULL) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n%s", suggestion);
}
}
static void _check_and_display_atmosphere_fatal_error(void) {
/* Check for valid magic. */
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
@@ -82,7 +144,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic = 0xCCCCCCCC;
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "A fatal error occurred when running Atmosph\xe8re.\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Title ID: %016llx\n", ctx.title_id);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Program ID: %016llx\n", ctx.program_id);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc);
/* Save context to the SD card. */
@@ -90,12 +152,18 @@ static void _check_and_display_atmosphere_fatal_error(void) {
char filepath[0x40];
snprintf(filepath, sizeof(filepath) - 1, "/atmosphere/fatal_errors/report_%016llx.bin", ctx.report_identifier);
filepath[sizeof(filepath)-1] = 0;
write_to_file(&ctx, sizeof(ctx), filepath);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"Report saved to %s\n", filepath);
if (write_to_file(&ctx, sizeof(ctx), filepath) != sizeof(ctx)) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Failed to save report to the SD card!\n");
} else {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Report saved to %s\n", filepath);
}
}
/* Try to print a fix suggestion via automatic error detection. */
_try_suggest_fix(&ctx);
/* Display error. */
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nPress POWER to reboot\n");
}
/* Wait for button and reboot. */

View File

@@ -36,7 +36,7 @@
typedef struct {
uint32_t magic;
uint32_t error_desc;
uint64_t title_id;
uint64_t program_id;
union {
uint64_t gprs[32];
struct {

View File

@@ -106,7 +106,7 @@ void load_stage2(const char *bct0) {
}
if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) {
print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n");
fatal_error("Stage2's path name is too big!\n");
}
if (!check_32bit_address_loadable(config.entrypoint)) {

View File

@@ -26,6 +26,7 @@
#include "car.h"
#include "btn.h"
#include "lib/log.h"
#include "lib/vsprintf.h"
#include "display/video_fb.h"
#include <inttypes.h>
@@ -112,11 +113,11 @@ __attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
/* Turn on the backlight after initializing the lfb */
/* to avoid flickering. */
display_backlight(true);
/* Override the global logging level. */
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
}
/* Override the global logging level. */
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
/* Display fatal error. */
va_list args;
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
@@ -137,37 +138,3 @@ __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, u
return true;
return false;
}
/* Adapted from https://gist.github.com/ccbrown/9722406 */
void hexdump(const void* data, size_t size, uintptr_t addrbase) {
const uint8_t *d = (const uint8_t *)data;
char ascii[17];
ascii[16] = '\0';
for (size_t i = 0; i < size; i++) {
if (i % 16 == 0) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
}
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%02X ", d[i]);
if (d[i] >= ' ' && d[i] <= '~') {
ascii[i % 16] = d[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
if ((i+1) % 16 == 0) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
}
for (size_t j = (i+1) % 16; j < 16; j++) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
}
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii);
}
}
}
}

View File

@@ -117,15 +117,12 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s
overlaps_a(start, end, __start__, __end__);
}
void hexdump(const void* data, size_t size, uintptr_t addrbase);
__attribute__((noreturn)) void watchdog_reboot(void);
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
__attribute__((noreturn)) void reboot_to_self(void);
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
__attribute__((noreturn)) void generic_panic(void);
__attribute__((noreturn)) void fatal_error(const char *fmt, ...);
#endif

View File

@@ -89,7 +89,7 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(AMS)/exosphere $(AMS)/exosphere/warmboot $(AMS)/exosphere/program/rebootstub \
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
export DEPSDIR := $(CURDIR)/$(BUILD)
@@ -100,7 +100,7 @@ KIPFILES := loader.kip ncm.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
exosphere.bin warmboot.bin rebootstub.bin thermosphere.bin splash_screen.bmp \
sept-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \
sept-secondary_dev_00.enc sept-secondary_dev_01.enc kernel_ldr.bin $(KIPFILES)
sept-secondary_dev_00.enc sept-secondary_dev_01.enc mesosphere.bin kernel_ldr.bin $(KIPFILES)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@@ -186,11 +186,15 @@ DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin
$(OUTPUT).bin : $(OUTPUT).elf
$(OUTPUT).bin : $(OUTPUT)-experimental.bin
@python $(TOPDIR)/fusee_make_standard.py $(OUTPUT)-experimental.bin $(OUTPUT).bin
@echo built ... $(notdir $@)
$(OUTPUT)-experimental.bin : $(OUTPUT)-experimental.elf
$(OBJCOPY) -S -O binary $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
$(OUTPUT)-experimental.elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python
import sys, os
from struct import pack as pk, unpack as up
def make_standard(exp):
std = exp[:]
_, metadata_offset, is_exp = up('<III', exp[:12])
assert is_exp == 1
# Patch the experimental flag to zero.
std = std[:8] + pk('<I', 0) + std[12:]
# Locate the mesosphere content header, patch to be experimental.
magic, size, code_ofs, content_ofs, num_contents, ver, sup_ver, rev = up('<IIIIIIII', exp[metadata_offset:metadata_offset + 0x20])
for i in range(num_contents):
start, size, cnt_type, flag0, flag1, flag2, pad = up('<IIBBBBI', exp[content_ofs + 0x20 * i:content_ofs + 0x20 * i + 0x10])
if cnt_type == 10: # CONTENT_TYPE_KRN
assert exp[content_ofs + 0x20 * i + 0x10:content_ofs + 0x20 * i + 0x10 + len(b'mesosphere') + 1] == (b'mesosphere\x00')
assert flag0 == 0 and flag1 == 0 and flag2 == 0
std = std[:content_ofs + 0x20 * i] + pk('<IIBBBBI', start, size, cnt_type, flag0 | 0x1, flag1, flag2, pad) + std[content_ofs + 0x20 * i + 0x10:]
return std
def main(argc, argv):
if argc != 3:
print('Usage: %s input output' % argv[0])
return 1
with open(argv[1], 'rb') as f:
experimental = f.read()
with open(argv[2], 'wb') as f:
f.write(make_standard(experimental))
return 0
if __name__ == '__main__':
sys.exit(main(len(sys.argv), sys.argv))

View File

@@ -254,4 +254,6 @@ SECTIONS
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
PROVIDE(__kernel_ldr_bin_size__ = kernel_ldr_bin_end - kernel_ldr_bin);
PROVIDE(__mesosphere_bin_start__ = mesosphere_bin - __start__);
PROVIDE(__mesosphere_bin_size__ = mesosphere_bin_end - mesosphere_bin);
}

View File

@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FUSEE_CAR_H
#define FUSEE_CAR_H
@@ -37,23 +37,27 @@
/* Clock and reset devices. */
typedef enum {
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_BPMP = ((0 << 5) | 0x1),
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_USBD = ((0 << 5) | 0x16),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_AHBDMA = ((1 << 5) | 0x1),
CARDEVICE_APBDMA = ((1 << 5) | 0x2),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_BPMP = ((0 << 5) | 0x1)
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
} CarDevice;
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
@@ -97,31 +101,31 @@ typedef struct {
uint32_t pllc_out;
uint32_t pllc_misc0;
uint32_t pllc_misc1;
/* PLLM 0x90-0x9c */
uint32_t pllm_base;
uint32_t pllm_out;
uint32_t pllm_misc1;
uint32_t pllm_misc2;
/* PLLP 0xa0-0xac */
uint32_t pllp_base;
uint32_t pllp_outa;
uint32_t pllp_outb;
uint32_t pllp_misc;
/* PLLA 0xb0-0xbc */
uint32_t plla_base;
uint32_t plla_out;
uint32_t plla_misc0;
uint32_t plla_misc1;
/* PLLU 0xc0-0xcc */
uint32_t pllu_base;
uint32_t pllu_out;
uint32_t pllu_misc1;
uint32_t pllu_misc2;
/* PLLD 0xd0-0xdc */
uint32_t plld_base;
uint32_t plld_out;
@@ -131,13 +135,13 @@ typedef struct {
/* PLLX 0xe0-0xe4 */
uint32_t pllx_base;
uint32_t pllx_misc;
/* PLLE 0xe8-0xf4 */
uint32_t plle_base;
uint32_t plle_misc;
uint32_t plle_ss_cntl1;
uint32_t plle_ss_cntl2;
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
@@ -188,7 +192,7 @@ typedef struct {
uint32_t _0x1e0[5];
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
uint32_t _0x1f8;
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
uint32_t _0x200[32];
@@ -257,7 +261,7 @@ typedef struct {
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
uint32_t _0x3a8[2];
uint32_t _0x3b0;
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
@@ -371,13 +375,13 @@ typedef struct {
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
uint32_t _0x568[2];
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
uint32_t _0x57c[5];
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
@@ -399,7 +403,7 @@ typedef struct {
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
uint32_t _0x5f8[2];
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
@@ -428,7 +432,7 @@ typedef struct {
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
uint32_t _0x670[2];
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
uint32_t _0x684[2];
@@ -439,14 +443,14 @@ typedef struct {
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
@@ -455,11 +459,11 @@ typedef struct {
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
@@ -470,7 +474,7 @@ typedef struct {
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
@@ -484,7 +488,7 @@ typedef struct {
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
} tegra_car_t;
static inline volatile tegra_car_t *car_get_regs(void) {

View File

@@ -18,67 +18,9 @@
#include <string.h>
#include "device_partition.h"
int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors)
{
int rc;
if (!devpart->initialized) {
rc = devpart->initializer(devpart);
if (rc != 0) {
return rc;
}
}
if ((devpart->read_cipher != NULL) && (devpart->crypto_mode != DevicePartitionCryptoMode_None)) {
for (uint64_t i = 0; i < num_sectors; i += devpart->crypto_work_buffer_num_sectors) {
uint64_t n = (i + devpart->crypto_work_buffer_num_sectors > num_sectors) ? (num_sectors - i) : devpart->crypto_work_buffer_num_sectors;
rc = devpart->reader(devpart, devpart->crypto_work_buffer, sector + i, n);
if (rc != 0) {
return rc;
}
rc = devpart->read_cipher(devpart, sector + i, n);
if (rc != 0) {
return rc;
}
memcpy(dst + (size_t)(devpart->sector_size * i), devpart->crypto_work_buffer, (size_t)(devpart->sector_size * n));
}
return 0;
} else {
return devpart->reader(devpart, dst, sector, num_sectors);
}
}
int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors)
{
int rc;
if (!devpart->initialized) {
rc = devpart->initializer(devpart);
if (rc != 0) {
return rc;
}
}
if ((devpart->write_cipher != NULL) && (devpart->crypto_mode != DevicePartitionCryptoMode_None)) {
for (uint64_t i = 0; i < num_sectors; i += devpart->crypto_work_buffer_num_sectors) {
uint64_t n = (i + devpart->crypto_work_buffer_num_sectors > num_sectors) ? (num_sectors - i) : devpart->crypto_work_buffer_num_sectors;
memcpy(devpart->crypto_work_buffer, src + (size_t)(devpart->sector_size * i), (size_t)(devpart->sector_size * n));
rc = devpart->write_cipher(devpart, sector + i, n);
if (rc != 0) {
return rc;
}
rc = devpart->writer(devpart, devpart->crypto_work_buffer, sector + i, n);
if (rc != 0) {
return rc;
}
}
return 0;
} else {
return devpart->writer(devpart, src, sector, num_sectors);
}
}
int emu_device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors, const char *origin_path, int num_parts, uint64_t part_limit)
{
int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {
int rc = 0;
uint64_t target_sector = sector;
char target_path[0x300 + 1] = {0};
/* Perform initialization steps, if necessary. */
if (!devpart->initialized) {
@@ -88,33 +30,37 @@ int emu_device_partition_read_data(device_partition_t *devpart, void *dst, uint6
}
}
/* Prepare the right file path if using file mode. */
if (devpart->emu_use_file && (origin_path != NULL)) {
/* Handle data in multiple parts, if necessary. */
if (num_parts > 0) {
int target_part = 0;
uint64_t data_offset = sector * devpart->sector_size;
/* Handle emulation. */
if (devpart->is_emulated) {
/* Prepare the right file path if using file mode. */
if (devpart->emu_use_file) {
int num_parts = devpart->emu_num_parts;
uint64_t part_limit = devpart->emu_part_limit;
if (data_offset >= part_limit) {
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
target_sector = (data_offset - (target_part * part_limit)) / devpart->sector_size;
/* Target part is invalid. */
if (target_part > num_parts) {
return -1;
/* Handle data in multiple parts, if necessary. */
if (num_parts > 0) {
int target_part = 0;
char target_path[0x300 + 1] = {0};
uint64_t data_offset = sector * devpart->sector_size;
if (data_offset >= part_limit) {
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
target_sector = (data_offset - (target_part * part_limit)) / devpart->sector_size;
/* Target part is invalid. */
if (target_part > num_parts) {
return -1;
}
}
/* Treat the path as a folder with each part inside. */
snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", devpart->emu_root_path, target_part);
/* Update the target file path. */
strcpy(devpart->emu_file_path, target_path);
}
/* Treat the path as a folder with each part inside. */
snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", origin_path, target_part);
} else {
/* If there are no parts, copy the origin path directly. */
strcpy(target_path, origin_path);
}
/* Update the target file path. */
devpart->emu_file_path = target_path;
}
/* Read the partition data. */
@@ -147,11 +93,9 @@ int emu_device_partition_read_data(device_partition_t *devpart, void *dst, uint6
return rc;
}
int emu_device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors, const char *origin_path, int num_parts, uint64_t part_limit)
{
int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) {
int rc = 0;
uint64_t target_sector = sector;
char target_path[0x300 + 1] = {0};
/* Perform initialization steps, if necessary. */
if (!devpart->initialized) {
@@ -161,33 +105,37 @@ int emu_device_partition_write_data(device_partition_t *devpart, const void *src
}
}
/* Prepare the right file path if using file mode. */
if (devpart->emu_use_file && (origin_path != NULL)) {
/* Handle data in multiple parts, if necessary. */
if (num_parts > 0) {
int target_part = 0;
uint64_t data_offset = sector * devpart->sector_size;
/* Handle emulation. */
if (devpart->is_emulated) {
/* Prepare the right file path if using file mode. */
if (devpart->emu_use_file) {
int num_parts = devpart->emu_num_parts;
uint64_t part_limit = devpart->emu_part_limit;
if (data_offset >= part_limit) {
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
target_sector = (data_offset - (target_part * part_limit)) / devpart->sector_size;
/* Target part is invalid. */
if (target_part > num_parts) {
return -1;
/* Handle data in multiple parts, if necessary. */
if (num_parts > 0) {
int target_part = 0;
char target_path[0x300 + 1] = {0};
uint64_t data_offset = sector * devpart->sector_size;
if (data_offset >= part_limit) {
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
target_sector = (data_offset - (target_part * part_limit)) / devpart->sector_size;
/* Target part is invalid. */
if (target_part > num_parts) {
return -1;
}
}
/* Treat the path as a folder with each part inside. */
snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", devpart->emu_root_path, target_part);
/* Update the target file path. */
strcpy(devpart->emu_file_path, target_path);
}
/* Treat the path as a folder with each part inside. */
snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", origin_path, target_part);
} else {
/* If there are no parts, copy the origin path directly. */
strcpy(target_path, origin_path);
}
/* Update the target file path. */
devpart->emu_file_path = target_path;
}
/* Write the partition data. */

View File

@@ -67,13 +67,16 @@ typedef struct device_partition_t {
uint8_t __attribute__((aligned(16))) iv[DEVPART_IV_MAX_SIZE]; /* IV. */
bool initialized;
char *emu_file_path; /* Emulated device file path. */
/* Emulation only. */
bool is_emulated;
bool emu_use_file;
char emu_root_path[0x100 + 1];
char emu_file_path[0x300 + 1];
int emu_num_parts;
uint64_t emu_part_limit;
} device_partition_t;
int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors);
int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors);
int emu_device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors, const char *origin_path, int num_parts, uint64_t part_limit);
int emu_device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors, const char *origin_path, int num_parts, uint64_t part_limit);
#endif

View File

@@ -1,489 +0,0 @@
/*
* 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 <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/iosupport.h>
#include <sys/param.h>
#include <unistd.h>
#include "emu_dev.h"
#include "utils.h"
static int emudev_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
static int emudev_close(struct _reent *r, void *fd);
static ssize_t emudev_write(struct _reent *r, void *fd, const char *ptr, size_t len);
static ssize_t emudev_read(struct _reent *r, void *fd, char *ptr, size_t len);
static off_t emudev_seek(struct _reent *r, void *fd, off_t pos, int whence);
static int emudev_fstat(struct _reent *r, void *fd, struct stat *st);
static int emudev_stat(struct _reent *r, const char *file, struct stat *st);
static int emudev_fsync(struct _reent *r, void *fd);
typedef struct emudev_device_t {
devoptab_t devoptab;
char origin_path[0x300+1];
int num_parts;
uint64_t part_limit;
uint8_t *tmp_sector;
device_partition_t devpart;
char name[32+1];
char root_path[34+1];
bool setup, registered;
} emudev_device_t;
typedef struct emudev_file_t {
emudev_device_t *device;
int open_flags;
uint64_t offset;
} emudev_file_t;
static emudev_device_t g_emudev_devices[EMUDEV_MAX_DEVICES] = {0};
static devoptab_t g_emudev_devoptab = {
.structSize = sizeof(emudev_file_t),
.open_r = emudev_open,
.close_r = emudev_close,
.write_r = emudev_write,
.read_r = emudev_read,
.seek_r = emudev_seek,
.fstat_r = emudev_fstat,
.stat_r = emudev_stat,
.fsync_r = emudev_fsync,
.deviceData = NULL,
};
static emudev_device_t *emudev_find_device(const char *name) {
for (size_t i = 0; i < EMUDEV_MAX_DEVICES; i++) {
if (g_emudev_devices[i].setup && strcmp(g_emudev_devices[i].name, name) == 0) {
return &g_emudev_devices[i];
}
}
return NULL;
}
int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path, int num_parts, uint64_t part_limit) {
emudev_device_t *device = NULL;
if (name[0] == '\0' || devpart == NULL) {
errno = EINVAL;
return -1;
}
if (strlen(name) > 32) {
errno = ENAMETOOLONG;
return -1;
}
if (emudev_find_device(name) != NULL) {
errno = EEXIST; /* Device already exists */
return -1;
}
/* Find an unused slot. */
for (size_t i = 0; i < EMUDEV_MAX_DEVICES; i++) {
if (!g_emudev_devices[i].setup) {
device = &g_emudev_devices[i];
break;
}
}
if (device == NULL) {
errno = ENOMEM;
return -1;
}
memset(device, 0, sizeof(emudev_device_t));
device->devoptab = g_emudev_devoptab;
device->devpart = *devpart;
strcpy(device->name, name);
strcpy(device->root_path, name);
strcat(device->root_path, ":/");
/* Copy the file path for file mode. */
if (devpart->emu_use_file)
strcpy(device->origin_path, origin_path);
device->num_parts = num_parts;
device->part_limit = part_limit;
device->devoptab.name = device->name;
device->devoptab.deviceData = device;
/* Initialize immediately. */
int rc = device->devpart.initializer(&device->devpart);
if (rc != 0) {
errno = rc;
return -1;
}
/* Allocate memory for our intermediate sector. */
device->tmp_sector = (uint8_t *)malloc(devpart->sector_size);
if (device->tmp_sector == NULL) {
errno = ENOMEM;
return -1;
}
device->setup = true;
device->registered = false;
return 0;
}
int emudev_register_device(const char *name) {
emudev_device_t *device = emudev_find_device(name);
if (device == NULL) {
errno = ENOENT;
return -1;
}
if (device->registered) {
/* Do nothing if the device is already registered. */
return 0;
}
if (AddDevice(&device->devoptab) == -1) {
errno = ENOMEM;
return -1;
} else {
device->registered = true;
return 0;
}
}
int emudev_unregister_device(const char *name) {
emudev_device_t *device = emudev_find_device(name);
char drname[40];
if (device == NULL) {
errno = ENOENT;
return -1;
}
if (!device->registered) {
/* Do nothing if the device is not registered. */
return 0;
}
strcpy(drname, name);
strcat(drname, ":");
if (RemoveDevice(drname) == -1) {
errno = ENOENT;
return -1;
} else {
device->registered = false;
return 0;
}
}
int emudev_unmount_device(const char *name) {
int rc;
emudev_device_t *device = emudev_find_device(name);
if (device == NULL) {
errno = ENOENT;
return -1;
}
rc = emudev_unregister_device(name);
if (rc == -1) {
return -1;
}
free(device->tmp_sector);
device->devpart.finalizer(&device->devpart);
memset(device, 0, sizeof(emudev_device_t));
return 0;
}
int emudev_unmount_all(void) {
for (size_t i = 0; i < EMUDEV_MAX_DEVICES; i++) {
int rc = emudev_unmount_device(g_emudev_devices[i].name);
if (rc != 0) {
return rc;
}
}
return 0;
}
static int emudev_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
(void)mode;
emudev_file_t *f = (emudev_file_t *)fileStruct;
emudev_device_t *device = (emudev_device_t *)(r->deviceData);
/* Only allow "device:/". */
if (strcmp(path, device->root_path) != 0) {
r->_errno = ENOENT;
return -1;
}
/* Forbid some flags that we explicitly don't support.*/
if (flags & (O_APPEND | O_TRUNC | O_EXCL)) {
r->_errno = EINVAL;
return -1;
}
memset(f, 0, sizeof(emudev_file_t));
f->device = device;
f->open_flags = flags;
return 0;
}
static int emudev_close(struct _reent *r, void *fd) {
(void)r;
emudev_file_t *f = (emudev_file_t *)fd;
memset(f, 0, sizeof(emudev_file_t));
return 0;
}
static ssize_t emudev_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
emudev_file_t *f = (emudev_file_t *)fd;
emudev_device_t *device = f->device;
size_t sector_size = device->devpart.sector_size;
uint64_t sector_begin = f->offset / sector_size;
uint64_t sector_end = (f->offset + len + sector_size - 1) / sector_size;
uint64_t sector_end_aligned;
uint64_t current_sector = sector_begin;
const uint8_t *data = (const uint8_t *)ptr;
int no = 0;
if (sector_end >= device->devpart.num_sectors) {
len = (size_t)(sector_size * device->devpart.num_sectors - f->offset);
sector_end = device->devpart.num_sectors;
}
sector_end_aligned = sector_end - ((f->offset + len) % sector_size != 0 ? 1 : 0);
if (len == 0) {
return 0;
}
/* Unaligned at the start, we need to read the sector and incorporate the data. */
if (f->offset % sector_size != 0) {
size_t nb = (size_t)(len <= (sector_size - (f->offset % sector_size)) ? len : sector_size - (f->offset % sector_size));
no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_begin, 1, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
memcpy(device->tmp_sector + (f->offset % sector_size), data, nb);
no = emu_device_partition_write_data(&device->devpart, device->tmp_sector, sector_begin, 1, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
/* Advance */
data += sector_size - (f->offset % sector_size);
current_sector++;
}
/* Check if we're already done (otherwise this causes a bug in handling the last sector of the range). */
if (current_sector == sector_end) {
f->offset += len;
return len;
}
/* Write all of the sector-aligned data. */
if (current_sector != sector_end_aligned) {
no = emu_device_partition_write_data(&device->devpart, data, current_sector, sector_end_aligned - current_sector, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
}
data += sector_size * (sector_end_aligned - current_sector);
current_sector = sector_end_aligned;
/* Unaligned at the end, we need to read the sector and incorporate the data. */
if (sector_end != sector_end_aligned) {
no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_end_aligned, 1, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
memcpy(device->tmp_sector, data, (size_t)((f->offset + len) % sector_size));
no = emu_device_partition_write_data(&device->devpart, device->tmp_sector, sector_end_aligned, 1, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
/* Advance */
data += sector_size - ((f->offset + len) % sector_size);
current_sector++;
}
f->offset += len;
return len;
}
static ssize_t emudev_read(struct _reent *r, void *fd, char *ptr, size_t len) {
emudev_file_t *f = (emudev_file_t *)fd;
emudev_device_t *device = f->device;
size_t sector_size = device->devpart.sector_size;
uint64_t sector_begin = f->offset / sector_size;
uint64_t sector_end = (f->offset + len + sector_size - 1) / sector_size;
uint64_t sector_end_aligned;
uint64_t current_sector = sector_begin;
uint8_t *data = (uint8_t *)ptr;
int no = 0;
if (sector_end >= device->devpart.num_sectors) {
len = (size_t)(sector_size * device->devpart.num_sectors - f->offset);
sector_end = device->devpart.num_sectors;
}
sector_end_aligned = sector_end - ((f->offset + len) % sector_size != 0 ? 1 : 0);
if (len == 0) {
return 0;
}
/* Unaligned at the start, we need to read the sector and incorporate the data. */
if (f->offset % sector_size != 0) {
size_t nb = (size_t)(len <= (sector_size - (f->offset % sector_size)) ? len : sector_size - (f->offset % sector_size));
no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_begin, 1, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
memcpy(data, device->tmp_sector + (f->offset % sector_size), nb);
/* Advance */
data += sector_size - (f->offset % sector_size);
current_sector++;
}
/* Check if we're already done (otherwise this causes a bug in handling the last sector of the range). */
if (current_sector == sector_end) {
f->offset += len;
return len;
}
/* Read all of the sector-aligned data. */
if (current_sector != sector_end_aligned) {
no = emu_device_partition_read_data(&device->devpart, data, current_sector, sector_end_aligned - current_sector, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
}
data += sector_size * (sector_end_aligned - current_sector);
current_sector = sector_end_aligned;
/* Unaligned at the end, we need to read the sector and incorporate the data. */
if (sector_end != sector_end_aligned) {
no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_end_aligned, 1, device->origin_path, device->num_parts, device->part_limit);
if (no != 0) {
r->_errno = no;
return -1;
}
memcpy(data, device->tmp_sector, (size_t)((f->offset + len) % sector_size));
/* Advance */
data += sector_size - ((f->offset + len) % sector_size);
current_sector++;
}
f->offset += len;
return len;
}
static off_t emudev_seek(struct _reent *r, void *fd, off_t pos, int whence) {
emudev_file_t *f = (emudev_file_t *)fd;
emudev_device_t *device = f->device;
uint64_t off;
switch (whence) {
case SEEK_SET:
off = 0;
break;
case SEEK_CUR:
off = f->offset;
break;
case SEEK_END:
off = device->devpart.num_sectors * device->devpart.sector_size;
break;
default:
r->_errno = EINVAL;
return -1;
}
if (pos < 0 && pos + off < 0) {
/* don't allow seek to before the beginning of the file */
r->_errno = EINVAL;
return -1;
}
f->offset = (uint64_t)(pos + off);
return (off_t)(pos + off);
}
static void emudev_stat_impl(emudev_device_t *device, struct stat *st) {
memset(st, 0, sizeof(struct stat));
st->st_size = (off_t)(device->devpart.num_sectors * device->devpart.sector_size);
st->st_nlink = 1;
st->st_blksize = device->devpart.sector_size;
st->st_blocks = st->st_size / st->st_blksize;
st->st_mode = S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
}
static int emudev_fstat(struct _reent *r, void *fd, struct stat *st) {
(void)r;
emudev_file_t *f = (emudev_file_t *)fd;
emudev_device_t *device = f->device;
emudev_stat_impl(device, st);
return 0;
}
static int emudev_stat(struct _reent *r, const char *file, struct stat *st) {
emudev_device_t *device = (emudev_device_t *)(r->deviceData);
if (strcmp(file, device->root_path) != 0) {
r->_errno = ENOENT;
return -1;
}
emudev_stat_impl(device, st);
return 0;
}
static int emudev_fsync(struct _reent *r, void *fd) {
/* Nothing to do. */
(void)r;
(void)fd;
return 0;
}

View File

@@ -85,6 +85,9 @@ typedef enum {
FS_VER_10_0_0,
FS_VER_10_0_0_EXFAT,
FS_VER_10_2_0,
FS_VER_10_2_0_EXFAT,
FS_VER_MAX,
} emummc_fs_ver_t;

View File

@@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <inttypes.h>
#include "exception_handlers.h"
@@ -22,7 +23,7 @@
#include "lib/log.h"
#define CODE_DUMP_SIZE 0x30
#define STACK_DUMP_SIZE 0x60
#define STACK_DUMP_SIZE 0x30
extern const uint32_t exception_handler_table[];
@@ -35,6 +36,40 @@ static const char *register_names[] = {
"SP", "LR", "PC", "CPSR",
};
/* Adapted from https://gist.github.com/ccbrown/9722406 */
static void hexdump(const void* data, size_t size, uintptr_t addrbase, char* strbuf) {
const uint8_t *d = (const uint8_t *)data;
char ascii[17] = {0};
ascii[16] = '\0';
for (size_t i = 0; i < size; i++) {
if (i % 16 == 0) {
strbuf += sprintf(strbuf, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
}
strbuf += sprintf(strbuf, "%02X ", d[i]);
if (d[i] >= ' ' && d[i] <= '~') {
ascii[i % 16] = d[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
strbuf += sprintf(strbuf, " ");
if ((i+1) % 16 == 0) {
strbuf += sprintf(strbuf, "| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
strbuf += sprintf(strbuf, " ");
}
for (size_t j = (i+1) % 16; j < 16; j++) {
strbuf += sprintf(strbuf, " ");
}
strbuf += sprintf(strbuf, "| %s \n", ascii);
}
}
}
}
void setup_exception_handlers(void) {
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
for (int i = 0; i < 8; i++) {
@@ -45,38 +80,40 @@ void setup_exception_handlers(void) {
}
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
uint8_t code_dump[CODE_DUMP_SIZE];
uint8_t stack_dump[STACK_DUMP_SIZE];
size_t code_dump_size;
size_t stack_dump_size;
char exception_log[0x400] = {0};
uint8_t code_dump[CODE_DUMP_SIZE] = {0};
uint8_t stack_dump[STACK_DUMP_SIZE] = {0};
size_t code_dump_size = 0;
size_t stack_dump_size = 0;
uint32_t pc = registers[15];
uint32_t cpsr = registers[16];
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
sprintf(exception_log, "An exception occured!\n");
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE);
stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
exception_names[exception_type]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n");
sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]);
sprintf(exception_log + strlen(exception_log), "\nRegisters:\n");
/* Print r0 to pc. */
for (int i = 0; i < 16; i += 2) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
register_names[i], registers[i], register_names[i+1], registers[i+1]);
}
/* Print cpsr. */
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
fatal_error("An exception occurred!\n");
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
/* Print code and stack regions. */
sprintf(exception_log + strlen(exception_log), "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\n");
/* Throw fatal error with the full exception log. */
fatal_error(exception_log);
}

View File

@@ -302,7 +302,6 @@ int fsdev_register_keys(const char *name, unsigned int target_firmware, BisParti
return 0;
}
int fsdev_unmount_all(void) {
for (size_t i = 0; i < FF_VOLUMES; i++) {
int ret = fsdev_unmount_device(g_fsdev_devices[i].name);

View File

@@ -112,42 +112,3 @@ int gpt_iterate_through_entries(FILE *disk, size_t sector_size, gpt_entry_iterat
return 0;
}
int gpt_iterate_through_emu_entries(FILE *disk, size_t sector_size, gpt_emu_entry_iterator_t callback, void *param, const char *origin_path, int num_parts, uint64_t part_limit) {
efi_header_t hdr;
efi_entry_t entry;
size_t offset = 2 * 512; /* Sector #2. */
size_t delta;
/* Get the header. */
if (gpt_get_header(&hdr, disk, sector_size) == -1) {
return -1;
}
/* Seek to the entry table. */
if (fseek(disk, sector_size * hdr.entries_first_lba - offset, SEEK_CUR) != 0) {
return -1;
}
offset = sector_size * hdr.entries_first_lba;
delta = hdr.entry_size - sizeof(efi_entry_t);
/* Iterate through the entries. */
for (uint32_t i = 0; i < hdr.entry_count; i++) {
if (!fread(&entry, sizeof(efi_entry_t), 1, disk)) {
return -1;
}
if (callback(&entry, param, offset, disk, origin_path, num_parts, part_limit) != 0) {
return -1;
}
if (delta != 0 && fseek(disk, delta, SEEK_CUR) != 0) {
return -1;
}
offset += hdr.entry_size;
}
return 0;
}

View File

@@ -56,6 +56,5 @@ typedef int (*gpt_emu_entry_iterator_t)(const efi_entry_t *entry, void *param, s
int gpt_get_header(efi_header_t *out, FILE *disk, size_t sector_size);
int gpt_iterate_through_entries(FILE *disk, size_t sector_size, gpt_entry_iterator_t callback, void *param);
int gpt_iterate_through_emu_entries(FILE *disk, size_t sector_size, gpt_emu_entry_iterator_t callback, void *param, const char *origin_path, int num_parts, uint64_t part_limit);
#endif

View File

@@ -420,6 +420,9 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
"\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", /* FS_VER_10_0_0 */
"\x81\x7E\xA2\xB0\xB7\x02\xC1\xF3", /* FS_VER_10_0_0_EXFAT */
"\xA9\x52\xB6\x57\xAD\xF9\xC2\xBA", /* FS_VER_10_2_0 */
"\x16\x0D\x3E\x10\x4E\xAD\x61\x76", /* FS_VER_10_2_0_EXFAT */
};
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {

View File

@@ -971,12 +971,6 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
const uint32_t kernel_ldr_offset = *((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr + 8));
memcpy((void *)((uintptr_t)_kernel + kernel_ldr_offset), kernel_ldr_bin, kernel_ldr_bin_size);
/* Set target firmware for our kernel loader. */
uint32_t *kldr_u32 = (uint32_t *)((uintptr_t)_kernel + kernel_ldr_offset);
if (kldr_u32[1] == 0x30444C4D) {
kldr_u32[2] = target_firmware;
}
/* Update size. */
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;

View File

@@ -273,7 +273,10 @@ void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmwa
}
};
const uint32_t bis_key_generation = fuse_get_5x_key_generation();
uint32_t bis_key_generation = fuse_get_5x_key_generation();
if (bis_key_generation > 0) {
bis_key_generation -= 1;
}
static const uint8_t AL16 bis_kek_source[0x10] = {0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F};
switch (partition_id) {

View File

@@ -17,7 +17,7 @@
#ifndef FUSEE_LOG_H
#define FUSEE_LOG_H
#define PRINT_MESSAGE_MAX_LENGTH 512
#define PRINT_MESSAGE_MAX_LENGTH 1024
#include <stdarg.h>

View File

@@ -24,6 +24,7 @@
#include "nxboot.h"
#include "nxfs.h"
#include "bct.h"
#include "car.h"
#include "di.h"
#include "mc.h"
#include "se.h"
@@ -54,6 +55,7 @@
#define u8 uint8_t
#define u32 uint32_t
#include "exosphere_bin.h"
#include "mesosphere_bin.h"
#include "sept_secondary_00_enc.h"
#include "sept_secondary_01_enc.h"
#include "sept_secondary_dev_00_enc.h"
@@ -64,7 +66,8 @@
#undef u32
extern const uint8_t warmboot_bin[];
extern const uint32_t warmboot_bin_size;
extern int fusee_is_experimental(void);
static const uint8_t retail_pkc_modulus[0x100] = {
0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD,
@@ -209,11 +212,11 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
strat_cfg->has_nogc_config = true;
sscanf(value, "%d", &tmp);
strat_cfg->enable_nogc = tmp != 0;
} else if (strcmp(name, STRATOSPHERE_ENABLE_NCM_KEY) == 0) {
} else if (strcmp(name, STRATOSPHERE_DISABLE_NCM_KEY) == 0) {
sscanf(value, "%d", &tmp);
strat_cfg->ncm_enabled = tmp != 0;
if (strat_cfg->ncm_enabled) {
stratosphere_enable_ncm();
strat_cfg->ncm_disabled = tmp != 0;
if (strat_cfg->ncm_disabled) {
stratosphere_disable_ncm();
}
} else {
return 0;
@@ -236,6 +239,9 @@ static uint32_t nxboot_get_specific_target_firmware(uint32_t target_firmware){
#define CHECK_NCA(NCA_ID, VERSION) do { if (is_nca_present(NCA_ID)) { return ATMOSPHERE_TARGET_FIRMWARE_##VERSION; } } while(0)
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
CHECK_NCA("26325de4db3909e0ef2379787c7e671d", 10_2_0);
CHECK_NCA("5077973537f6735b564dd7475b779f87", 10_1_1); /* Exclusive to China. */
CHECK_NCA("fd1faed0ca750700d254c0915b93d506", 10_1_0);
CHECK_NCA("34728c771299443420820d8ae490ea41", 10_0_4);
CHECK_NCA("5b1df84f88c3334335bbb45d8522cbb4", 10_0_3);
CHECK_NCA("e951bc9dedcd54f65ffd83d4d050f9e0", 10_0_2);
@@ -621,6 +627,7 @@ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
uint32_t nxboot_main(void) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
loader_ctx_t *loader_ctx = get_loader_ctx();
const bool is_experimental = fusee_is_experimental();
package2_header_t *package2;
size_t package2_size;
void *tsec_fw;
@@ -632,6 +639,8 @@ uint32_t nxboot_main(void) {
void *warmboot_memaddr;
void *package1loader;
size_t package1loader_size;
void *mesosphere;
size_t mesosphere_size;
void *emummc;
size_t emummc_size;
uint32_t available_revision;
@@ -649,7 +658,7 @@ uint32_t nxboot_main(void) {
} else {
emummc_size = get_file_size("atmosphere/emummc.kip");
if (emummc_size != 0) {
/* Allocate memory for the TSEC firmware. */
/* Allocate memory for the emummc KIP. */
emummc = memalign(0x100, emummc_size);
if (emummc == NULL) {
@@ -838,13 +847,7 @@ uint32_t nxboot_main(void) {
/* Derive new device keys. */
{
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_5_0_0) {
derive_new_device_keys(fuse_get_retail_type() != 0, KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, target_firmware);
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
derive_new_device_keys(fuse_get_retail_type() != 0, KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY, target_firmware);
} else {
/* No new keys to derive */
}
derive_new_device_keys(fuse_get_retail_type() != 0, KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, target_firmware);
}
/* Set the system partition's keys. */
@@ -933,6 +936,41 @@ uint32_t nxboot_main(void) {
pmc->scratch1 = (uint32_t)warmboot_memaddr;
}
/* Configure mesosphere. */
{
size_t sd_meso_size = get_file_size("atmosphere/mesosphere.bin");
if (sd_meso_size != 0) {
if (sd_meso_size > PACKAGE2_SIZE_MAX) {
fatal_error("Error: atmosphere/mesosphere.bin is too large!\n");
}
mesosphere = malloc(sd_meso_size);
if (mesosphere == NULL) {
fatal_error("Error: failed to allocate mesosphere!\n");
}
if (read_from_file(mesosphere, sd_meso_size, "atmosphere/mesosphere.bin") != sd_meso_size) {
fatal_error("Error: failed to read atmosphere/mesosphere.bin!\n");
}
mesosphere_size = sd_meso_size;
} else if (is_experimental) {
mesosphere_size = mesosphere_bin_size;
mesosphere = malloc(mesosphere_size);
if (mesosphere == NULL) {
fatal_error("[NXBOOT] Out of memory!\n");
}
memcpy(mesosphere, mesosphere_bin, mesosphere_size);
if (mesosphere_size == 0) {
fatal_error("[NXBOOT] Could not read embedded mesosphere!\n");
}
} else {
mesosphere = NULL;
mesosphere_size = 0;
}
}
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Rebuilding package2...\n");
/* Parse stratosphere config. */
@@ -941,7 +979,7 @@ uint32_t nxboot_main(void) {
print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Configured Stratosphere...\n");
/* Patch package2, adding Thermosphère + custom KIPs. */
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, emummc, emummc_size);
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, mesosphere, mesosphere_size, emummc, emummc_size);
/* Set detected FS version. */
MAILBOX_EXOSPHERE_CONFIGURATION->emummc_cfg.base_cfg.fs_version = stratosphere_get_fs_version();
@@ -996,6 +1034,12 @@ uint32_t nxboot_main(void) {
/* Wait for the splash screen to have been displayed for as long as it should be. */
splash_screen_wait_delay();
/* Set reset for USBD, USB2, AHBDMA, and APBDMA. */
rst_enable(CARDEVICE_USBD);
rst_enable(CARDEVICE_USB2);
rst_enable(CARDEVICE_AHBDMA);
rst_enable(CARDEVICE_APBDMA);
/* Return the memory address for booting CPU0. */
return (uint32_t)exosphere_memaddr;
}

View File

@@ -36,7 +36,6 @@ static bool g_emmc_device_initialized = false;
static bool g_fsdev_ready = false;
static bool g_rawdev_ready = false;
static bool g_emudev_ready = false;
static bool g_is_emummc = false;
@@ -356,87 +355,6 @@ static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *par
return 0;
}
static int nxfs_mount_emu_partition_gpt_callback(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk, const char *origin_path, int num_parts, uint64_t part_limit) {
(void)entry_offset;
(void)disk;
device_partition_t *parent = (device_partition_t *)param;
device_partition_t devpart = *parent;
char name_buffer[128];
const uint16_t *utf16name = entry->name;
uint32_t name_len;
int rc;
static const struct {
const char *partition_name;
const char *mount_point;
bool is_fat;
bool is_encrypted;
bool register_immediately;
} known_partitions[] = {
{"PRODINFO", "prodinfo", false, true, false},
{"PRODINFOF", "prodinfof", true, true, false},
{"BCPKG2-1-Normal-Main", "bcpkg21", false, false, true},
{"BCPKG2-2-Normal-Sub", "bcpkg22", false, false, false},
{"BCPKG2-3-SafeMode-Main", "bcpkg23", false, false, false},
{"BCPKG2-4-SafeMode-Sub", "bcpkg24", false, false, false},
{"BCPKG2-5-Repair-Main", "bcpkg25", false, false, false},
{"BCPKG2-6-Repair-Sub", "bcpkg26", false, false, false},
{"SAFE", "safe", true, true, false},
{"SYSTEM", "system", true, true, true},
{"USER", "user", true, true, false},
};
/* Convert the partition name to ASCII, for comparison. */
for (name_len = 0; name_len < sizeof(entry->name) && *utf16name != 0; name_len++) {
name_buffer[name_len] = (char)*utf16name++;
}
name_buffer[name_len] = '\0';
/* Mount the partition, if we know about it. */
for (size_t i = 0; i < sizeof(known_partitions)/sizeof(known_partitions[0]); i++) {
if (strcmp(name_buffer, known_partitions[i].partition_name) == 0) {
devpart.start_sector += entry->first_lba;
devpart.num_sectors = (entry->last_lba + 1) - entry->first_lba;
if (parent->num_sectors < devpart.num_sectors) {
errno = EINVAL;
return -1;
}
if (known_partitions[i].is_encrypted) {
devpart.read_cipher = nxfs_bis_crypto_decrypt;
devpart.write_cipher = nxfs_bis_crypto_encrypt;
devpart.crypto_mode = DevicePartitionCryptoMode_Xts;
}
if (known_partitions[i].is_fat) {
rc = fsdev_mount_device(known_partitions[i].mount_point, &devpart, false);
if (rc == -1) {
return -1;
}
if (known_partitions[i].register_immediately) {
rc = fsdev_register_device(known_partitions[i].mount_point);
if (rc == -1) {
return -1;
}
}
} else {
rc = emudev_mount_device(known_partitions[i].mount_point, &devpart, origin_path, num_parts, part_limit);
if (rc == -1) {
return -1;
}
if (known_partitions[i].register_immediately) {
rc = emudev_register_device(known_partitions[i].mount_point);
if (rc == -1) {
return -1;
}
}
}
}
}
return 0;
}
int nxfs_mount_sd() {
device_partition_t model;
int rc;
@@ -446,6 +364,7 @@ int nxfs_mount_sd() {
model.device_struct = &g_sd_mmcpart;
model.start_sector = 0;
model.num_sectors = 1u << 30; /* arbitrary numbers of sectors. TODO: find the size of the SD in sectors. */
model.is_emulated = false;
/* Mount the SD card device. */
rc = fsdev_mount_device("sdmc", &model, true);
@@ -479,6 +398,7 @@ int nxfs_mount_emmc() {
model.device_struct = &g_emmc_boot0_mmcpart;
model.start_sector = 0;
model.num_sectors = 0x184000 / model.sector_size;
model.is_emulated = false;
/* Mount boot0 device. */
rc = rawdev_mount_device("boot0", &model, true);
@@ -499,6 +419,7 @@ int nxfs_mount_emmc() {
model.device_struct = &g_emmc_boot1_mmcpart;
model.start_sector = 0;
model.num_sectors = 0x80000 / model.sector_size;
model.is_emulated = false;
/* Mount boot1 device. */
rc = rawdev_mount_device("boot1", &model, false);
@@ -514,6 +435,7 @@ int nxfs_mount_emmc() {
model.device_struct = &g_emmc_user_mmcpart;
model.start_sector = 0;
model.num_sectors = (256ull << 30) / model.sector_size;
model.is_emulated = false;
/* Mount raw NAND device. */
rc = rawdev_mount_device("rawnand", &model, false);
@@ -558,10 +480,11 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
model = g_emummc_devpart_template;
model.start_sector = emummc_start_sector + (0x400000 * 0 / model.sector_size);
model.num_sectors = 0x400000 / model.sector_size;
model.is_emulated = true;
model.emu_use_file = false;
/* Mount emulated boot0 device. */
rc = emudev_mount_device("boot0", &model, NULL, 0, 0);
rc = rawdev_mount_device("boot0", &model, true);
/* Failed to mount boot0 device. */
if (rc == -1) {
@@ -569,7 +492,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
}
/* Register emulated boot0 device. */
rc = emudev_register_device("boot0");
rc = rawdev_register_device("boot0");
/* Failed to register boot0 device. */
if (rc == -1) {
@@ -580,10 +503,11 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
model = g_emummc_devpart_template;
model.start_sector = emummc_start_sector + (0x400000 * 1 / model.sector_size);
model.num_sectors = 0x400000 / model.sector_size;
model.is_emulated = true;
model.emu_use_file = false;
/* Mount emulated boot1 device. */
rc = emudev_mount_device("boot1", &model, NULL, 0, 0);
rc = rawdev_mount_device("boot1", &model, false);
/* Failed to mount boot1. */
if (rc == -1) {
@@ -596,10 +520,11 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
model = g_emummc_devpart_template;
model.start_sector = emummc_start_sector + (0x400000 * 2 / model.sector_size);
model.num_sectors = (256ull << 30) / model.sector_size;
model.is_emulated = true;
model.emu_use_file = false;
/* Mount emulated raw NAND device. */
rc = emudev_mount_device("rawnand", &model, NULL, 0, 0);
rc = rawdev_mount_device("rawnand", &model, false);
/* Failed to mount raw NAND. */
if (rc == -1) {
@@ -607,7 +532,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
}
/* Register emulated raw NAND device. */
rc = emudev_register_device("rawnand");
rc = rawdev_register_device("rawnand");
/* Failed to register raw NAND device. */
if (rc == -1) {
@@ -623,14 +548,14 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
}
/* Iterate the GPT and mount each emulated raw NAND partition. */
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, NULL, 0, 0);
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
/* Close emulated raw NAND device. */
fclose(rawnand);
/* All emulated devices are ready. */
if (rc == 0) {
g_emudev_ready = true;
g_rawdev_ready = true;
g_is_emummc = true;
}
@@ -641,10 +566,9 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
device_partition_t model;
int rc;
FILE *rawnand;
bool is_exfat;
char emummc_boot0_path[0x300 + 1] = {0};
char emummc_boot1_path[0x300 + 1] = {0};
/* Check if the SD card is EXFAT formatted. */
rc = fsdev_is_exfat("sdmc");
@@ -652,29 +576,20 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
if (rc == -1) {
return -1;
}
/* Set EXFAT status. */
is_exfat = (rc == 1);
/* Reject single part in FAT32. */
/* NOTE: This check has no effect in the current design. */
if (!is_exfat && (num_parts < 1)) {
return -2;
}
/* We want a folder with the archive bit set. */
rc = fsdev_get_attr(emummc_path);
/* Failed to get file DOS attributes. */
if (rc == -1) {
return -3;
return -2;
}
/* Our path is not a directory. */
if (!(rc & AM_DIR)) {
return -4;
return -3;
}
/* Check if the archive bit is not set. */
if (!(rc & AM_ARC)) {
/* Try to set the archive bit. */
@@ -682,102 +597,117 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Failed to set file DOS attributes. */
if (rc == -1) {
return -5;
return -4;
}
}
/* Prepare boot0 file path. */
snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0");
/* Setup an emulation template for boot0. */
model = g_emummc_devpart_template;
model.start_sector = 0;
model.num_sectors = 0x400000 / model.sector_size;
model.is_emulated = true;
model.emu_use_file = true;
/* Prepare boot0 file path. */
snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0");
model.emu_num_parts = 0;
model.emu_part_limit = 0;
strcpy(model.emu_root_path, emummc_path);
strcpy(model.emu_file_path, emummc_boot0_path);
/* Mount emulated boot0 device. */
rc = emudev_mount_device("boot0", &model, emummc_boot0_path, 0, 0);
rc = rawdev_mount_device("boot0", &model, true);
/* Failed to mount boot0 device. */
if (rc == -1) {
return -6;
return -5;
}
/* Register emulated boot0 device. */
rc = emudev_register_device("boot0");
rc = rawdev_register_device("boot0");
/* Failed to register boot0 device. */
if (rc == -1) {
return -7;
return -6;
}
/* Prepare boot1 file path. */
snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1");
/* Setup an emulation template for boot1. */
model = g_emummc_devpart_template;
model.start_sector = 0;
model.num_sectors = 0x400000 / model.sector_size;
model.is_emulated = true;
model.emu_use_file = true;
/* Prepare boot1 file path. */
snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1");
model.emu_num_parts = 0;
model.emu_part_limit = 0;
strcpy(model.emu_root_path, emummc_path);
strcpy(model.emu_file_path, emummc_boot1_path);
/* Mount emulated boot1 device. */
rc = emudev_mount_device("boot1", &model, emummc_boot1_path, 0, 0);
rc = rawdev_mount_device("boot1", &model, false);
/* Failed to mount boot1. */
if (rc == -1) {
return -8;
return -7;
}
/* Register emulated boot1 device. */
rc = emudev_register_device("boot1");
rc = rawdev_register_device("boot1");
/* Failed to register boot1 device. */
if (rc == -1) {
return -9;
return -8;
}
/* Setup a template for raw NAND. */
model = g_emummc_devpart_template;
model.start_sector = 0;
model.num_sectors = (256ull << 30) / model.sector_size;
model.is_emulated = true;
model.emu_use_file = true;
model.emu_num_parts = num_parts;
model.emu_part_limit = part_limit;
strcpy(model.emu_root_path, emummc_path);
strcpy(model.emu_file_path, emummc_path);
/* Mount emulated raw NAND device from single or multiple parts. */
rc = emudev_mount_device("rawnand", &model, emummc_path, num_parts, part_limit);
rc = rawdev_mount_device("rawnand", &model, false);
/* Failed to mount raw NAND. */
if (rc == -1) {
return -10;
return -9;
}
/* Register emulated raw NAND device. */
rc = emudev_register_device("rawnand");
rc = rawdev_register_device("rawnand");
/* Failed to register raw NAND device. */
if (rc == -1) {
return -11;
return -10;
}
/* Open emulated raw NAND device. */
rawnand = fopen("rawnand:/", "rb");
/* Failed to open emulated raw NAND device. */
if (rawnand == NULL) {
return -12;
return -11;
}
/* Iterate the GPT and mount each emulated raw NAND partition. */
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, emummc_path, num_parts, part_limit);
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
/* Close emulated raw NAND device. */
fclose(rawnand);
/* All emulated devices are ready. */
if (rc == 0) {
g_emudev_ready = true;
g_rawdev_ready = true;
g_is_emummc = true;
}
return rc;
}
@@ -805,18 +735,6 @@ int nxfs_unmount_emmc() {
return rc;
}
int nxfs_unmount_emummc() {
int rc = 0;
/* Unmount all emulated devices. */
if (g_emudev_ready) {
rc = emudev_unmount_all();
g_emudev_ready = false;
}
return rc;
}
int nxfs_init() {
int rc;
@@ -832,5 +750,5 @@ int nxfs_init() {
}
int nxfs_end() {
return ((nxfs_unmount_sd() || nxfs_unmount_emmc() || nxfs_unmount_emummc()) ? -1 : 0);
return ((nxfs_unmount_sd() || nxfs_unmount_emmc()) ? -1 : 0);
}

View File

@@ -19,7 +19,6 @@
#include "fs_dev.h"
#include "raw_dev.h"
#include "emu_dev.h"
int nxfs_init();
int nxfs_end();

View File

@@ -44,7 +44,7 @@ static inline size_t align_to_4(size_t s) {
return ((s + 3) >> 2) << 2;
}
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *emummc, size_t emummc_size) {
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *mesosphere, size_t mesosphere_size, void *emummc, size_t emummc_size) {
package2_header_t *rebuilt_package2;
size_t rebuilt_package2_size;
void *kernel;
@@ -95,10 +95,28 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
fatal_error("Error: inappropriate kernel embedded ini context");
}
/* Use mesosphere instead of Nintendo's kernel when present. */
const bool is_mesosphere = mesosphere != NULL && mesosphere_size != 0;
if (is_mesosphere) {
kernel = mesosphere;
kernel_size = mesosphere_size;
/* Patch mesosphere to use our rebuilt ini. */
*(volatile uint64_t *)((uintptr_t)mesosphere + 8) = (uint64_t)mesosphere_size;
/* Place the kernel section at the correct location. */
package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] = 0x60000;
package2->metadata.entrypoint = 0x60000;
print(SCREEN_LOG_LEVEL_DEBUG, "Using Mesosphere...\n");
}
print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n");
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
} else {
}
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0 || is_mesosphere) {
/* On 8.0.0, place INI1 right after kernelldr for our sanity. */
package2->metadata.section_offsets[PACKAGE2_SECTION_INI1] = package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] + kernel_size;
}

View File

@@ -94,6 +94,6 @@ static inline uint8_t package2_meta_get_header_version(const package2_meta_t *me
return (uint8_t)((metadata->ctr_dwords[1] ^ (metadata->ctr_dwords[1] >> 16) ^ (metadata->ctr_dwords[1] >> 24)) & 0xFF);
}
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *emummc, size_t emummc_size);
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *mesosphere, size_t mesosphere_size, void *emummc, size_t emummc_size);
#endif

View File

@@ -77,9 +77,6 @@ static rawdev_device_t *rawdev_find_device(const char *name) {
int rawdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately) {
rawdev_device_t *device = NULL;
char drname[40];
strcpy(drname, name);
strcat(drname, ":");
if (name[0] == '\0' || devpart == NULL) {
errno = EINVAL;
@@ -205,6 +202,19 @@ int rawdev_unmount_device(const char *name) {
return 0;
}
int rawdev_register_keys(const char *name, unsigned int target_firmware, BisPartition part) {
rawdev_device_t *device = rawdev_find_device(name);
if (device == NULL) {
errno = ENOENT;
return -1;
}
derive_bis_key(device->devpart.keys, part, target_firmware);
return 0;
}
int rawdev_unmount_all(void) {
for (size_t i = 0; i < RAWDEV_MAX_DEVICES; i++) {
int rc = rawdev_unmount_device(g_rawdev_devices[i].name);

View File

@@ -21,6 +21,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "device_partition.h"
#include "key_derivation.h"
#define RAWDEV_MAX_DEVICES 16
@@ -29,6 +30,8 @@ int rawdev_register_device(const char *name);
int rawdev_unregister_device(const char *name);
int rawdev_unmount_device(const char *name); /* also unregisters. */
int rawdev_register_keys(const char *name, unsigned int target_firmware, BisPartition part);
int rawdev_unmount_all(void);
#endif

View File

@@ -30,6 +30,9 @@ _start:
.word (_metadata - _start)
_is_experimental:
.word 0x00000001 /* is experimental */
_crt0:
/* Switch to system mode, mask all interrupts, clear all flags */
msr cpsr_cxsf, #0xDF
@@ -68,6 +71,14 @@ _crt0:
ldr r1, [r1]
b main
.arm
.global fusee_is_experimental
.type fusee_is_experimental, %function
fusee_is_experimental:
ldr r0, =_is_experimental
ldr r0, [r0]
bx lr
/* Fusee-secondary header. */
.align 5
_metadata:
@@ -135,6 +146,17 @@ _content_headers:
.asciz "exosphere"
.align 5
/* mesosphere content header */
.word __mesosphere_bin_start__
.word __mesosphere_bin_size__
.byte CONTENT_TYPE_KRN
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "mesosphere"
.align 5
/* fusee_primary content header */
.word __fusee_primary_bin_start__
.word __fusee_primary_bin_size__
@@ -249,7 +271,7 @@ _content_headers:
.word __ncm_kip_start__
.word __ncm_kip_size__
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG0_EXPERIMENTAL
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
@@ -267,17 +289,6 @@ _content_headers:
.asciz "emummc"
.align 5
/* kernel_ldr content header */
.word __kernel_ldr_bin_start__
.word __kernel_ldr_bin_size__
.byte CONTENT_TYPE_KLD
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "kernel_ldr"
.align 5
/* splash_screen content header */
.word __splash_screen_bmp_start__
.word __splash_screen_bmp_size__

View File

@@ -48,10 +48,9 @@ static bool g_stratosphere_pm_enabled = true;
static bool g_stratosphere_ams_mitm_enabled = true;
static bool g_stratosphere_spl_enabled = true;
static bool g_stratosphere_boot_enabled = true;
static bool g_stratosphere_ncm_enabled = false;
static bool g_stratosphere_ncm_enabled = true;
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, spl_kip_size, boot_kip_size, ncm_kip_size, ams_mitm_kip_size;
static emummc_fs_ver_t g_fs_ver = FS_VER_1_0_0;
@@ -59,17 +58,17 @@ emummc_fs_ver_t stratosphere_get_fs_version(void) {
return g_fs_ver;
}
void stratosphere_enable_ncm(void) {
void stratosphere_disable_ncm(void) {
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
/* and does not think it likely there is any possibility of undesirable behavior */
/* when using the NCM reimplementation. However, because NCM manages critical save games */
/* the implementation will default to off for some time, until the code has been thoroughly */
/* tested in practice. */
/* the implementation may be optionally disabled for those not comfortable using it. */
/* PLEASE NOTE: The default behavior will be NCM on in a future atmosphere release, */
/* and this opt-in functionality will be removed at that time. */
g_stratosphere_ncm_enabled = true;
/* PLEASE NOTE: The NCM reimplementation has been well-tested, and correspondingly opt-out */
/* functionality will be removed in Atmosphere 1.0.0. */
g_stratosphere_ncm_enabled = false;
}
/* GCC doesn't consider the size as const... we have to write it ourselves. */

View File

@@ -30,7 +30,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware);
ini1_header_t *stratosphere_get_sd_files_ini1(void);
void stratosphere_free_ini1(void);
void stratosphere_enable_ncm(void);
void stratosphere_disable_ncm(void);
emummc_fs_ver_t stratosphere_get_fs_version(void);
@@ -39,10 +39,10 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_in
typedef struct {
bool has_nogc_config;
bool enable_nogc;
bool ncm_enabled;
bool ncm_disabled;
} stratosphere_cfg_t;
#define STRATOSPHERE_NOGC_KEY "nogc"
#define STRATOSPHERE_ENABLE_NCM_KEY "enable_ncm"
#define STRATOSPHERE_DISABLE_NCM_KEY "disable_ncm"
#endif

View File

@@ -157,12 +157,18 @@ __attribute__ ((noreturn)) void generic_panic(void) {
}
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
/* Override the global logging level. */
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
/* Display fatal error. */
va_list args;
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
va_start(args, fmt);
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
va_end(args);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n Press POWER to reboot.\n");
/* Wait for button and reboot. */
wait_for_button_and_reboot();
}
@@ -174,37 +180,3 @@ __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, u
return true;
return false;
}
/* Adapted from https://gist.github.com/ccbrown/9722406 */
void hexdump(const void* data, size_t size, uintptr_t addrbase) {
const uint8_t *d = (const uint8_t *)data;
char ascii[17];
ascii[16] = '\0';
for (size_t i = 0; i < size; i++) {
if (i % 16 == 0) {
printf("%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
}
printf("%02X ", d[i]);
if (d[i] >= ' ' && d[i] <= '~') {
ascii[i % 16] = d[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
printf(" ");
if ((i+1) % 16 == 0) {
printf("| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
printf(" ");
}
for (size_t j = (i+1) % 16; j < 16; j++) {
printf(" ");
}
printf("| %s \n", ascii);
}
}
}
}

View File

@@ -118,8 +118,6 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s
overlaps_a(start, end, __start__, __end__);
}
void hexdump(const void* data, size_t size, uintptr_t addrbase);
__attribute__((noreturn)) void watchdog_reboot(void);
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
__attribute__((noreturn)) void reboot_to_fusee_primary(void);
@@ -129,8 +127,6 @@ __attribute__((noreturn)) void wait_for_button_and_reboot(void);
void wait_for_button(void);
__attribute__((noreturn)) void generic_panic(void);
__attribute__((noreturn)) void fatal_error(const char *fmt, ...);
#endif

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = cf8f0c3c1f006e07c0b3976908220d3e7e83f7fa
parent = 033ae1dbe09ba354849caf90ca2a2f114d9b3b4b
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
method = merge
cmdver = 0.4.1

View File

@@ -1,4 +1,4 @@
ATMOSPHERE_LIBRARIES := libmesosphere libstratosphere
ATMOSPHERE_LIBRARIES := libmesosphere libstratosphere libexosphere
TOPTARGETS := all clean

View File

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

View File

@@ -1,5 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_ARM_CORTEX_A57
export ATMOSPHERE_SETTINGS += -mtune=cortex-a57
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mtune=cortex-a57
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@@ -10,16 +10,18 @@ ifeq ($(strip $(ATMOSPHERE_BOARD)),)
export ATMOSPHERE_BOARD := nx-hac-001
ifeq ($(strip $(ATMOSPHERE_CPU)),)
export ATMOSPHERE_CPU := arm-cortex-a57
export ATMOSPHERE_CPU := arm-cortex-a57
endif
endif
ATMOSPHERE_BUILD_SETTINGS ?=
export ATMOSPHERE_DEFINES := -DATMOSPHERE
export ATMOSPHERE_SETTINGS := -fPIE -g
export ATMOSPHERE_SETTINGS := -fPIE -g $(ATMOSPHERE_BUILD_SETTINGS)
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
-Wno-format-truncation
-Wno-format-truncation -Wno-format-zero-length -Wno-stringop-truncation
export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++20
export ATMOSPHERE_ASFLAGS :=
@@ -28,40 +30,44 @@ export ATMOSPHERE_ASFLAGS :=
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
export ATMOSPHERE_ARCH_DIR := arch/arm64
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx
export ATMOSPHERE_OS_DIR := os/horizon
export ATMOSPHERE_ARCH_DIR := arm64
export ATMOSPHERE_BOARD_DIR := nintendo/nx
export ATMOSPHERE_OS_DIR := horizon
export ATMOSPHERE_ARCH_NAME := arm64
export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon
export ATMOSPHERE_CPU_EXTENSIONS := arm_crypto_extension aarch64_crypto_extension
else ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
export ATMOSPHERE_ARCH_DIR := arch/arm
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx_bpmp
export ATMOSPHERE_OS_DIR := os/horizon
export ATMOSPHERE_ARCH_DIR := arm
export ATMOSPHERE_BOARD_DIR := nintendo/nx_bpmp
export ATMOSPHERE_OS_DIR := horizon
export ATMOSPHERE_ARCH_NAME := arm
export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon
export ATMOSPHERE_CPU_EXTENSIONS :=
endif
endif
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
export ATMOSPHERE_CPU_DIR := arch/arm64/cpu/cortex_a57
export ATMOSPHERE_CPU_DIR := cortex_a57
export ATMOSPHERE_CPU_NAME := arm_cortex_a57
endif
ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
export ATMOSPHERE_CPU_DIR := arch/arm/cpu/arm7tdmi
export ATMOSPHERE_CPU_DIR := arm7tdmi
export ATMOSPHERE_CPU_NAME := arm7tdmi
endif
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_ARCH_DIR)
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_BOARD_DIR)
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_OS_DIR)
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_CPU_DIR)
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/arch/$(ATMOSPHERE_ARCH_DIR)
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/board/$(ATMOSPHERE_BOARD_DIR)
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/os/$(ATMOSPHERE_OS_DIR)
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_ARCH_MAKE_DIR)/cpu/$(ATMOSPHERE_CPU_DIR)
export ATMOSPHERE_LIBRARY_DIR := lib_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
export ATMOSPHERE_BUILD_DIR := build_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
@@ -102,16 +108,41 @@ BUILD := build
DATA := data
INCLUDES := include
GENERAL_SOURCE_DIRS=$1 $(foreach d,$(filter-out $1/arch $1/board $1,$(wildcard $1/*)),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
SPECIFIC_SOURCE_DIRS=$(if $(wildcard $1/$2/.*),$1/$2 $(call DIR_WILDCARD,$1/$2),)
ALL_SOURCE_DIRS=$(call GENERAL_SOURCE_DIRS,$1) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_ARCH_DIR)) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_BOARD_DIR)) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_OS_DIR))
GENERAL_SOURCE_DIRS=$1 $(foreach d,$(filter-out $1/arch $1/board $1/os $1/cpu $1,$(wildcard $1/*)),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
SPECIFIC_SOURCE_DIRS=$(if $(wildcard $1/$2/$3/.*),$1/$2/$3 $(call DIR_WILDCARD,$1/$2/$3),$(if $(wildcard $1/$2/generic/.*), $1/$2/generic $(call DIR_WILDCARD,$1/$2/generic),))
UNFILTERED_SOURCE_DIRS=$1 $(foreach d,$(wildcard $1/*),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
ALL_SOURCE_DIRS=$(call GENERAL_SOURCE_DIRS,$1) \
$(call SPECIFIC_SOURCE_DIRS,$1,arch,$(ATMOSPHERE_ARCH_DIR)) \
$(call SPECIFIC_SOURCE_DIRS,$1,board,$(ATMOSPHERE_BOARD_DIR)) \
$(call SPECIFIC_SOURCE_DIRS,$1,os,$(ATMOSPHERE_OS_DIR)) \
$(call SPECIFIC_SOURCE_DIRS,$1,cpu,$(ATMOSPHERE_ARCH_DIR)/$(ATMOSPHERE_CPU_DIR))
SOURCES ?= $(call ALL_SOURCE_DIRS,source)
FIND_SPECIFIC_SOURCE_FILES= $(notdir $(wildcard $1/*.$2.$3.$4)) $(filter-out $(subst .$2.$3.,.$2.generic.,$(notdir $(wildcard $1/*.$2.$3.$4))),$(notdir $(wildcard $1/*.$2.generic.$4)))
FIND_SPECIFIC_SOURCE_FILES_EX=$(foreach ext,$3,$(notdir $(wildcard $1/*.$2.$(ext).$4))) $(filter-out $(foreach ext,$3,$(subst .$2.$(ext).,.$2.generic.,$(notdir $(wildcard $1/*.$2.$(ext).$4)))),$(notdir $(wildcard $1/*.$2.generic.$4)))
FIND_SOURCE_FILES=$(foreach dir,$1,$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.$2)) \
$(notdir $(wildcard $(dir)/*.board.*.$2)) \
$(notdir $(wildcard $(dir)/*.os.*.$2)) \
$(notdir $(wildcard $(dir)/.cpu.*.$2)), \
$(notdir $(wildcard $(dir)/*.$2)))) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),arch,$(ATMOSPHERE_ARCH_NAME),$2)) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),board,$(ATMOSPHERE_BOARD_NAME),$2)) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),os,$(ATMOSPHERE_OS_NAME),$2)) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES_EX,$(dir),cpu,$(ATMOSPHERE_CPU_NAME) $(ATMOSPHERE_CPU_EXTENSIONS),$2))
ATMOSPHERE_GCH_IDENTIFIER ?= ams_placeholder_gch_identifier
#---------------------------------------------------------------------------------
# Rules for compiling pre-compiled headers
#---------------------------------------------------------------------------------
%.gch: %.hpp
@echo $<
$(CXX) -w -x c++-header -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
@cp $@ $(<).gch
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
@echo Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
%.hpp.gch: %.hpp
@echo Precompiling $(notdir $<)
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)

View File

@@ -8,7 +8,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
#---------------------------------------------------------------------------------
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Werror -fno-non-call-exceptions
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Wextra -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)

View File

@@ -7,12 +7,12 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
# options for code generation
#---------------------------------------------------------------------------------
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Werror -fno-non-call-exceptions
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -nostdlib -nostartfiles -g $(SETTINGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -nostdlib -nostartfiles -g $(SETTINGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,__cxa_throw \
@@ -29,7 +29,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
export LIBS := -lmesosphere
export LIBS := -l$(LIBMESOSPHERE_NAME)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

@@ -14,7 +14,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
#---------------------------------------------------------------------------------
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -flto -fno-non-call-exceptions
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Wextra -Werror -flto -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
@@ -39,23 +39,9 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@@ -126,6 +112,7 @@ $(OFILES) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
libc.o: CFLAGS += -fno-builtin -fno-lto
libgcc_division.arch.arm.o: CFLAGS += -fno-builtin -fno-lto
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin

View File

@@ -14,7 +14,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
#---------------------------------------------------------------------------------
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Werror -fno-non-call-exceptions
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Wextra -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
@@ -39,23 +39,9 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -17,7 +17,6 @@
#include <vapours.hpp>
#include <exosphere/common.hpp>
#include <exosphere/reg.hpp>
#include <exosphere/hw.hpp>
#include <exosphere/util.hpp>
#include <exosphere/mmu.hpp>
@@ -41,4 +40,3 @@
#include <exosphere/actmon.hpp>
#include <exosphere/pmc.hpp>
#include <exosphere/secmon.hpp>
#include <exosphere/tegra.hpp>

View File

@@ -19,34 +19,40 @@
namespace ams::pkg1 {
enum AesKeySlot {
AesKeySlot_UserStart = 0,
AesKeySlot_UserStart = 0,
AesKeySlot_TzramSaveKek = 2,
AesKeySlot_TzramSaveKey = 3,
AesKeySlot_TzramSaveKek = 2,
AesKeySlot_TzramSaveKey = 3,
AesKeySlot_UserLast = 5,
AesKeySlot_UserEnd = AesKeySlot_UserLast + 1,
AesKeySlot_UserLast = 5,
AesKeySlot_UserEnd = AesKeySlot_UserLast + 1,
AesKeySlot_SecmonStart = 8,
AesKeySlot_SecmonStart = 8,
AesKeySlot_Temporary = 8,
AesKeySlot_Smc = 9,
AesKeySlot_RandomForUserWrap = 10,
AesKeySlot_RandomForKeyStorageWrap = 11,
AesKeySlot_DeviceMaster = 12,
AesKeySlot_Master = 13,
AesKeySlot_Device = 15,
AesKeySlot_Temporary = 8,
AesKeySlot_Smc = 9,
AesKeySlot_RandomForUserWrap = 10,
AesKeySlot_RandomForKeyStorageWrap = 11,
AesKeySlot_DeviceMaster = 12,
AesKeySlot_Master = 13,
AesKeySlot_Device = 15,
AesKeySlot_SecmonEnd = 16,
AesKeySlot_Count = 16,
AesKeySlot_SecmonEnd = AesKeySlot_Count,
/* Used only during boot. */
AesKeySlot_Tsec = 12,
AesKeySlot_TsecRoot = 13,
AesKeySlot_SecureBoot = 14,
AesKeySlot_SecureStorage = 15,
AesKeySlot_Tsec = 12,
AesKeySlot_TsecRoot = 13,
AesKeySlot_SecureBoot = 14,
AesKeySlot_SecureStorage = 15,
AesKeySlot_MasterKek = 13,
AesKeySlot_DeviceMasterKeySourceKek = 14,
AesKeySlot_DeviceMasterKeySourceKekErista = 10,
AesKeySlot_MasterKek = 13,
AesKeySlot_DeviceMasterKeySourceKekMariko = 14,
/* Mariko only keyslots, used during boot. */
AesKeySlot_MarikoKek = 12,
AesKeySlot_MarikoBek = 13,
};
enum RsaKeySlot {

View File

@@ -26,6 +26,9 @@ namespace ams::se {
void ClearAesKeyIv(int slot);
void LockAesKeySlot(int slot, u32 flags);
/* NOTE: This is Nintendo's API, but if we actually want to use SE2 we should use a different one. */
void ClearAesKeySlot2(int slot);
void SetAesKey(int slot, const void *key, size_t key_size);
void SetEncryptedAesKey128(int dst_slot, int kek_slot, const void *key, size_t key_size);

View File

@@ -18,13 +18,14 @@
namespace ams::se {
void SetRegisterAddress(uintptr_t address);
void SetRegisterAddress(uintptr_t address, uintptr_t address2);
void Initialize();
void SetSecure(bool secure);
void SetTzramSecure();
void SetPerKeySecure();
void SetContextSaveSecure();
void Lockout();

View File

@@ -53,4 +53,8 @@ namespace ams::se {
bool ValidateStickyBits(const StickyBits &bits);
void SaveContext(Context *dst);
void ConfigureAutomaticContextSave();
void SaveContextAutomatic();
void SaveTzramAutomatic();
}

View File

@@ -89,7 +89,13 @@ namespace ams::secmon {
constexpr inline const SecureMonitorConfiguration DefaultSecureMonitorConfiguration = {
.target_firmware = ams::TargetFirmware_Current,
.key_generation = {},
.hardware_type = {},
.soc_type = {},
.hardware_state = {},
.pad_0B = {},
.flags = SecureMonitorConfigurationFlag_Default,
.reserved = {},
};
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <exosphere/tegra/tegra_ahb_arbc.hpp>
#include <exosphere/tegra/tegra_apb_misc.hpp>
#include <exosphere/tegra/tegra_avp_cache.hpp>
#include <exosphere/tegra/tegra_clkrst.hpp>
#include <exosphere/tegra/tegra_emc.hpp>
#include <exosphere/tegra/tegra_evp.hpp>
#include <exosphere/tegra/tegra_flow_ctlr.hpp>
#include <exosphere/tegra/tegra_ictlr.hpp>
#include <exosphere/tegra/tegra_mc.hpp>
#include <exosphere/tegra/tegra_mselect.hpp>
#include <exosphere/tegra/tegra_pinmux.hpp>
#include <exosphere/tegra/tegra_pg_up.hpp>
#include <exosphere/tegra/tegra_pmc.hpp>
#include <exosphere/tegra/tegra_sb.hpp>
#include <exosphere/tegra/tegra_sysctr0.hpp>
#include <exosphere/tegra/tegra_timer.hpp>

View File

@@ -20,14 +20,6 @@ namespace ams::util {
void SetRegisterAddress(uintptr_t address);
u32 GetMicroSeconds();
void WaitMicroSeconds(int us);
void ClearMemory(void *ptr, size_t size);
template<typename T, typename U> requires std::integral<T> && std::integral<U>
constexpr T DivideUp(T x, U y) {
return (x + (y - 1)) / y;
}
}

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