Compare commits
7 Commits
mariko_boo
...
sysupdater
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
838492c84c | ||
|
|
76fa4db2ed | ||
|
|
015537f9bf | ||
|
|
d47e9ec9fd | ||
|
|
4291d81642 | ||
|
|
dc9c9284e2 | ||
|
|
aa9ba17986 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -38,9 +38,6 @@
|
|||||||
*.x86_64
|
*.x86_64
|
||||||
*.hex
|
*.hex
|
||||||
|
|
||||||
# Deko3d shaders
|
|
||||||
*.dksh
|
|
||||||
|
|
||||||
# Switch Executables
|
# Switch Executables
|
||||||
*.nso
|
*.nso
|
||||||
*.nro
|
*.nro
|
||||||
|
|||||||
15
Makefile
15
Makefile
@@ -64,14 +64,13 @@ dist-no-debug: all
|
|||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000003C
|
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/fatal_errors
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/config
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/config
|
||||||
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
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-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
|
||||||
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||||
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/sept/payload.bin
|
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||||
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.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.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
|
||||||
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
|
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
|
||||||
@@ -92,20 +91,14 @@ dist-no-debug: all
|
|||||||
cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036/exefs.nsp
|
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/ro/ro.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/exefs.nsp
|
||||||
cp stratosphere/jpegdec/jpegdec.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000003C/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
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/flags
|
||||||
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/flags/boot2.flag
|
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/flags/boot2.flag
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags
|
||||||
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
|
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
|
||||||
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
||||||
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
|
|
||||||
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 ../;
|
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
|
||||||
rm -r atmosphere-$(AMSVER)
|
rm -r atmosphere-$(AMSVER)
|
||||||
mkdir out
|
mkdir out
|
||||||
mv atmosphere-EXPERIMENTAL-$(AMSVER).zip out/atmosphere-EXPERIMENTAL-$(AMSVER).zip
|
|
||||||
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
|
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
|
||||||
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
|
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
|
||||||
|
|
||||||
@@ -124,7 +117,7 @@ dist: dist-no-debug
|
|||||||
mkdir atmosphere-$(AMSVER)-debug
|
mkdir atmosphere-$(AMSVER)-debug
|
||||||
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
|
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-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
|
||||||
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
cp fusee/fusee-secondary/fusee-secondary.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
||||||
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.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/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
|
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf
|
||||||
@@ -148,8 +141,6 @@ dist: dist-no-debug
|
|||||||
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
|
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
|
||||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
||||||
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.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 ../;
|
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
||||||
rm -r atmosphere-$(AMSVER)-debug
|
rm -r atmosphere-$(AMSVER)-debug
|
||||||
mv atmosphere-$(AMSVER)-debug.zip out/atmosphere-$(AMSVER)-debug.zip
|
mv atmosphere-$(AMSVER)-debug.zip out/atmosphere-$(AMSVER)-debug.zip
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ stage2_entrypoint = 0xF0000000
|
|||||||
; To force-enable nogc, add nogc = 1
|
; To force-enable nogc, add nogc = 1
|
||||||
; To force-disable nogc, add nogc = 0
|
; To force-disable nogc, add nogc = 0
|
||||||
|
|
||||||
; To opt out of using Atmosphere's NCM reimplementation, add disable_ncm = 1
|
; To opt in to using Atmosphere's NCM reimplementation, add enable_ncm = 1
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,7 @@ Building Atmosphère is a very straightforward process that relies almost exclus
|
|||||||
## Dependencies
|
## Dependencies
|
||||||
+ [devkitA64](https://devkitpro.org)
|
+ [devkitA64](https://devkitpro.org)
|
||||||
+ [devkitARM](https://devkitpro.org)
|
+ [devkitARM](https://devkitpro.org)
|
||||||
+ [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed)
|
+ [Python 2 or 3](https://www.python.org) (optional)
|
||||||
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
|
|||||||
@@ -1,81 +1,4 @@
|
|||||||
# Changelog
|
# 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
|
## 0.13.0
|
||||||
+ `exosphère`, atmosphère's secure monitor re-implementation, was completely re-written.
|
+ `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.
|
+ `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.
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ nogc = X
|
|||||||
0 = force-disable nogc, so Atmosphère will always enable the Game Card reader.
|
0 = force-disable nogc, so Atmosphère will always enable the Game Card reader.
|
||||||
```
|
```
|
||||||
|
|
||||||
### NCM opt-out
|
### NCM opt-in
|
||||||
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:
|
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:
|
||||||
```
|
```
|
||||||
[stratosphere]
|
[stratosphere]
|
||||||
disable_ncm = 1
|
enable_ncm = 1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
# Planned Features
|
# Planned Features
|
||||||
atmosphère has a number of features that are either works-in-progress or planned. Please note that while time-estimates are given, they are loose, and things may be completed sooner or later than advertised.
|
atmosphère has a number of features that are either works-in-progress or planned. Please note that while time-estimates are given, they are loose, and things may be completed sooner or later than advertised.
|
||||||
|
|
||||||
The following descriptions were last updated on July 7th, 2020.
|
The following descriptions were last updated on 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
|
||||||
|
|
||||||
## ams-on-mariko
|
## ams-on-mariko
|
||||||
* **Description**: Atmosphere cannot run as-is on Mariko hardware. A large number of changes are needed in many components. Although secure monitor support is complete in exosphere, additional work is needed on the bootloader and stratosphere sides as well. Mariko support will also require further design thought; atmosphere's debugging design heavily relies on reboot-to-payload and (more generally) the ability to perform warmboot bootrom hax at will. This is not possible on Mariko, and will require a new design/software support for whatever solution is chosen.
|
* **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.
|
||||||
* **Development Status**: Planned.
|
* **Development Status**: Planned.
|
||||||
* **Estimated Time**: Summer 2020
|
* **Estimated Time**: Summer 2020
|
||||||
|
|
||||||
@@ -15,7 +20,7 @@ The following descriptions were last updated on July 7th, 2020.
|
|||||||
|
|
||||||
## mesosphere
|
## 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.
|
* **Description**: mesosphère is a reimplementation of the Horizon operating system's Kernel. It aims to provide an open-source reference for Nintendo's code.
|
||||||
* **Development Status**: Under active development by SciresM.
|
* **Development Status**: Under semi-active development by SciresM; temporarily on pause while the System Updater API is completed.
|
||||||
* **Estimated Time**: Mid-to-Late 2020
|
* **Estimated Time**: Mid-to-Late 2020
|
||||||
|
|
||||||
## tma reimplementation
|
## tma reimplementation
|
||||||
@@ -42,21 +47,3 @@ The following descriptions were last updated on July 7th, 2020.
|
|||||||
* **Description**: General system stability improvements to enhance the user's experience.
|
* **Description**: General system stability improvements to enhance the user's experience.
|
||||||
* **Development Status**: Undergoing active development by all members of the atmosphère team.
|
* **Development Status**: Undergoing active development by all members of the atmosphère team.
|
||||||
* **Estimated Time**: June 15th.
|
* **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
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/m4xw/emuMMC
|
remote = https://github.com/m4xw/emuMMC
|
||||||
branch = exo2
|
branch = exo2
|
||||||
commit = 6a814ebbe72cf5245b863b9edea9cd3801437a12
|
commit = 06ab9b895c4264ecc14d3bf9be1260e2096f6037
|
||||||
parent = f551ca4461a79908c37307db10cd8cacf8b98f17
|
parent = dccd41f6d25498c191a157123a27724203d3bc37
|
||||||
method = rebase
|
method = rebase
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -47,8 +47,6 @@
|
|||||||
#include "offsets/910_exfat.h"
|
#include "offsets/910_exfat.h"
|
||||||
#include "offsets/1000.h"
|
#include "offsets/1000.h"
|
||||||
#include "offsets/1000_exfat.h"
|
#include "offsets/1000_exfat.h"
|
||||||
#include "offsets/1020.h"
|
|
||||||
#include "offsets/1020_exfat.h"
|
|
||||||
#include "../utils/fatal.h"
|
#include "../utils/fatal.h"
|
||||||
|
|
||||||
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
|
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
|
||||||
@@ -106,8 +104,6 @@ DEFINE_OFFSET_STRUCT(_910);
|
|||||||
DEFINE_OFFSET_STRUCT(_910_EXFAT);
|
DEFINE_OFFSET_STRUCT(_910_EXFAT);
|
||||||
DEFINE_OFFSET_STRUCT(_1000);
|
DEFINE_OFFSET_STRUCT(_1000);
|
||||||
DEFINE_OFFSET_STRUCT(_1000_EXFAT);
|
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) {
|
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
||||||
switch (version) {
|
switch (version) {
|
||||||
@@ -173,10 +169,6 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
|||||||
return &(GET_OFFSET_STRUCT_NAME(_1000));
|
return &(GET_OFFSET_STRUCT_NAME(_1000));
|
||||||
case FS_VER_10_0_0_EXFAT:
|
case FS_VER_10_0_0_EXFAT:
|
||||||
return &(GET_OFFSET_STRUCT_NAME(_1000_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:
|
default:
|
||||||
fatal_abort(Fatal_UnknownVersion);
|
fatal_abort(Fatal_UnknownVersion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,9 +68,6 @@ enum FS_VER
|
|||||||
FS_VER_10_0_0,
|
FS_VER_10_0_0,
|
||||||
FS_VER_10_0_0_EXFAT,
|
FS_VER_10_0_0_EXFAT,
|
||||||
|
|
||||||
FS_VER_10_2_0,
|
|
||||||
FS_VER_10_2_0_EXFAT,
|
|
||||||
|
|
||||||
FS_VER_MAX,
|
FS_VER_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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__
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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__
|
|
||||||
@@ -24,9 +24,23 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||||
$(TOPDIR)/../program
|
$(TOPDIR)/../program
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
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)))
|
||||||
|
|
||||||
BINFILES := program.lz4 boot_code.lz4
|
BINFILES := program.lz4 boot_code.lz4
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,10 @@
|
|||||||
namespace ams::diag {
|
namespace ams::diag {
|
||||||
|
|
||||||
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) {
|
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();
|
ams::secmon::loader::ErrorReboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) {
|
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();
|
ams::secmon::loader::ErrorReboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,23 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|||||||
$(TOPDIR)/sc7fw \
|
$(TOPDIR)/sc7fw \
|
||||||
$(TOPDIR)/rebootstub
|
$(TOPDIR)/rebootstub
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
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)))
|
||||||
|
|
||||||
BINFILES := sc7fw.bin rebootstub.bin
|
BINFILES := sc7fw.bin rebootstub.bin
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,23 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
|
|||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
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)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
|||||||
@@ -23,9 +23,23 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
|
|||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
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)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ namespace ams::sc7fw {
|
|||||||
reg::ReadWrite(PMC + APBDEV_PMC_DPD_ENABLE, PMC_REG_BITS_ENUM(DPD_ENABLE_ON, ENABLE));
|
reg::ReadWrite(PMC + APBDEV_PMC_DPD_ENABLE, PMC_REG_BITS_ENUM(DPD_ENABLE_ON, ENABLE));
|
||||||
|
|
||||||
/* Wait forever until we're asleep. */
|
/* Wait forever until we're asleep. */
|
||||||
AMS_INFINITE_LOOP();
|
while (true) { /* ... */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -102,9 +102,7 @@ namespace ams::sc7fw {
|
|||||||
NORETURN void ExceptionHandler() {
|
NORETURN void ExceptionHandler() {
|
||||||
/* Write enable to MAIN_RESET. */
|
/* Write enable to MAIN_RESET. */
|
||||||
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
|
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,7 @@ namespace ams::secmon::boot {
|
|||||||
const auto pmc = MemoryRegionVirtualDevicePmc.GetAddress();
|
const auto pmc = MemoryRegionVirtualDevicePmc.GetAddress();
|
||||||
|
|
||||||
/* Set the physical address of the warmboot binary to scratch 1. */
|
/* Set the physical address of the warmboot binary to scratch 1. */
|
||||||
if (GetSocType() == fuse::SocType_Mariko) {
|
reg::Write(pmc + APBDEV_PMC_SCRATCH1, static_cast<u32>(MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware.GetAddress()));
|
||||||
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. */
|
/* Configure logging by setting bits 18-19 of scratch 20. */
|
||||||
reg::ReadWrite(pmc + APBDEV_PMC_SCRATCH20, REG_BITS_VALUE(18, 2, 0));
|
reg::ReadWrite(pmc + APBDEV_PMC_SCRATCH20, REG_BITS_VALUE(18, 2, 0));
|
||||||
@@ -71,76 +66,14 @@ namespace ams::secmon::boot {
|
|||||||
/* The warmboot key as a parameter. The latter is a better solution, but it would be nice to take */
|
/* 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 */
|
/* 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. */
|
/* 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. */
|
/* This function derives the master kek and device keys using the tsec root key. */
|
||||||
void DeriveMasterKekAndDeviceKeyErista(bool is_prod) {
|
/* NOTE: Exosphere does not use this in practice, and expects the bootloader to set up keys already. */
|
||||||
/* 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. */
|
||||||
/* NOTE: This function is currently not implemented. If implemented, it will only be a reference implementation. */
|
[[maybe_unused]]
|
||||||
if constexpr (false) {
|
void DeriveMasterKekAndDeviceKey() {
|
||||||
/* TODO: Consider implementing this as a reference. */
|
/* TODO: Decide whether to implement this. */
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
void SetupRandomKey(int slot, se::KeySlotLockFlags flags) {
|
||||||
@@ -285,9 +218,6 @@ namespace ams::secmon::boot {
|
|||||||
/* Get the current key generation. */
|
/* Get the current key generation. */
|
||||||
const int current_generation = secmon::GetKeyGeneration();
|
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. */
|
/* Iterate for all generations. */
|
||||||
for (int i = 0; i < pkg1::OldDeviceMasterKeyCount; ++i) {
|
for (int i = 0; i < pkg1::OldDeviceMasterKeyCount; ++i) {
|
||||||
const int generation = pkg1::KeyGeneration_4_0_0 + i;
|
const int generation = pkg1::KeyGeneration_4_0_0 + i;
|
||||||
@@ -299,7 +229,7 @@ namespace ams::secmon::boot {
|
|||||||
se::SetEncryptedAesKey128(pkg1::AesKeySlot_Temporary, pkg1::AesKeySlot_Temporary, is_prod ? DeviceMasterKekSourcesProd[i] : DeviceMasterKekSourcesDev[i], se::AesBlockSize);
|
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. */
|
/* Decrypt the device master key source into the work block. */
|
||||||
se::DecryptAes128(work_block, se::AesBlockSize, kek_slot, DeviceMasterKeySourceSources[i], se::AesBlockSize);
|
se::DecryptAes128(work_block, se::AesBlockSize, pkg1::AesKeySlot_DeviceMasterKeySourceKek, DeviceMasterKeySourceSources[i], se::AesBlockSize);
|
||||||
|
|
||||||
/* If we're decrypting the current device master key, decrypt into the keyslot. */
|
/* If we're decrypting the current device master key, decrypt into the keyslot. */
|
||||||
if (generation == current_generation) {
|
if (generation == current_generation) {
|
||||||
@@ -314,11 +244,14 @@ namespace ams::secmon::boot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Clear and lock the Device Master Key Source Kek. */
|
/* Clear and lock the Device Master Key Source Kek. */
|
||||||
se::ClearAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKekMariko);
|
se::ClearAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKek);
|
||||||
se::LockAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKekMariko, se::KeySlotLockFlags_AllLockKek);
|
se::LockAesKeySlot(pkg1::AesKeySlot_DeviceMasterKeySourceKek, se::KeySlotLockFlags_AllLockKek);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeriveAllKeys(bool is_prod) {
|
void DeriveAllKeys() {
|
||||||
|
/* Determine whether we're prod. */
|
||||||
|
const bool is_prod = IsProduction();
|
||||||
|
|
||||||
/* Get the ephemeral work block. */
|
/* Get the ephemeral work block. */
|
||||||
u8 * const work_block = se::GetEphemeralWorkBlock();
|
u8 * const work_block = se::GetEphemeralWorkBlock();
|
||||||
ON_SCOPE_EXIT { util::ClearMemory(work_block, se::AesBlockSize); };
|
ON_SCOPE_EXIT { util::ClearMemory(work_block, se::AesBlockSize); };
|
||||||
@@ -332,9 +265,6 @@ namespace ams::secmon::boot {
|
|||||||
/* Derive the master keys. */
|
/* Derive the master keys. */
|
||||||
DeriveAllMasterKeys(is_prod, work_block);
|
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. */
|
/* Derive the device master keys. */
|
||||||
DeriveAllDeviceMasterKeys(is_prod, work_block);
|
DeriveAllDeviceMasterKeys(is_prod, work_block);
|
||||||
|
|
||||||
@@ -370,21 +300,16 @@ namespace ams::secmon::boot {
|
|||||||
/* Initialize the rng. */
|
/* Initialize the rng. */
|
||||||
se::InitializeRandom();
|
se::InitializeRandom();
|
||||||
|
|
||||||
/* Determine whether we're production. */
|
|
||||||
const bool is_prod = IsProduction();
|
|
||||||
|
|
||||||
/* Derive the master kek and device key. */
|
/* Derive the master kek and device key. */
|
||||||
/* NOTE: This is a no-op on erista, because fusee will have set up keys. */
|
if constexpr (false) {
|
||||||
DeriveMasterKekAndDeviceKey(is_prod);
|
DeriveMasterKekAndDeviceKey();
|
||||||
|
}
|
||||||
|
|
||||||
/* Lock the device key as only usable as a kek. */
|
/* Lock the device key as only usable as a kek. */
|
||||||
se::LockAesKeySlot(pkg1::AesKeySlot_Device, se::KeySlotLockFlags_AllLockKek);
|
se::LockAesKeySlot(pkg1::AesKeySlot_Device, se::KeySlotLockFlags_AllLockKek);
|
||||||
|
|
||||||
/* Derive the master key. */
|
/* Derive all keys. */
|
||||||
DeriveMasterKey();
|
DeriveAllKeys();
|
||||||
|
|
||||||
/* Derive all other keys. */
|
|
||||||
DeriveAllKeys(is_prod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -408,7 +333,6 @@ namespace ams::secmon::boot {
|
|||||||
|
|
||||||
constexpr void UnmapDramImpl(u64 *l1, u64 *l2, u64 *l3) {
|
constexpr void UnmapDramImpl(u64 *l1, u64 *l2, u64 *l3) {
|
||||||
/* Unmap the L1 entry corresponding to to the Dram entries. */
|
/* Unmap the L1 entry corresponding to to the Dram entries. */
|
||||||
AMS_UNUSED(l2, l3);
|
|
||||||
InvalidateL1Entries(l1, MemoryRegionDram.GetAddress(), MemoryRegionDram.GetSize());
|
InvalidateL1Entries(l1, MemoryRegionDram.GetAddress(), MemoryRegionDram.GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,9 +348,6 @@ namespace ams::secmon::boot {
|
|||||||
/* Set the security engine to Per Key Secure. */
|
/* Set the security engine to Per Key Secure. */
|
||||||
se::SetPerKeySecure();
|
se::SetPerKeySecure();
|
||||||
|
|
||||||
/* Set the security engine to Context Save Secure. */
|
|
||||||
se::SetContextSaveSecure();
|
|
||||||
|
|
||||||
/* Setup the PMC registers. */
|
/* Setup the PMC registers. */
|
||||||
SetupPmcRegisters();
|
SetupPmcRegisters();
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace ams::secmon {
|
|||||||
i2c::SetRegisterAddress(i2c::Port_5, MemoryRegionVirtualDeviceI2c5.GetAddress());
|
i2c::SetRegisterAddress(i2c::Port_5, MemoryRegionVirtualDeviceI2c5.GetAddress());
|
||||||
pinmux::SetRegisterAddress(MemoryRegionVirtualDeviceApbMisc.GetAddress(), MemoryRegionVirtualDeviceGpio.GetAddress());
|
pinmux::SetRegisterAddress(MemoryRegionVirtualDeviceApbMisc.GetAddress(), MemoryRegionVirtualDeviceGpio.GetAddress());
|
||||||
pmc::SetRegisterAddress(MemoryRegionVirtualDevicePmc.GetAddress());
|
pmc::SetRegisterAddress(MemoryRegionVirtualDevicePmc.GetAddress());
|
||||||
se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress(), MemoryRegionVirtualDeviceSecurityEngine2.GetAddress());
|
se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress());
|
||||||
uart::SetRegisterAddress(MemoryRegionVirtualDeviceUart.GetAddress());
|
uart::SetRegisterAddress(MemoryRegionVirtualDeviceUart.GetAddress());
|
||||||
wdt::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
|
wdt::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
|
||||||
util::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
|
util::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace ams::secmon {
|
|||||||
u32 mdcr_el2;
|
u32 mdcr_el2;
|
||||||
u32 mdcr_el3;
|
u32 mdcr_el3;
|
||||||
u32 spsr_el3;
|
u32 spsr_el3;
|
||||||
|
u64 dbgbvcr_el1[12];
|
||||||
|
u64 dbgwvcr_el1[ 8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CoreContext {
|
struct CoreContext {
|
||||||
@@ -59,6 +61,30 @@ namespace ams::secmon {
|
|||||||
HW_CPU_GET_MDCR_EL2 (dr.mdcr_el2);
|
HW_CPU_GET_MDCR_EL2 (dr.mdcr_el2);
|
||||||
HW_CPU_GET_MDCR_EL3 (dr.mdcr_el3);
|
HW_CPU_GET_MDCR_EL3 (dr.mdcr_el3);
|
||||||
HW_CPU_GET_SPSR_EL3 (dr.spsr_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) {
|
void RestoreDebugRegisters(const DebugRegisters &dr) {
|
||||||
@@ -74,6 +100,30 @@ namespace ams::secmon {
|
|||||||
HW_CPU_SET_MDCR_EL2 (dr.mdcr_el2);
|
HW_CPU_SET_MDCR_EL2 (dr.mdcr_el2);
|
||||||
HW_CPU_SET_MDCR_EL3 (dr.mdcr_el3);
|
HW_CPU_SET_MDCR_EL3 (dr.mdcr_el3);
|
||||||
HW_CPU_SET_SPSR_EL3 (dr.spsr_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] = {};
|
constinit CoreContext g_core_contexts[NumCores] = {};
|
||||||
|
|||||||
@@ -16,24 +16,10 @@
|
|||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
#include "secmon_error.hpp"
|
#include "secmon_error.hpp"
|
||||||
|
|
||||||
namespace ams {
|
namespace {
|
||||||
|
|
||||||
namespace {
|
constexpr bool SaveSystemStateForDebug = false;
|
||||||
|
|
||||||
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 {
|
namespace ams::diag {
|
||||||
@@ -112,57 +98,6 @@ namespace ams::secmon {
|
|||||||
util::WaitMicroSeconds(1000);
|
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) {
|
void SetError(pkg1::ErrorInfo info) {
|
||||||
@@ -179,14 +114,6 @@ namespace ams::secmon {
|
|||||||
SaveSystemStateForDebugErrorReboot();
|
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. */
|
/* Lockout the security engine. */
|
||||||
se::Lockout();
|
se::Lockout();
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ namespace ams::secmon {
|
|||||||
|
|
||||||
constexpr void UnmapBootCodeImpl(u64 *l1, u64 *l2, u64 *l3, uintptr_t boot_code, size_t boot_code_size) {
|
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. */
|
/* Unmap the L3 entries corresponding to the boot code. */
|
||||||
AMS_UNUSED(l1, l2);
|
|
||||||
InvalidateL3Entries(l3, boot_code, boot_code_size);
|
InvalidateL3Entries(l3, boot_code, boot_code_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +95,10 @@ namespace ams::secmon {
|
|||||||
util::ClearMemory(reinterpret_cast<void *>(address + size / 2), size / 2);
|
util::ClearMemory(reinterpret_cast<void *>(address + size / 2), size / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPhysicalMemoryAddress(uintptr_t address) {
|
||||||
|
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearBootCodeHigh() {
|
void ClearBootCodeHigh() {
|
||||||
@@ -126,10 +129,6 @@ namespace ams::secmon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPhysicalMemoryAddress(uintptr_t address) {
|
|
||||||
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnmapTzram() {
|
void UnmapTzram() {
|
||||||
/* Get the tables. */
|
/* Get the tables. */
|
||||||
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
namespace ams::secmon {
|
namespace ams::secmon {
|
||||||
|
|
||||||
bool IsPhysicalMemoryAddress(uintptr_t address);
|
|
||||||
size_t GetPhysicalMemorySize();
|
size_t GetPhysicalMemorySize();
|
||||||
|
|
||||||
void UnmapTzram();
|
void UnmapTzram();
|
||||||
|
|||||||
@@ -51,27 +51,27 @@ namespace ams::secmon {
|
|||||||
|
|
||||||
constinit bool g_is_cold_boot = true;
|
constinit bool g_is_cold_boot = true;
|
||||||
|
|
||||||
constinit se::StickyBits ExpectedSeStickyBits = {
|
constinit const se::StickyBits ExpectedSeStickyBits = {
|
||||||
.se_security = (1 << 0), /* SE_HARD_SETTING */
|
.se_security = (1 << 0), /* SE_HARD_SETTING */
|
||||||
.tzram_security = 0,
|
.tzram_security = 0,
|
||||||
.crypto_security_perkey = (1 << pkg1::AesKeySlot_UserEnd) - 1,
|
.crypto_security_perkey = (1 << pkg1::AesKeySlot_UserEnd) - 1,
|
||||||
.crypto_keytable_access = {
|
.crypto_keytable_access = {
|
||||||
(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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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 << 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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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 << 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 << 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 << 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 << 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. */
|
(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. */
|
||||||
(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 << 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 << 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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
(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. */
|
(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. */
|
||||||
},
|
},
|
||||||
.rsa_security_perkey = 0,
|
.rsa_security_perkey = 0,
|
||||||
.rsa_keytable_access = {
|
.rsa_keytable_access = {
|
||||||
@@ -139,16 +139,6 @@ namespace ams::secmon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VerifySecurityEngineStickyBits() {
|
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)) {
|
if (!se::ValidateStickyBits(ExpectedSeStickyBits)) {
|
||||||
SetError(pkg1::ErrorInfo_InvalidSecurityEngineStickyBits);
|
SetError(pkg1::ErrorInfo_InvalidSecurityEngineStickyBits);
|
||||||
AMS_ABORT("Invalid sticky bits");
|
AMS_ABORT("Invalid sticky bits");
|
||||||
@@ -648,7 +638,7 @@ namespace ams::secmon {
|
|||||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||||
|
|
||||||
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
||||||
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
|
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||||
|
|
||||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||||
@@ -907,7 +897,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));
|
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. */
|
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
||||||
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
|
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||||
|
|
||||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||||
@@ -948,16 +938,12 @@ namespace ams::secmon {
|
|||||||
return reg::Read(MC + MC_SECURITY_CFG3) == 0;
|
return reg::Read(MC + MC_SECURITY_CFG3) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupLogForBoot() {
|
|
||||||
log::Initialize();
|
|
||||||
log::SendText("OHAYO\n", 6);
|
|
||||||
log::Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogExitLp0() {
|
void LogExitLp0() {
|
||||||
/* NOTE: Nintendo only does this on dev, but we will always do it. */
|
/* NOTE: Nintendo only does this on dev, but we will always do it. */
|
||||||
if (true /* !pkg1::IsProduction() */) {
|
if (true /* !pkg1::IsProduction() */) {
|
||||||
SetupLogForBoot();
|
log::Initialize();
|
||||||
|
log::SendText("OHAYO\n", 6);
|
||||||
|
log::Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,7 +969,7 @@ namespace ams::secmon {
|
|||||||
InitializeConfigurationContext();
|
InitializeConfigurationContext();
|
||||||
|
|
||||||
/* Initialize uart for logging. */
|
/* Initialize uart for logging. */
|
||||||
SetupLogForBoot();
|
log::Initialize();
|
||||||
|
|
||||||
/* Initialize the security engine. */
|
/* Initialize the security engine. */
|
||||||
se::Initialize();
|
se::Initialize();
|
||||||
@@ -1031,16 +1017,12 @@ namespace ams::secmon {
|
|||||||
|
|
||||||
/* Overwrite keys that we want to be random with random contents. */
|
/* Overwrite keys that we want to be random with random contents. */
|
||||||
se::InitializeRandom();
|
se::InitializeRandom();
|
||||||
se::ConfigureAutomaticContextSave();
|
|
||||||
se::SetRandomKey(pkg1::AesKeySlot_Temporary);
|
se::SetRandomKey(pkg1::AesKeySlot_Temporary);
|
||||||
se::GenerateSrk();
|
se::GenerateSrk();
|
||||||
se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek);
|
se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek);
|
||||||
|
|
||||||
/* Initialize pmc secure scratch. */
|
/* Initialize pmc secure scratch. */
|
||||||
if (GetSocType() == fuse::SocType_Erista) {
|
pmc::InitializeRandomScratch();
|
||||||
pmc::InitializeRandomScratch();
|
|
||||||
}
|
|
||||||
pmc::LockSecureRegister(pmc::SecureRegister_Srk);
|
|
||||||
|
|
||||||
/* Setup secure registers. */
|
/* Setup secure registers. */
|
||||||
SetupSecureRegisters();
|
SetupSecureRegisters();
|
||||||
|
|||||||
@@ -264,13 +264,6 @@ namespace ams::secmon {
|
|||||||
{
|
{
|
||||||
reg::Write(AHB_ARBC(AHB_GIZMO_TZRAM), (1u << 7));
|
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() {
|
void SetupSocDmaControllersCpuMemoryControllersEnableMmuWarmboot() {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ SetRegisterAllowed(MC_SMMU_CONFIG); /* 0x010 */
|
|||||||
SetRegisterAllowed(MC_SMMU_PTB_ASID); /* 0x01C */
|
SetRegisterAllowed(MC_SMMU_PTB_ASID); /* 0x01C */
|
||||||
SetRegisterAllowed(MC_SMMU_PTB_DATA); /* 0x020 */
|
SetRegisterAllowed(MC_SMMU_PTB_DATA); /* 0x020 */
|
||||||
SetRegisterAllowed(MC_SMMU_TLB_FLUSH); /* 0x030 */
|
SetRegisterAllowed(MC_SMMU_TLB_FLUSH); /* 0x030 */
|
||||||
SetRegisterAllowed(MC_SMMU_PTC_FLUSH_0); /* 0x034 */
|
SetRegisterAllowed(MC_SMMU_PTC_FLUSH); /* 0x034 */
|
||||||
SetRegisterAllowed(MC_EMEM_CFG); /* 0x050 */
|
SetRegisterAllowed(MC_EMEM_CFG); /* 0x050 */
|
||||||
SetRegisterAllowed(MC_EMEM_ADR_CFG); /* 0x054 */
|
SetRegisterAllowed(MC_EMEM_ADR_CFG); /* 0x054 */
|
||||||
SetRegisterAllowed(MC_EMEM_ARB_CFG); /* 0x090 */
|
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_HC_ASID); /* 0x250 */
|
||||||
SetRegisterAllowed(MC_SMMU_HDA_ASID); /* 0x254 */
|
SetRegisterAllowed(MC_SMMU_HDA_ASID); /* 0x254 */
|
||||||
SetRegisterAllowed(MC_SMMU_ISP2_ASID); /* 0x258 */
|
SetRegisterAllowed(MC_SMMU_ISP2_ASID); /* 0x258 */
|
||||||
SetRegisterAllowed(MC_SMMU_MSENC_NVENC_ASID); /* 0x264 */
|
SetRegisterAllowed(MC_SMMU_NVENC_ASID); /* 0x264 */
|
||||||
SetRegisterAllowed(MC_SMMU_NV_ASID); /* 0x268 */
|
SetRegisterAllowed(MC_SMMU_NV_ASID); /* 0x268 */
|
||||||
SetRegisterAllowed(MC_SMMU_NV2_ASID); /* 0x26C */
|
SetRegisterAllowed(MC_SMMU_NV2_ASID); /* 0x26C */
|
||||||
SetRegisterAllowed(MC_SMMU_PPCS_ASID); /* 0x270 */
|
SetRegisterAllowed(MC_SMMU_PPCS_ASID); /* 0x270 */
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ namespace ams::secmon::smc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PrepareDeviceMasterKey(int generation) {
|
int PrepareDeviceMasterKey(int generation) {
|
||||||
if (generation == pkg1::KeyGeneration_1_0_0 && GetSocType() == fuse::SocType_Erista) {
|
if (generation == pkg1::KeyGeneration_1_0_0) {
|
||||||
return pkg1::AesKeySlot_Device;
|
return pkg1::AesKeySlot_Device;
|
||||||
}
|
}
|
||||||
if (generation == GetKeyGeneration()) {
|
if (generation == GetKeyGeneration()) {
|
||||||
|
|||||||
@@ -141,9 +141,6 @@ namespace ams::secmon::smc {
|
|||||||
{ 0xC3000006, Restriction_Normal, SmcShowError },
|
{ 0xC3000006, Restriction_Normal, SmcShowError },
|
||||||
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
|
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
|
||||||
{ 0xC3000008, Restriction_Normal, SmcReadWriteRegister },
|
{ 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[] = {
|
constinit HandlerInfo g_ams_handlers[] = {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
#include "../secmon_error.hpp"
|
#include "../secmon_error.hpp"
|
||||||
#include "../secmon_map.hpp"
|
|
||||||
#include "../secmon_misc.hpp"
|
#include "../secmon_misc.hpp"
|
||||||
#include "../secmon_page_mapper.hpp"
|
#include "../secmon_page_mapper.hpp"
|
||||||
#include "../secmon_user_power_management.hpp"
|
#include "../secmon_user_power_management.hpp"
|
||||||
@@ -158,8 +157,6 @@ namespace ams::secmon::smc {
|
|||||||
return value.value;
|
return value.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
constinit u64 g_payload_address = 0;
|
|
||||||
|
|
||||||
SmcResult GetConfig(SmcArguments &args, bool kern) {
|
SmcResult GetConfig(SmcArguments &args, bool kern) {
|
||||||
switch (static_cast<ConfigItem>(args.r[1])) {
|
switch (static_cast<ConfigItem>(args.r[1])) {
|
||||||
case ConfigItem::DisableProgramVerification:
|
case ConfigItem::DisableProgramVerification:
|
||||||
@@ -265,19 +262,6 @@ namespace ams::secmon::smc {
|
|||||||
/* Get whether this unit should allow writing to the calibration partition. */
|
/* Get whether this unit should allow writing to the calibration partition. */
|
||||||
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() || GetSecmonConfiguration().AllowWritingToCalibrationBinarySysmmc());
|
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() || GetSecmonConfiguration().AllowWritingToCalibrationBinarySysmmc());
|
||||||
break;
|
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:
|
default:
|
||||||
return SmcResult::InvalidArgument;
|
return SmcResult::InvalidArgument;
|
||||||
}
|
}
|
||||||
@@ -320,17 +304,6 @@ namespace ams::secmon::smc {
|
|||||||
return SmcResult::NotImplemented;
|
return SmcResult::NotImplemented;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
return SmcResult::InvalidArgument;
|
return SmcResult::InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ namespace ams::secmon::smc {
|
|||||||
ExosphereHasRcmBugPatch = 65004,
|
ExosphereHasRcmBugPatch = 65004,
|
||||||
ExosphereBlankProdInfo = 65005,
|
ExosphereBlankProdInfo = 65005,
|
||||||
ExosphereAllowCalWrites = 65006,
|
ExosphereAllowCalWrites = 65006,
|
||||||
ExosphereEmummcType = 65007,
|
|
||||||
ExospherePayloadAddress = 65008,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ namespace ams::secmon::smc {
|
|||||||
|
|
||||||
SmcResult SmcWriteAddress(SmcArguments &args) {
|
SmcResult SmcWriteAddress(SmcArguments &args) {
|
||||||
/* NOTE: This smc was deprecated in Atmosphère 0.13.0. */
|
/* NOTE: This smc was deprecated in Atmosphère 0.13.0. */
|
||||||
AMS_UNUSED(args);
|
|
||||||
return SmcResult::NotImplemented;
|
return SmcResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -325,11 +325,7 @@ namespace ams::secmon::smc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SaveSecureContextForMariko() {
|
void SaveSecureContextForMariko() {
|
||||||
/* Save security engine context to TZRAM SE carveout (inaccessible to cpu). */
|
/* TODO: Implement this when adding ams-on-mariko support. */
|
||||||
se::SaveContextAutomatic();
|
|
||||||
|
|
||||||
/* Save TZRAM to shadow-TZRAM in always-on power domain. */
|
|
||||||
se::SaveTzramAutomatic();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveSecureContext() {
|
void SaveSecureContext() {
|
||||||
@@ -492,8 +488,6 @@ namespace ams::secmon::smc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SmcResult SmcPowerOffCpu(SmcArguments &args) {
|
SmcResult SmcPowerOffCpu(SmcArguments &args) {
|
||||||
AMS_UNUSED(args);
|
|
||||||
|
|
||||||
/* Get the current core id. */
|
/* Get the current core id. */
|
||||||
const auto core_id = hw::GetCurrentCoreId();
|
const auto core_id = hw::GetCurrentCoreId();
|
||||||
|
|
||||||
|
|||||||
@@ -155,27 +155,10 @@ namespace ams::secmon::smc {
|
|||||||
/* Find the access table. */
|
/* Find the access table. */
|
||||||
const AccessTableEntry * const entry = GetAccessTableEntry(address);
|
const AccessTableEntry * const entry = GetAccessTableEntry(address);
|
||||||
|
|
||||||
/* Translate our entry into an address to access. */
|
/* If we have a table, perform the write. */
|
||||||
uintptr_t virtual_address = 0;
|
|
||||||
if (entry != nullptr) {
|
if (entry != nullptr) {
|
||||||
/* Get the address to read or write. */
|
/* Get the address to read or write. */
|
||||||
virtual_address = entry->virtual_address + (address - entry->address);
|
const uintptr_t 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;
|
u32 out = 0;
|
||||||
|
|
||||||
if (mask != ~static_cast<u32>(0)) {
|
if (mask != ~static_cast<u32>(0)) {
|
||||||
@@ -186,6 +169,13 @@ namespace ams::secmon::smc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.r[1] = out;
|
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;
|
return SmcResult::Success;
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ namespace ams::secmon::smc {
|
|||||||
u8 msg[se::RsaSize];
|
u8 msg[se::RsaSize];
|
||||||
public:
|
public:
|
||||||
void Set(const void *m, size_t m_size) {
|
void Set(const void *m, size_t m_size) {
|
||||||
AMS_UNUSED(m_size);
|
|
||||||
std::memcpy(this->msg, m, sizeof(this->msg));
|
std::memcpy(this->msg, m, sizeof(this->msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,7 @@ import sys, lz4
|
|||||||
from struct import unpack as up
|
from struct import unpack as up
|
||||||
|
|
||||||
def lz4_compress(data):
|
def lz4_compress(data):
|
||||||
try:
|
return lz4.block.compress(data, 'high_compression', store_size=False)
|
||||||
import lz4.block as block
|
|
||||||
except ImportError:
|
|
||||||
block = lz4.LZ4_compress
|
|
||||||
return block.compress(data, 'high_compression', store_size=False)
|
|
||||||
|
|
||||||
def split_binary(data):
|
def split_binary(data):
|
||||||
A, B, START, BOOT_CODE_START, BOOT_CODE_END, PROGRAM_START, C, D = up('<QQQQQQQQ', data[:0x40])
|
A, B, START, BOOT_CODE_START, BOOT_CODE_END, PROGRAM_START, C, D = up('<QQQQQQQQ', data[:0x40])
|
||||||
@@ -23,7 +19,7 @@ def split_binary(data):
|
|||||||
|
|
||||||
def main(argc, argv):
|
def main(argc, argv):
|
||||||
if argc != 3:
|
if argc != 3:
|
||||||
print('Usage: %s in outdir' % argv[0])
|
print 'Usage: %s in outdir' % argv[0]
|
||||||
return 1
|
return 1
|
||||||
with open(argv[1], 'rb') as f:
|
with open(argv[1], 'rb') as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
#---------------------------------------------------------------------------------
|
|
||||||
# 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
|
|
||||||
#---------------------------------------------------------------------------------------
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
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) }
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
%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
|
|
||||||
@@ -1,146 +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 <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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,37 +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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.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
|
|
||||||
@@ -23,9 +23,23 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
|
|||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
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)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
|||||||
@@ -90,9 +90,7 @@ namespace ams::warmboot {
|
|||||||
NORETURN void ExceptionHandler() {
|
NORETURN void ExceptionHandler() {
|
||||||
/* Write enable to MAIN_RESET. */
|
/* Write enable to MAIN_RESET. */
|
||||||
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
|
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ _ZN3ams8warmboot5StartEv:
|
|||||||
|
|
||||||
/* Invoke main. */
|
/* Invoke main. */
|
||||||
ldr r0, =_metadata
|
ldr r0, =_metadata
|
||||||
b _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
bl _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
||||||
|
|
||||||
/* Infinite loop. */
|
/* Infinite loop. */
|
||||||
1: b 1b
|
1: b 1b
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
#ifndef FUSEE_LOG_H
|
#ifndef FUSEE_LOG_H
|
||||||
#define FUSEE_LOG_H
|
#define FUSEE_LOG_H
|
||||||
|
|
||||||
#define PRINT_MESSAGE_MAX_LENGTH 1024
|
#define PRINT_MESSAGE_MAX_LENGTH 512
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|||||||
@@ -17,26 +17,17 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "display/video_fb.h"
|
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
|
|
||||||
__attribute__ ((noreturn)) void generic_panic(void) {
|
__attribute__ ((noreturn)) void generic_panic(void) {
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR, "Panic raised!");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Lock. */
|
/* Lock. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
__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;
|
va_list args;
|
||||||
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|||||||
@@ -19,10 +19,9 @@
|
|||||||
#include "exception_handlers.h"
|
#include "exception_handlers.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
#include "lib/vsprintf.h"
|
|
||||||
|
|
||||||
#define CODE_DUMP_SIZE 0x30
|
#define CODE_DUMP_SIZE 0x30
|
||||||
#define STACK_DUMP_SIZE 0x30
|
#define STACK_DUMP_SIZE 0x60
|
||||||
|
|
||||||
extern const uint32_t exception_handler_table[];
|
extern const uint32_t exception_handler_table[];
|
||||||
|
|
||||||
@@ -35,40 +34,6 @@ static const char *register_names[] = {
|
|||||||
"SP", "LR", "PC", "CPSR",
|
"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) {
|
void setup_exception_handlers(void) {
|
||||||
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
|
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
@@ -79,40 +44,38 @@ void setup_exception_handlers(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
|
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
|
||||||
char exception_log[0x400] = {0};
|
uint8_t code_dump[CODE_DUMP_SIZE];
|
||||||
uint8_t code_dump[CODE_DUMP_SIZE] = {0};
|
uint8_t stack_dump[STACK_DUMP_SIZE];
|
||||||
uint8_t stack_dump[STACK_DUMP_SIZE] = {0};
|
size_t code_dump_size;
|
||||||
size_t code_dump_size = 0;
|
size_t stack_dump_size;
|
||||||
size_t stack_dump_size = 0;
|
|
||||||
|
|
||||||
uint32_t pc = registers[15];
|
uint32_t pc = registers[15];
|
||||||
uint32_t cpsr = registers[16];
|
uint32_t cpsr = registers[16];
|
||||||
|
|
||||||
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
|
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
|
||||||
|
|
||||||
sprintf(exception_log, "An exception occured!\n");
|
print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
|
||||||
|
|
||||||
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE);
|
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);
|
stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
|
||||||
|
|
||||||
sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
|
||||||
sprintf(exception_log + strlen(exception_log), "\nRegisters:\n");
|
exception_names[exception_type]);
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n");
|
||||||
|
|
||||||
/* Print r0 to pc. */
|
/* Print r0 to pc. */
|
||||||
for (int i = 0; i < 16; i += 2) {
|
for (int i = 0; i < 16; i += 2) {
|
||||||
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
|
||||||
register_names[i], registers[i], register_names[i+1], registers[i+1]);
|
register_names[i], registers[i], register_names[i+1], registers[i+1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print cpsr. */
|
/* Print cpsr. */
|
||||||
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
|
||||||
|
|
||||||
/* Print code and stack regions. */
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n");
|
||||||
sprintf(exception_log + strlen(exception_log), "\nCode dump:\n");
|
hexdump(code_dump, code_dump_size, instr_addr);
|
||||||
hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log));
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n");
|
||||||
sprintf(exception_log + strlen(exception_log), "\nStack dump:\n");
|
hexdump(stack_dump, stack_dump_size, registers[13]);
|
||||||
hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log));
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
|
||||||
sprintf(exception_log + strlen(exception_log), "\n");
|
fatal_error("An exception occured!\n");
|
||||||
|
|
||||||
/* Throw fatal error with the full exception log. */
|
|
||||||
fatal_error(exception_log);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#ifndef FUSEE_LOG_H
|
#ifndef FUSEE_LOG_H
|
||||||
#define FUSEE_LOG_H
|
#define FUSEE_LOG_H
|
||||||
|
|
||||||
#define PRINT_MESSAGE_MAX_LENGTH 1024
|
#define PRINT_MESSAGE_MAX_LENGTH 512
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
#include "display/video_fb.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 uint32_t g_panic_code = 0;
|
||||||
|
|
||||||
static const char *get_error_desc_str(uint32_t error_desc) {
|
static const char *get_error_desc_str(uint32_t error_desc) {
|
||||||
@@ -45,10 +42,6 @@ static const char *get_error_desc_str(uint32_t error_desc) {
|
|||||||
return "SError";
|
return "SError";
|
||||||
case 0x301:
|
case 0x301:
|
||||||
return "Bad SVC";
|
return "Bad SVC";
|
||||||
case 0xF00:
|
|
||||||
return "Kernel Panic";
|
|
||||||
case 0xFFD:
|
|
||||||
return "Stack overflow";
|
|
||||||
case 0xFFE:
|
case 0xFFE:
|
||||||
return "std::abort() called";
|
return "std::abort() called";
|
||||||
default:
|
default:
|
||||||
@@ -56,61 +49,6 @@ 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) {
|
static void _check_and_display_atmosphere_fatal_error(void) {
|
||||||
/* Check for valid magic. */
|
/* Check for valid magic. */
|
||||||
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
|
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
|
||||||
@@ -144,7 +82,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
|||||||
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic = 0xCCCCCCCC;
|
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, "A fatal error occurred when running Atmosph\xe8re.\n");
|
||||||
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, "Title ID: %016llx\n", ctx.title_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);
|
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. */
|
/* Save context to the SD card. */
|
||||||
@@ -152,18 +90,12 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
|||||||
char filepath[0x40];
|
char filepath[0x40];
|
||||||
snprintf(filepath, sizeof(filepath) - 1, "/atmosphere/fatal_errors/report_%016llx.bin", ctx.report_identifier);
|
snprintf(filepath, sizeof(filepath) - 1, "/atmosphere/fatal_errors/report_%016llx.bin", ctx.report_identifier);
|
||||||
filepath[sizeof(filepath)-1] = 0;
|
filepath[sizeof(filepath)-1] = 0;
|
||||||
if (write_to_file(&ctx, sizeof(ctx), filepath) != sizeof(ctx)) {
|
write_to_file(&ctx, sizeof(ctx), filepath);
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Failed to save report to the SD card!\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"Report saved to %s\n", filepath);
|
||||||
} 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. */
|
/* 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. */
|
/* Wait for button and reboot. */
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t error_desc;
|
uint32_t error_desc;
|
||||||
uint64_t program_id;
|
uint64_t title_id;
|
||||||
union {
|
union {
|
||||||
uint64_t gprs[32];
|
uint64_t gprs[32];
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ void load_stage2(const char *bct0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) {
|
if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) {
|
||||||
fatal_error("Stage2's path name is too big!\n");
|
print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_32bit_address_loadable(config.entrypoint)) {
|
if (!check_32bit_address_loadable(config.entrypoint)) {
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "car.h"
|
#include "car.h"
|
||||||
#include "btn.h"
|
#include "btn.h"
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
#include "lib/vsprintf.h"
|
|
||||||
#include "display/video_fb.h"
|
#include "display/video_fb.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@@ -113,10 +112,10 @@ __attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
|||||||
/* Turn on the backlight after initializing the lfb */
|
/* Turn on the backlight after initializing the lfb */
|
||||||
/* to avoid flickering. */
|
/* to avoid flickering. */
|
||||||
display_backlight(true);
|
display_backlight(true);
|
||||||
}
|
|
||||||
|
|
||||||
/* Override the global logging level. */
|
/* Override the global logging level. */
|
||||||
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
|
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
/* Display fatal error. */
|
/* Display fatal error. */
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -138,3 +137,37 @@ __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, u
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -117,12 +117,15 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s
|
|||||||
overlaps_a(start, end, __start__, __end__);
|
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 watchdog_reboot(void);
|
||||||
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
||||||
__attribute__((noreturn)) void reboot_to_self(void);
|
__attribute__((noreturn)) void reboot_to_self(void);
|
||||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
|
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
|
||||||
|
|
||||||
__attribute__((noreturn)) void generic_panic(void);
|
__attribute__((noreturn)) void generic_panic(void);
|
||||||
|
|
||||||
__attribute__((noreturn)) void fatal_error(const char *fmt, ...);
|
__attribute__((noreturn)) void fatal_error(const char *fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||||
$(AMS)/exosphere $(AMS)/exosphere/warmboot $(AMS)/exosphere/program/rebootstub \
|
$(AMS)/exosphere $(AMS)/exosphere/warmboot $(AMS)/exosphere/program/rebootstub \
|
||||||
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
|
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
|
||||||
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
|
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
|
||||||
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
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 \
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
|
||||||
exosphere.bin warmboot.bin rebootstub.bin thermosphere.bin splash_screen.bmp \
|
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-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \
|
||||||
sept-secondary_dev_00.enc sept-secondary_dev_01.enc mesosphere.bin kernel_ldr.bin $(KIPFILES)
|
sept-secondary_dev_00.enc sept-secondary_dev_01.enc kernel_ldr.bin $(KIPFILES)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
@@ -186,15 +186,11 @@ DEPENDS := $(OFILES:.o=.d)
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all : $(OUTPUT).bin
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
$(OUTPUT).bin : $(OUTPUT)-experimental.bin
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
@python $(TOPDIR)/fusee_make_standard.py $(OUTPUT)-experimental.bin $(OUTPUT).bin
|
|
||||||
@echo built ... $(notdir $@)
|
|
||||||
|
|
||||||
$(OUTPUT)-experimental.bin : $(OUTPUT)-experimental.elf
|
|
||||||
$(OBJCOPY) -S -O binary $< $@
|
$(OBJCOPY) -S -O binary $< $@
|
||||||
@echo built ... $(notdir $@)
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
$(OUTPUT)-experimental.elf : $(OFILES)
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
%.elf: $(OFILES)
|
%.elf: $(OFILES)
|
||||||
@echo linking $(notdir $@)
|
@echo linking $(notdir $@)
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
#!/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))
|
|
||||||
@@ -254,6 +254,4 @@ SECTIONS
|
|||||||
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
|
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
|
||||||
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
|
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
|
||||||
PROVIDE(__kernel_ldr_bin_size__ = kernel_ldr_bin_end - kernel_ldr_bin);
|
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,27 +37,23 @@
|
|||||||
|
|
||||||
/* Clock and reset devices. */
|
/* Clock and reset devices. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CARDEVICE_BPMP = ((0 << 5) | 0x1),
|
CARDEVICE_UARTA = ((0 << 5) | 0x6),
|
||||||
CARDEVICE_UARTA = ((0 << 5) | 0x6),
|
CARDEVICE_UARTB = ((0 << 5) | 0x7),
|
||||||
CARDEVICE_UARTB = ((0 << 5) | 0x7),
|
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||||
CARDEVICE_USBD = ((0 << 5) | 0x16),
|
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||||
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_AHBDMA = ((1 << 5) | 0x1),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
CARDEVICE_APBDMA = ((1 << 5) | 0x2),
|
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||||
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
|
||||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
|
||||||
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
|
||||||
|
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
|
||||||
|
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
|
||||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
CARDEVICE_BPMP = ((0 << 5) | 0x1)
|
||||||
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;
|
} CarDevice;
|
||||||
|
|
||||||
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
||||||
|
|||||||
@@ -18,9 +18,67 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "device_partition.h"
|
#include "device_partition.h"
|
||||||
|
|
||||||
int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {
|
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 rc = 0;
|
int rc = 0;
|
||||||
uint64_t target_sector = sector;
|
uint64_t target_sector = sector;
|
||||||
|
char target_path[0x300 + 1] = {0};
|
||||||
|
|
||||||
/* Perform initialization steps, if necessary. */
|
/* Perform initialization steps, if necessary. */
|
||||||
if (!devpart->initialized) {
|
if (!devpart->initialized) {
|
||||||
@@ -30,37 +88,33 @@ int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle emulation. */
|
/* Prepare the right file path if using file mode. */
|
||||||
if (devpart->is_emulated) {
|
if (devpart->emu_use_file && (origin_path != NULL)) {
|
||||||
/* Prepare the right file path if using file mode. */
|
/* Handle data in multiple parts, if necessary. */
|
||||||
if (devpart->emu_use_file) {
|
if (num_parts > 0) {
|
||||||
int num_parts = devpart->emu_num_parts;
|
int target_part = 0;
|
||||||
uint64_t part_limit = devpart->emu_part_limit;
|
uint64_t data_offset = sector * devpart->sector_size;
|
||||||
|
|
||||||
/* Handle data in multiple parts, if necessary. */
|
if (data_offset >= part_limit) {
|
||||||
if (num_parts > 0) {
|
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
|
||||||
int target_part = 0;
|
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
|
||||||
char target_path[0x300 + 1] = {0};
|
target_sector = (data_offset - (target_part * part_limit)) / devpart->sector_size;
|
||||||
uint64_t data_offset = sector * devpart->sector_size;
|
|
||||||
|
|
||||||
if (data_offset >= part_limit) {
|
/* Target part is invalid. */
|
||||||
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
|
if (target_part > num_parts) {
|
||||||
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
|
return -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. */
|
/* Read the partition data. */
|
||||||
@@ -93,9 +147,11 @@ int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) {
|
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 rc = 0;
|
int rc = 0;
|
||||||
uint64_t target_sector = sector;
|
uint64_t target_sector = sector;
|
||||||
|
char target_path[0x300 + 1] = {0};
|
||||||
|
|
||||||
/* Perform initialization steps, if necessary. */
|
/* Perform initialization steps, if necessary. */
|
||||||
if (!devpart->initialized) {
|
if (!devpart->initialized) {
|
||||||
@@ -105,37 +161,33 @@ int device_partition_write_data(device_partition_t *devpart, const void *src, ui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle emulation. */
|
/* Prepare the right file path if using file mode. */
|
||||||
if (devpart->is_emulated) {
|
if (devpart->emu_use_file && (origin_path != NULL)) {
|
||||||
/* Prepare the right file path if using file mode. */
|
/* Handle data in multiple parts, if necessary. */
|
||||||
if (devpart->emu_use_file) {
|
if (num_parts > 0) {
|
||||||
int num_parts = devpart->emu_num_parts;
|
int target_part = 0;
|
||||||
uint64_t part_limit = devpart->emu_part_limit;
|
uint64_t data_offset = sector * devpart->sector_size;
|
||||||
|
|
||||||
/* Handle data in multiple parts, if necessary. */
|
if (data_offset >= part_limit) {
|
||||||
if (num_parts > 0) {
|
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
|
||||||
int target_part = 0;
|
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
|
||||||
char target_path[0x300 + 1] = {0};
|
target_sector = (data_offset - (target_part * part_limit)) / devpart->sector_size;
|
||||||
uint64_t data_offset = sector * devpart->sector_size;
|
|
||||||
|
|
||||||
if (data_offset >= part_limit) {
|
/* Target part is invalid. */
|
||||||
uint64_t data_offset_aligned = (data_offset + (part_limit - 1)) & ~(part_limit - 1);
|
if (target_part > num_parts) {
|
||||||
target_part = (data_offset_aligned == data_offset) ? (data_offset / part_limit) : (data_offset_aligned / part_limit) - 1;
|
return -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. */
|
/* Write the partition data. */
|
||||||
|
|||||||
@@ -67,16 +67,13 @@ typedef struct device_partition_t {
|
|||||||
uint8_t __attribute__((aligned(16))) iv[DEVPART_IV_MAX_SIZE]; /* IV. */
|
uint8_t __attribute__((aligned(16))) iv[DEVPART_IV_MAX_SIZE]; /* IV. */
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
|
||||||
/* Emulation only. */
|
char *emu_file_path; /* Emulated device file path. */
|
||||||
bool is_emulated;
|
|
||||||
bool emu_use_file;
|
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;
|
} device_partition_t;
|
||||||
|
|
||||||
int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors);
|
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 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
|
#endif
|
||||||
|
|||||||
489
fusee/fusee-secondary/src/emu_dev.c
Normal file
489
fusee/fusee-secondary/src/emu_dev.c
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
@@ -13,25 +13,22 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
|
||||||
#include <vapours.hpp>
|
|
||||||
|
|
||||||
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
#ifndef FUSEE_EMU_DEV_H
|
||||||
|
#define FUSEE_EMU_DEV_H
|
||||||
|
|
||||||
#include <stratosphere/wec/wec_wake_event.board.nintendo_nx.hpp>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "device_partition.h"
|
||||||
|
|
||||||
#else
|
#define EMUDEV_MAX_DEVICES 16
|
||||||
|
|
||||||
#error "Unknown board for ams::wec::WakeEvent"
|
int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path, int num_parts, uint64_t part_limit);
|
||||||
|
int emudev_register_device(const char *name);
|
||||||
|
int emudev_unregister_device(const char *name);
|
||||||
|
int emudev_unmount_device(const char *name); /* also unregisters. */
|
||||||
|
|
||||||
|
int emudev_unmount_all(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ams::wec {
|
|
||||||
|
|
||||||
enum WakeEventLevel {
|
|
||||||
WakeEventLevel_Low = 0,
|
|
||||||
WakeEventLevel_High = 1,
|
|
||||||
WakeEventLevel_Auto = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -85,9 +85,6 @@ typedef enum {
|
|||||||
FS_VER_10_0_0,
|
FS_VER_10_0_0,
|
||||||
FS_VER_10_0_0_EXFAT,
|
FS_VER_10_0_0_EXFAT,
|
||||||
|
|
||||||
FS_VER_10_2_0,
|
|
||||||
FS_VER_10_2_0_EXFAT,
|
|
||||||
|
|
||||||
FS_VER_MAX,
|
FS_VER_MAX,
|
||||||
} emummc_fs_ver_t;
|
} emummc_fs_ver_t;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "exception_handlers.h"
|
#include "exception_handlers.h"
|
||||||
@@ -23,7 +22,7 @@
|
|||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
|
|
||||||
#define CODE_DUMP_SIZE 0x30
|
#define CODE_DUMP_SIZE 0x30
|
||||||
#define STACK_DUMP_SIZE 0x30
|
#define STACK_DUMP_SIZE 0x60
|
||||||
|
|
||||||
extern const uint32_t exception_handler_table[];
|
extern const uint32_t exception_handler_table[];
|
||||||
|
|
||||||
@@ -36,40 +35,6 @@ static const char *register_names[] = {
|
|||||||
"SP", "LR", "PC", "CPSR",
|
"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) {
|
void setup_exception_handlers(void) {
|
||||||
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
|
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
@@ -80,40 +45,38 @@ void setup_exception_handlers(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
|
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
|
||||||
char exception_log[0x400] = {0};
|
uint8_t code_dump[CODE_DUMP_SIZE];
|
||||||
uint8_t code_dump[CODE_DUMP_SIZE] = {0};
|
uint8_t stack_dump[STACK_DUMP_SIZE];
|
||||||
uint8_t stack_dump[STACK_DUMP_SIZE] = {0};
|
size_t code_dump_size;
|
||||||
size_t code_dump_size = 0;
|
size_t stack_dump_size;
|
||||||
size_t stack_dump_size = 0;
|
|
||||||
|
|
||||||
uint32_t pc = registers[15];
|
uint32_t pc = registers[15];
|
||||||
uint32_t cpsr = registers[16];
|
uint32_t cpsr = registers[16];
|
||||||
|
|
||||||
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
|
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
|
||||||
|
|
||||||
sprintf(exception_log, "An exception occured!\n");
|
print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
|
||||||
|
|
||||||
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE);
|
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);
|
stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
|
||||||
|
|
||||||
sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
|
||||||
sprintf(exception_log + strlen(exception_log), "\nRegisters:\n");
|
exception_names[exception_type]);
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n");
|
||||||
|
|
||||||
/* Print r0 to pc. */
|
/* Print r0 to pc. */
|
||||||
for (int i = 0; i < 16; i += 2) {
|
for (int i = 0; i < 16; i += 2) {
|
||||||
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
|
||||||
register_names[i], registers[i], register_names[i+1], registers[i+1]);
|
register_names[i], registers[i], register_names[i+1], registers[i+1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print cpsr. */
|
/* Print cpsr. */
|
||||||
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
|
||||||
|
|
||||||
/* Print code and stack regions. */
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n");
|
||||||
sprintf(exception_log + strlen(exception_log), "\nCode dump:\n");
|
hexdump(code_dump, code_dump_size, instr_addr);
|
||||||
hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log));
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n");
|
||||||
sprintf(exception_log + strlen(exception_log), "\nStack dump:\n");
|
hexdump(stack_dump, stack_dump_size, registers[13]);
|
||||||
hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log));
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
|
||||||
sprintf(exception_log + strlen(exception_log), "\n");
|
fatal_error("An exception occurred!\n");
|
||||||
|
|
||||||
/* Throw fatal error with the full exception log. */
|
|
||||||
fatal_error(exception_log);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ int fsdev_register_keys(const char *name, unsigned int target_firmware, BisParti
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fsdev_unmount_all(void) {
|
int fsdev_unmount_all(void) {
|
||||||
for (size_t i = 0; i < FF_VOLUMES; i++) {
|
for (size_t i = 0; i < FF_VOLUMES; i++) {
|
||||||
int ret = fsdev_unmount_device(g_fsdev_devices[i].name);
|
int ret = fsdev_unmount_device(g_fsdev_devices[i].name);
|
||||||
|
|||||||
@@ -112,3 +112,42 @@ int gpt_iterate_through_entries(FILE *disk, size_t sector_size, gpt_entry_iterat
|
|||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,5 +56,6 @@ 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_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_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
|
#endif
|
||||||
|
|||||||
@@ -420,9 +420,6 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
|
|||||||
|
|
||||||
"\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", /* FS_VER_10_0_0 */
|
"\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 */
|
"\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) {
|
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {
|
||||||
|
|||||||
@@ -971,6 +971,12 @@ 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));
|
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);
|
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. */
|
/* Update size. */
|
||||||
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;
|
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;
|
||||||
|
|
||||||
|
|||||||
@@ -273,10 +273,7 @@ void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmwa
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t bis_key_generation = fuse_get_5x_key_generation();
|
const 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};
|
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) {
|
switch (partition_id) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#ifndef FUSEE_LOG_H
|
#ifndef FUSEE_LOG_H
|
||||||
#define FUSEE_LOG_H
|
#define FUSEE_LOG_H
|
||||||
|
|
||||||
#define PRINT_MESSAGE_MAX_LENGTH 1024
|
#define PRINT_MESSAGE_MAX_LENGTH 512
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "nxboot.h"
|
#include "nxboot.h"
|
||||||
#include "nxfs.h"
|
#include "nxfs.h"
|
||||||
#include "bct.h"
|
#include "bct.h"
|
||||||
#include "car.h"
|
|
||||||
#include "di.h"
|
#include "di.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
@@ -55,7 +54,6 @@
|
|||||||
#define u8 uint8_t
|
#define u8 uint8_t
|
||||||
#define u32 uint32_t
|
#define u32 uint32_t
|
||||||
#include "exosphere_bin.h"
|
#include "exosphere_bin.h"
|
||||||
#include "mesosphere_bin.h"
|
|
||||||
#include "sept_secondary_00_enc.h"
|
#include "sept_secondary_00_enc.h"
|
||||||
#include "sept_secondary_01_enc.h"
|
#include "sept_secondary_01_enc.h"
|
||||||
#include "sept_secondary_dev_00_enc.h"
|
#include "sept_secondary_dev_00_enc.h"
|
||||||
@@ -66,8 +64,7 @@
|
|||||||
#undef u32
|
#undef u32
|
||||||
|
|
||||||
extern const uint8_t warmboot_bin[];
|
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] = {
|
static const uint8_t retail_pkc_modulus[0x100] = {
|
||||||
0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD,
|
0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD,
|
||||||
@@ -212,11 +209,11 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
|
|||||||
strat_cfg->has_nogc_config = true;
|
strat_cfg->has_nogc_config = true;
|
||||||
sscanf(value, "%d", &tmp);
|
sscanf(value, "%d", &tmp);
|
||||||
strat_cfg->enable_nogc = tmp != 0;
|
strat_cfg->enable_nogc = tmp != 0;
|
||||||
} else if (strcmp(name, STRATOSPHERE_DISABLE_NCM_KEY) == 0) {
|
} else if (strcmp(name, STRATOSPHERE_ENABLE_NCM_KEY) == 0) {
|
||||||
sscanf(value, "%d", &tmp);
|
sscanf(value, "%d", &tmp);
|
||||||
strat_cfg->ncm_disabled = tmp != 0;
|
strat_cfg->ncm_enabled = tmp != 0;
|
||||||
if (strat_cfg->ncm_disabled) {
|
if (strat_cfg->ncm_enabled) {
|
||||||
stratosphere_disable_ncm();
|
stratosphere_enable_ncm();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -239,9 +236,6 @@ 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)
|
#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) {
|
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("34728c771299443420820d8ae490ea41", 10_0_4);
|
||||||
CHECK_NCA("5b1df84f88c3334335bbb45d8522cbb4", 10_0_3);
|
CHECK_NCA("5b1df84f88c3334335bbb45d8522cbb4", 10_0_3);
|
||||||
CHECK_NCA("e951bc9dedcd54f65ffd83d4d050f9e0", 10_0_2);
|
CHECK_NCA("e951bc9dedcd54f65ffd83d4d050f9e0", 10_0_2);
|
||||||
@@ -627,7 +621,6 @@ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
|||||||
uint32_t nxboot_main(void) {
|
uint32_t nxboot_main(void) {
|
||||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||||
const bool is_experimental = fusee_is_experimental();
|
|
||||||
package2_header_t *package2;
|
package2_header_t *package2;
|
||||||
size_t package2_size;
|
size_t package2_size;
|
||||||
void *tsec_fw;
|
void *tsec_fw;
|
||||||
@@ -639,8 +632,6 @@ uint32_t nxboot_main(void) {
|
|||||||
void *warmboot_memaddr;
|
void *warmboot_memaddr;
|
||||||
void *package1loader;
|
void *package1loader;
|
||||||
size_t package1loader_size;
|
size_t package1loader_size;
|
||||||
void *mesosphere;
|
|
||||||
size_t mesosphere_size;
|
|
||||||
void *emummc;
|
void *emummc;
|
||||||
size_t emummc_size;
|
size_t emummc_size;
|
||||||
uint32_t available_revision;
|
uint32_t available_revision;
|
||||||
@@ -658,7 +649,7 @@ uint32_t nxboot_main(void) {
|
|||||||
} else {
|
} else {
|
||||||
emummc_size = get_file_size("atmosphere/emummc.kip");
|
emummc_size = get_file_size("atmosphere/emummc.kip");
|
||||||
if (emummc_size != 0) {
|
if (emummc_size != 0) {
|
||||||
/* Allocate memory for the emummc KIP. */
|
/* Allocate memory for the TSEC firmware. */
|
||||||
emummc = memalign(0x100, emummc_size);
|
emummc = memalign(0x100, emummc_size);
|
||||||
|
|
||||||
if (emummc == NULL) {
|
if (emummc == NULL) {
|
||||||
@@ -847,7 +838,13 @@ uint32_t nxboot_main(void) {
|
|||||||
|
|
||||||
/* Derive new device keys. */
|
/* Derive new device keys. */
|
||||||
{
|
{
|
||||||
derive_new_device_keys(fuse_get_retail_type() != 0, KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, target_firmware);
|
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 */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the system partition's keys. */
|
/* Set the system partition's keys. */
|
||||||
@@ -936,41 +933,6 @@ uint32_t nxboot_main(void) {
|
|||||||
pmc->scratch1 = (uint32_t)warmboot_memaddr;
|
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");
|
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Rebuilding package2...\n");
|
||||||
|
|
||||||
/* Parse stratosphere config. */
|
/* Parse stratosphere config. */
|
||||||
@@ -979,7 +941,7 @@ uint32_t nxboot_main(void) {
|
|||||||
print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Configured Stratosphere...\n");
|
print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Configured Stratosphere...\n");
|
||||||
|
|
||||||
/* Patch package2, adding Thermosphère + custom KIPs. */
|
/* Patch package2, adding Thermosphère + custom KIPs. */
|
||||||
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, mesosphere, mesosphere_size, emummc, emummc_size);
|
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, emummc, emummc_size);
|
||||||
|
|
||||||
/* Set detected FS version. */
|
/* Set detected FS version. */
|
||||||
MAILBOX_EXOSPHERE_CONFIGURATION->emummc_cfg.base_cfg.fs_version = stratosphere_get_fs_version();
|
MAILBOX_EXOSPHERE_CONFIGURATION->emummc_cfg.base_cfg.fs_version = stratosphere_get_fs_version();
|
||||||
@@ -1034,12 +996,6 @@ uint32_t nxboot_main(void) {
|
|||||||
/* Wait for the splash screen to have been displayed for as long as it should be. */
|
/* Wait for the splash screen to have been displayed for as long as it should be. */
|
||||||
splash_screen_wait_delay();
|
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 the memory address for booting CPU0. */
|
||||||
return (uint32_t)exosphere_memaddr;
|
return (uint32_t)exosphere_memaddr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ static bool g_emmc_device_initialized = false;
|
|||||||
|
|
||||||
static bool g_fsdev_ready = false;
|
static bool g_fsdev_ready = false;
|
||||||
static bool g_rawdev_ready = false;
|
static bool g_rawdev_ready = false;
|
||||||
|
static bool g_emudev_ready = false;
|
||||||
|
|
||||||
static bool g_is_emummc = false;
|
static bool g_is_emummc = false;
|
||||||
|
|
||||||
@@ -355,6 +356,87 @@ static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *par
|
|||||||
return 0;
|
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() {
|
int nxfs_mount_sd() {
|
||||||
device_partition_t model;
|
device_partition_t model;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -364,7 +446,6 @@ int nxfs_mount_sd() {
|
|||||||
model.device_struct = &g_sd_mmcpart;
|
model.device_struct = &g_sd_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 1u << 30; /* arbitrary numbers of sectors. TODO: find the size of the SD in sectors. */
|
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. */
|
/* Mount the SD card device. */
|
||||||
rc = fsdev_mount_device("sdmc", &model, true);
|
rc = fsdev_mount_device("sdmc", &model, true);
|
||||||
@@ -398,7 +479,6 @@ int nxfs_mount_emmc() {
|
|||||||
model.device_struct = &g_emmc_boot0_mmcpart;
|
model.device_struct = &g_emmc_boot0_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 0x184000 / model.sector_size;
|
model.num_sectors = 0x184000 / model.sector_size;
|
||||||
model.is_emulated = false;
|
|
||||||
|
|
||||||
/* Mount boot0 device. */
|
/* Mount boot0 device. */
|
||||||
rc = rawdev_mount_device("boot0", &model, true);
|
rc = rawdev_mount_device("boot0", &model, true);
|
||||||
@@ -419,7 +499,6 @@ int nxfs_mount_emmc() {
|
|||||||
model.device_struct = &g_emmc_boot1_mmcpart;
|
model.device_struct = &g_emmc_boot1_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 0x80000 / model.sector_size;
|
model.num_sectors = 0x80000 / model.sector_size;
|
||||||
model.is_emulated = false;
|
|
||||||
|
|
||||||
/* Mount boot1 device. */
|
/* Mount boot1 device. */
|
||||||
rc = rawdev_mount_device("boot1", &model, false);
|
rc = rawdev_mount_device("boot1", &model, false);
|
||||||
@@ -435,7 +514,6 @@ int nxfs_mount_emmc() {
|
|||||||
model.device_struct = &g_emmc_user_mmcpart;
|
model.device_struct = &g_emmc_user_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = (256ull << 30) / model.sector_size;
|
model.num_sectors = (256ull << 30) / model.sector_size;
|
||||||
model.is_emulated = false;
|
|
||||||
|
|
||||||
/* Mount raw NAND device. */
|
/* Mount raw NAND device. */
|
||||||
rc = rawdev_mount_device("rawnand", &model, false);
|
rc = rawdev_mount_device("rawnand", &model, false);
|
||||||
@@ -480,11 +558,10 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
|
|||||||
model = g_emummc_devpart_template;
|
model = g_emummc_devpart_template;
|
||||||
model.start_sector = emummc_start_sector + (0x400000 * 0 / model.sector_size);
|
model.start_sector = emummc_start_sector + (0x400000 * 0 / model.sector_size);
|
||||||
model.num_sectors = 0x400000 / model.sector_size;
|
model.num_sectors = 0x400000 / model.sector_size;
|
||||||
model.is_emulated = true;
|
|
||||||
model.emu_use_file = false;
|
model.emu_use_file = false;
|
||||||
|
|
||||||
/* Mount emulated boot0 device. */
|
/* Mount emulated boot0 device. */
|
||||||
rc = rawdev_mount_device("boot0", &model, true);
|
rc = emudev_mount_device("boot0", &model, NULL, 0, 0);
|
||||||
|
|
||||||
/* Failed to mount boot0 device. */
|
/* Failed to mount boot0 device. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
@@ -492,7 +569,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Register emulated boot0 device. */
|
/* Register emulated boot0 device. */
|
||||||
rc = rawdev_register_device("boot0");
|
rc = emudev_register_device("boot0");
|
||||||
|
|
||||||
/* Failed to register boot0 device. */
|
/* Failed to register boot0 device. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
@@ -503,11 +580,10 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
|
|||||||
model = g_emummc_devpart_template;
|
model = g_emummc_devpart_template;
|
||||||
model.start_sector = emummc_start_sector + (0x400000 * 1 / model.sector_size);
|
model.start_sector = emummc_start_sector + (0x400000 * 1 / model.sector_size);
|
||||||
model.num_sectors = 0x400000 / model.sector_size;
|
model.num_sectors = 0x400000 / model.sector_size;
|
||||||
model.is_emulated = true;
|
|
||||||
model.emu_use_file = false;
|
model.emu_use_file = false;
|
||||||
|
|
||||||
/* Mount emulated boot1 device. */
|
/* Mount emulated boot1 device. */
|
||||||
rc = rawdev_mount_device("boot1", &model, false);
|
rc = emudev_mount_device("boot1", &model, NULL, 0, 0);
|
||||||
|
|
||||||
/* Failed to mount boot1. */
|
/* Failed to mount boot1. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
@@ -520,11 +596,10 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
|
|||||||
model = g_emummc_devpart_template;
|
model = g_emummc_devpart_template;
|
||||||
model.start_sector = emummc_start_sector + (0x400000 * 2 / model.sector_size);
|
model.start_sector = emummc_start_sector + (0x400000 * 2 / model.sector_size);
|
||||||
model.num_sectors = (256ull << 30) / model.sector_size;
|
model.num_sectors = (256ull << 30) / model.sector_size;
|
||||||
model.is_emulated = true;
|
|
||||||
model.emu_use_file = false;
|
model.emu_use_file = false;
|
||||||
|
|
||||||
/* Mount emulated raw NAND device. */
|
/* Mount emulated raw NAND device. */
|
||||||
rc = rawdev_mount_device("rawnand", &model, false);
|
rc = emudev_mount_device("rawnand", &model, NULL, 0, 0);
|
||||||
|
|
||||||
/* Failed to mount raw NAND. */
|
/* Failed to mount raw NAND. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
@@ -532,7 +607,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Register emulated raw NAND device. */
|
/* Register emulated raw NAND device. */
|
||||||
rc = rawdev_register_device("rawnand");
|
rc = emudev_register_device("rawnand");
|
||||||
|
|
||||||
/* Failed to register raw NAND device. */
|
/* Failed to register raw NAND device. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
@@ -548,14 +623,14 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate the GPT and mount each emulated raw NAND partition. */
|
/* Iterate the GPT and mount each emulated raw NAND partition. */
|
||||||
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
|
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, NULL, 0, 0);
|
||||||
|
|
||||||
/* Close emulated raw NAND device. */
|
/* Close emulated raw NAND device. */
|
||||||
fclose(rawnand);
|
fclose(rawnand);
|
||||||
|
|
||||||
/* All emulated devices are ready. */
|
/* All emulated devices are ready. */
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
g_rawdev_ready = true;
|
g_emudev_ready = true;
|
||||||
g_is_emummc = true;
|
g_is_emummc = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,6 +641,7 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
|
|||||||
device_partition_t model;
|
device_partition_t model;
|
||||||
int rc;
|
int rc;
|
||||||
FILE *rawnand;
|
FILE *rawnand;
|
||||||
|
bool is_exfat;
|
||||||
char emummc_boot0_path[0x300 + 1] = {0};
|
char emummc_boot0_path[0x300 + 1] = {0};
|
||||||
char emummc_boot1_path[0x300 + 1] = {0};
|
char emummc_boot1_path[0x300 + 1] = {0};
|
||||||
|
|
||||||
@@ -577,17 +653,26 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
|
|||||||
return -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. */
|
/* We want a folder with the archive bit set. */
|
||||||
rc = fsdev_get_attr(emummc_path);
|
rc = fsdev_get_attr(emummc_path);
|
||||||
|
|
||||||
/* Failed to get file DOS attributes. */
|
/* Failed to get file DOS attributes. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -2;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Our path is not a directory. */
|
/* Our path is not a directory. */
|
||||||
if (!(rc & AM_DIR)) {
|
if (!(rc & AM_DIR)) {
|
||||||
return -3;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the archive bit is not set. */
|
/* Check if the archive bit is not set. */
|
||||||
@@ -597,95 +682,80 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
|
|||||||
|
|
||||||
/* Failed to set file DOS attributes. */
|
/* Failed to set file DOS attributes. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -4;
|
return -5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare boot0 file path. */
|
|
||||||
snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0");
|
|
||||||
|
|
||||||
/* Setup an emulation template for boot0. */
|
/* Setup an emulation template for boot0. */
|
||||||
model = g_emummc_devpart_template;
|
model = g_emummc_devpart_template;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 0x400000 / model.sector_size;
|
model.num_sectors = 0x400000 / model.sector_size;
|
||||||
model.is_emulated = true;
|
|
||||||
model.emu_use_file = true;
|
model.emu_use_file = true;
|
||||||
model.emu_num_parts = 0;
|
|
||||||
model.emu_part_limit = 0;
|
/* Prepare boot0 file path. */
|
||||||
strcpy(model.emu_root_path, emummc_path);
|
snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0");
|
||||||
strcpy(model.emu_file_path, emummc_boot0_path);
|
|
||||||
|
|
||||||
/* Mount emulated boot0 device. */
|
/* Mount emulated boot0 device. */
|
||||||
rc = rawdev_mount_device("boot0", &model, true);
|
rc = emudev_mount_device("boot0", &model, emummc_boot0_path, 0, 0);
|
||||||
|
|
||||||
/* Failed to mount boot0 device. */
|
/* Failed to mount boot0 device. */
|
||||||
if (rc == -1) {
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register emulated boot0 device. */
|
|
||||||
rc = rawdev_register_device("boot0");
|
|
||||||
|
|
||||||
/* Failed to register boot0 device. */
|
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -6;
|
return -6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare boot1 file path. */
|
/* Register emulated boot0 device. */
|
||||||
snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1");
|
rc = emudev_register_device("boot0");
|
||||||
|
|
||||||
|
/* Failed to register boot0 device. */
|
||||||
|
if (rc == -1) {
|
||||||
|
return -7;
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup an emulation template for boot1. */
|
/* Setup an emulation template for boot1. */
|
||||||
model = g_emummc_devpart_template;
|
model = g_emummc_devpart_template;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 0x400000 / model.sector_size;
|
model.num_sectors = 0x400000 / model.sector_size;
|
||||||
model.is_emulated = true;
|
|
||||||
model.emu_use_file = true;
|
model.emu_use_file = true;
|
||||||
model.emu_num_parts = 0;
|
|
||||||
model.emu_part_limit = 0;
|
/* Prepare boot1 file path. */
|
||||||
strcpy(model.emu_root_path, emummc_path);
|
snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1");
|
||||||
strcpy(model.emu_file_path, emummc_boot1_path);
|
|
||||||
|
|
||||||
/* Mount emulated boot1 device. */
|
/* Mount emulated boot1 device. */
|
||||||
rc = rawdev_mount_device("boot1", &model, false);
|
rc = emudev_mount_device("boot1", &model, emummc_boot1_path, 0, 0);
|
||||||
|
|
||||||
/* Failed to mount boot1. */
|
/* Failed to mount boot1. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -7;
|
return -8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register emulated boot1 device. */
|
/* Register emulated boot1 device. */
|
||||||
rc = rawdev_register_device("boot1");
|
rc = emudev_register_device("boot1");
|
||||||
|
|
||||||
/* Failed to register boot1 device. */
|
/* Failed to register boot1 device. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -8;
|
return -9;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup a template for raw NAND. */
|
/* Setup a template for raw NAND. */
|
||||||
model = g_emummc_devpart_template;
|
model = g_emummc_devpart_template;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = (256ull << 30) / model.sector_size;
|
model.num_sectors = (256ull << 30) / model.sector_size;
|
||||||
model.is_emulated = true;
|
|
||||||
model.emu_use_file = 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. */
|
/* Mount emulated raw NAND device from single or multiple parts. */
|
||||||
rc = rawdev_mount_device("rawnand", &model, false);
|
rc = emudev_mount_device("rawnand", &model, emummc_path, num_parts, part_limit);
|
||||||
|
|
||||||
/* Failed to mount raw NAND. */
|
/* Failed to mount raw NAND. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -9;
|
return -10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register emulated raw NAND device. */
|
/* Register emulated raw NAND device. */
|
||||||
rc = rawdev_register_device("rawnand");
|
rc = emudev_register_device("rawnand");
|
||||||
|
|
||||||
/* Failed to register raw NAND device. */
|
/* Failed to register raw NAND device. */
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -10;
|
return -11;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open emulated raw NAND device. */
|
/* Open emulated raw NAND device. */
|
||||||
@@ -693,18 +763,18 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
|
|||||||
|
|
||||||
/* Failed to open emulated raw NAND device. */
|
/* Failed to open emulated raw NAND device. */
|
||||||
if (rawnand == NULL) {
|
if (rawnand == NULL) {
|
||||||
return -11;
|
return -12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate the GPT and mount each emulated raw NAND partition. */
|
/* Iterate the GPT and mount each emulated raw NAND partition. */
|
||||||
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
|
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, emummc_path, num_parts, part_limit);
|
||||||
|
|
||||||
/* Close emulated raw NAND device. */
|
/* Close emulated raw NAND device. */
|
||||||
fclose(rawnand);
|
fclose(rawnand);
|
||||||
|
|
||||||
/* All emulated devices are ready. */
|
/* All emulated devices are ready. */
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
g_rawdev_ready = true;
|
g_emudev_ready = true;
|
||||||
g_is_emummc = true;
|
g_is_emummc = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,6 +805,18 @@ int nxfs_unmount_emmc() {
|
|||||||
return rc;
|
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 nxfs_init() {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -750,5 +832,5 @@ int nxfs_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int nxfs_end() {
|
int nxfs_end() {
|
||||||
return ((nxfs_unmount_sd() || nxfs_unmount_emmc()) ? -1 : 0);
|
return ((nxfs_unmount_sd() || nxfs_unmount_emmc() || nxfs_unmount_emummc()) ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "fs_dev.h"
|
#include "fs_dev.h"
|
||||||
#include "raw_dev.h"
|
#include "raw_dev.h"
|
||||||
|
#include "emu_dev.h"
|
||||||
|
|
||||||
int nxfs_init();
|
int nxfs_init();
|
||||||
int nxfs_end();
|
int nxfs_end();
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ static inline size_t align_to_4(size_t s) {
|
|||||||
return ((s + 3) >> 2) << 2;
|
return ((s + 3) >> 2) << 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *emummc, size_t emummc_size) {
|
||||||
package2_header_t *rebuilt_package2;
|
package2_header_t *rebuilt_package2;
|
||||||
size_t rebuilt_package2_size;
|
size_t rebuilt_package2_size;
|
||||||
void *kernel;
|
void *kernel;
|
||||||
@@ -95,28 +95,10 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
|
|||||||
fatal_error("Error: inappropriate kernel embedded ini context");
|
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");
|
print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n");
|
||||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
|
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
|
||||||
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
|
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. */
|
/* 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;
|
package2->metadata.section_offsets[PACKAGE2_SECTION_INI1] = package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] + kernel_size;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
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 *mesosphere, size_t mesosphere_size, void *emummc, size_t emummc_size);
|
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *emummc, size_t emummc_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ 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) {
|
int rawdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately) {
|
||||||
rawdev_device_t *device = NULL;
|
rawdev_device_t *device = NULL;
|
||||||
|
char drname[40];
|
||||||
|
strcpy(drname, name);
|
||||||
|
strcat(drname, ":");
|
||||||
|
|
||||||
if (name[0] == '\0' || devpart == NULL) {
|
if (name[0] == '\0' || devpart == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@@ -202,19 +205,6 @@ int rawdev_unmount_device(const char *name) {
|
|||||||
return 0;
|
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) {
|
int rawdev_unmount_all(void) {
|
||||||
for (size_t i = 0; i < RAWDEV_MAX_DEVICES; i++) {
|
for (size_t i = 0; i < RAWDEV_MAX_DEVICES; i++) {
|
||||||
int rc = rawdev_unmount_device(g_rawdev_devices[i].name);
|
int rc = rawdev_unmount_device(g_rawdev_devices[i].name);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "device_partition.h"
|
#include "device_partition.h"
|
||||||
#include "key_derivation.h"
|
|
||||||
|
|
||||||
#define RAWDEV_MAX_DEVICES 16
|
#define RAWDEV_MAX_DEVICES 16
|
||||||
|
|
||||||
@@ -30,8 +29,6 @@ int rawdev_register_device(const char *name);
|
|||||||
int rawdev_unregister_device(const char *name);
|
int rawdev_unregister_device(const char *name);
|
||||||
int rawdev_unmount_device(const char *name); /* also unregisters. */
|
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);
|
int rawdev_unmount_all(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,9 +30,6 @@ _start:
|
|||||||
|
|
||||||
.word (_metadata - _start)
|
.word (_metadata - _start)
|
||||||
|
|
||||||
_is_experimental:
|
|
||||||
.word 0x00000001 /* is experimental */
|
|
||||||
|
|
||||||
_crt0:
|
_crt0:
|
||||||
/* Switch to system mode, mask all interrupts, clear all flags */
|
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||||
msr cpsr_cxsf, #0xDF
|
msr cpsr_cxsf, #0xDF
|
||||||
@@ -71,14 +68,6 @@ _crt0:
|
|||||||
ldr r1, [r1]
|
ldr r1, [r1]
|
||||||
b main
|
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. */
|
/* Fusee-secondary header. */
|
||||||
.align 5
|
.align 5
|
||||||
_metadata:
|
_metadata:
|
||||||
@@ -146,17 +135,6 @@ _content_headers:
|
|||||||
.asciz "exosphere"
|
.asciz "exosphere"
|
||||||
.align 5
|
.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 */
|
/* fusee_primary content header */
|
||||||
.word __fusee_primary_bin_start__
|
.word __fusee_primary_bin_start__
|
||||||
.word __fusee_primary_bin_size__
|
.word __fusee_primary_bin_size__
|
||||||
@@ -271,7 +249,7 @@ _content_headers:
|
|||||||
.word __ncm_kip_start__
|
.word __ncm_kip_start__
|
||||||
.word __ncm_kip_size__
|
.word __ncm_kip_size__
|
||||||
.byte CONTENT_TYPE_KIP
|
.byte CONTENT_TYPE_KIP
|
||||||
.byte CONTENT_FLAG_NONE
|
.byte CONTENT_FLAG0_EXPERIMENTAL
|
||||||
.byte CONTENT_FLAG_NONE
|
.byte CONTENT_FLAG_NONE
|
||||||
.byte CONTENT_FLAG_NONE
|
.byte CONTENT_FLAG_NONE
|
||||||
.word 0xCCCCCCCC
|
.word 0xCCCCCCCC
|
||||||
@@ -289,6 +267,17 @@ _content_headers:
|
|||||||
.asciz "emummc"
|
.asciz "emummc"
|
||||||
.align 5
|
.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 */
|
/* splash_screen content header */
|
||||||
.word __splash_screen_bmp_start__
|
.word __splash_screen_bmp_start__
|
||||||
.word __splash_screen_bmp_size__
|
.word __splash_screen_bmp_size__
|
||||||
|
|||||||
@@ -48,9 +48,10 @@ static bool g_stratosphere_pm_enabled = true;
|
|||||||
static bool g_stratosphere_ams_mitm_enabled = true;
|
static bool g_stratosphere_ams_mitm_enabled = true;
|
||||||
static bool g_stratosphere_spl_enabled = true;
|
static bool g_stratosphere_spl_enabled = true;
|
||||||
static bool g_stratosphere_boot_enabled = true;
|
static bool g_stratosphere_boot_enabled = true;
|
||||||
static bool g_stratosphere_ncm_enabled = true;
|
static bool g_stratosphere_ncm_enabled = false;
|
||||||
|
|
||||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
|
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;
|
static emummc_fs_ver_t g_fs_ver = FS_VER_1_0_0;
|
||||||
|
|
||||||
@@ -58,17 +59,17 @@ emummc_fs_ver_t stratosphere_get_fs_version(void) {
|
|||||||
return g_fs_ver;
|
return g_fs_ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stratosphere_disable_ncm(void) {
|
void stratosphere_enable_ncm(void) {
|
||||||
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
|
/* 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 */
|
/* 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 */
|
/* when using the NCM reimplementation. However, because NCM manages critical save games */
|
||||||
/* the implementation may be optionally disabled for those not comfortable using it. */
|
/* the implementation will default to off for some time, until the code has been thoroughly */
|
||||||
|
/* tested in practice. */
|
||||||
|
|
||||||
|
/* PLEASE NOTE: The default behavior will be NCM on in a future atmosphere release, */
|
||||||
|
/* and this opt-in functionality will be removed at that time. */
|
||||||
|
|
||||||
/* PLEASE NOTE: The NCM reimplementation has been well-tested, and correspondingly opt-out */
|
g_stratosphere_ncm_enabled = true;
|
||||||
/* 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. */
|
/* GCC doesn't consider the size as const... we have to write it ourselves. */
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware);
|
|||||||
ini1_header_t *stratosphere_get_sd_files_ini1(void);
|
ini1_header_t *stratosphere_get_sd_files_ini1(void);
|
||||||
void stratosphere_free_ini1(void);
|
void stratosphere_free_ini1(void);
|
||||||
|
|
||||||
void stratosphere_disable_ncm(void);
|
void stratosphere_enable_ncm(void);
|
||||||
|
|
||||||
emummc_fs_ver_t stratosphere_get_fs_version(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 {
|
typedef struct {
|
||||||
bool has_nogc_config;
|
bool has_nogc_config;
|
||||||
bool enable_nogc;
|
bool enable_nogc;
|
||||||
bool ncm_disabled;
|
bool ncm_enabled;
|
||||||
} stratosphere_cfg_t;
|
} stratosphere_cfg_t;
|
||||||
|
|
||||||
#define STRATOSPHERE_NOGC_KEY "nogc"
|
#define STRATOSPHERE_NOGC_KEY "nogc"
|
||||||
#define STRATOSPHERE_DISABLE_NCM_KEY "disable_ncm"
|
#define STRATOSPHERE_ENABLE_NCM_KEY "enable_ncm"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -157,18 +157,12 @@ __attribute__ ((noreturn)) void generic_panic(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
__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;
|
va_list args;
|
||||||
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
|
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n Press POWER to reboot.\n");
|
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();
|
wait_for_button_and_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,3 +174,37 @@ __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, u
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -118,6 +118,8 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s
|
|||||||
overlaps_a(start, end, __start__, __end__);
|
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 watchdog_reboot(void);
|
||||||
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
||||||
__attribute__((noreturn)) void reboot_to_fusee_primary(void);
|
__attribute__((noreturn)) void reboot_to_fusee_primary(void);
|
||||||
@@ -127,6 +129,8 @@ __attribute__((noreturn)) void wait_for_button_and_reboot(void);
|
|||||||
void wait_for_button(void);
|
void wait_for_button(void);
|
||||||
|
|
||||||
__attribute__((noreturn)) void generic_panic(void);
|
__attribute__((noreturn)) void generic_panic(void);
|
||||||
|
|
||||||
__attribute__((noreturn)) void fatal_error(const char *fmt, ...);
|
__attribute__((noreturn)) void fatal_error(const char *fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||||
branch = master
|
branch = master
|
||||||
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
commit = cf8f0c3c1f006e07c0b3976908220d3e7e83f7fa
|
||||||
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
parent = 033ae1dbe09ba354849caf90ca2a2f114d9b3b4b
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
ATMOSPHERE_LIBRARIES := libmesosphere libstratosphere libexosphere
|
ATMOSPHERE_LIBRARIES := libmesosphere libstratosphere
|
||||||
|
|
||||||
TOPTARGETS := all clean
|
TOPTARGETS := all clean
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ endif
|
|||||||
include $(DEVKITPRO)/devkitA64/base_rules
|
include $(DEVKITPRO)/devkitA64/base_rules
|
||||||
|
|
||||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM64
|
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM64
|
||||||
export ATMOSPHERE_SETTINGS += -mtp=soft
|
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mtp=soft
|
||||||
export ATMOSPHERE_CFLAGS +=
|
export ATMOSPHERE_CFLAGS +=
|
||||||
export ATMOSPHERE_CXXFLAGS +=
|
export ATMOSPHERE_CXXFLAGS +=
|
||||||
export ATMOSPHERE_ASFLAGS +=
|
export ATMOSPHERE_ASFLAGS +=
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_ARM_CORTEX_A57
|
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_ARM_CORTEX_A57
|
||||||
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mtune=cortex-a57
|
export ATMOSPHERE_SETTINGS += -mtune=cortex-a57
|
||||||
export ATMOSPHERE_CFLAGS +=
|
export ATMOSPHERE_CFLAGS +=
|
||||||
export ATMOSPHERE_CXXFLAGS +=
|
export ATMOSPHERE_CXXFLAGS +=
|
||||||
export ATMOSPHERE_ASFLAGS +=
|
export ATMOSPHERE_ASFLAGS +=
|
||||||
@@ -10,18 +10,16 @@ ifeq ($(strip $(ATMOSPHERE_BOARD)),)
|
|||||||
export ATMOSPHERE_BOARD := nx-hac-001
|
export ATMOSPHERE_BOARD := nx-hac-001
|
||||||
|
|
||||||
ifeq ($(strip $(ATMOSPHERE_CPU)),)
|
ifeq ($(strip $(ATMOSPHERE_CPU)),)
|
||||||
export ATMOSPHERE_CPU := arm-cortex-a57
|
export ATMOSPHERE_CPU := arm-cortex-a57
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ATMOSPHERE_BUILD_SETTINGS ?=
|
|
||||||
|
|
||||||
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
||||||
export ATMOSPHERE_SETTINGS := -fPIE -g $(ATMOSPHERE_BUILD_SETTINGS)
|
export ATMOSPHERE_SETTINGS := -fPIE -g
|
||||||
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
|
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
|
||||||
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
|
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
|
||||||
-Wno-format-truncation -Wno-format-zero-length -Wno-stringop-truncation
|
-Wno-format-truncation
|
||||||
|
|
||||||
export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++20
|
export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++20
|
||||||
export ATMOSPHERE_ASFLAGS :=
|
export ATMOSPHERE_ASFLAGS :=
|
||||||
@@ -30,44 +28,40 @@ export ATMOSPHERE_ASFLAGS :=
|
|||||||
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
|
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
|
||||||
|
|
||||||
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
|
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
|
||||||
export ATMOSPHERE_ARCH_DIR := arm64
|
export ATMOSPHERE_ARCH_DIR := arch/arm64
|
||||||
export ATMOSPHERE_BOARD_DIR := nintendo/nx
|
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx
|
||||||
export ATMOSPHERE_OS_DIR := horizon
|
export ATMOSPHERE_OS_DIR := os/horizon
|
||||||
|
|
||||||
export ATMOSPHERE_ARCH_NAME := arm64
|
export ATMOSPHERE_ARCH_NAME := arm64
|
||||||
export ATMOSPHERE_BOARD_NAME := nintendo_nx
|
export ATMOSPHERE_BOARD_NAME := nintendo_nx
|
||||||
export ATMOSPHERE_OS_NAME := horizon
|
export ATMOSPHERE_OS_NAME := horizon
|
||||||
|
|
||||||
export ATMOSPHERE_CPU_EXTENSIONS := arm_crypto_extension aarch64_crypto_extension
|
|
||||||
else ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
|
else ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
|
||||||
export ATMOSPHERE_ARCH_DIR := arm
|
export ATMOSPHERE_ARCH_DIR := arch/arm
|
||||||
export ATMOSPHERE_BOARD_DIR := nintendo/nx_bpmp
|
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx_bpmp
|
||||||
export ATMOSPHERE_OS_DIR := horizon
|
export ATMOSPHERE_OS_DIR := os/horizon
|
||||||
|
|
||||||
export ATMOSPHERE_ARCH_NAME := arm
|
export ATMOSPHERE_ARCH_NAME := arm
|
||||||
export ATMOSPHERE_BOARD_NAME := nintendo_nx
|
export ATMOSPHERE_BOARD_NAME := nintendo_nx
|
||||||
export ATMOSPHERE_OS_NAME := horizon
|
export ATMOSPHERE_OS_NAME := horizon
|
||||||
|
|
||||||
export ATMOSPHERE_CPU_EXTENSIONS :=
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
|
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
|
||||||
export ATMOSPHERE_CPU_DIR := cortex_a57
|
export ATMOSPHERE_CPU_DIR := arch/arm64/cpu/cortex_a57
|
||||||
export ATMOSPHERE_CPU_NAME := arm_cortex_a57
|
export ATMOSPHERE_CPU_NAME := arm_cortex_a57
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
|
ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
|
||||||
export ATMOSPHERE_CPU_DIR := arm7tdmi
|
export ATMOSPHERE_CPU_DIR := arch/arm/cpu/arm7tdmi
|
||||||
export ATMOSPHERE_CPU_NAME := arm7tdmi
|
export ATMOSPHERE_CPU_NAME := arm7tdmi
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/arch/$(ATMOSPHERE_ARCH_DIR)
|
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_ARCH_DIR)
|
||||||
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/board/$(ATMOSPHERE_BOARD_DIR)
|
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_BOARD_DIR)
|
||||||
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/os/$(ATMOSPHERE_OS_DIR)
|
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_OS_DIR)
|
||||||
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_ARCH_MAKE_DIR)/cpu/$(ATMOSPHERE_CPU_DIR)
|
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_CPU_DIR)
|
||||||
|
|
||||||
export ATMOSPHERE_LIBRARY_DIR := lib_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
|
export ATMOSPHERE_LIBRARY_DIR := lib_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
|
||||||
export ATMOSPHERE_BUILD_DIR := build_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
|
export ATMOSPHERE_BUILD_DIR := build_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
|
||||||
@@ -108,41 +102,16 @@ BUILD := build
|
|||||||
DATA := data
|
DATA := data
|
||||||
INCLUDES := include
|
INCLUDES := include
|
||||||
|
|
||||||
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,))
|
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/$3/.*),$1/$2/$3 $(call DIR_WILDCARD,$1/$2/$3),$(if $(wildcard $1/$2/generic/.*), $1/$2/generic $(call DIR_WILDCARD,$1/$2/generic),))
|
SPECIFIC_SOURCE_DIRS=$(if $(wildcard $1/$2/.*),$1/$2 $(call DIR_WILDCARD,$1/$2),)
|
||||||
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,$(ATMOSPHERE_ARCH_DIR)) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_BOARD_DIR)) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_OS_DIR))
|
||||||
|
|
||||||
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)
|
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
|
# Rules for compiling pre-compiled headers
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
|
%.gch: %.hpp
|
||||||
@echo Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
|
@echo $<
|
||||||
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
$(CXX) -w -x c++-header -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||||
|
@cp $@ $(<).gch
|
||||||
%.hpp.gch: %.hpp
|
|
||||||
@echo Precompiling $(notdir $<)
|
|
||||||
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
|
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Wextra -Werror -fno-non-call-exceptions
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Werror -fno-non-call-exceptions
|
||||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
|
|||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Werror -fno-non-call-exceptions
|
||||||
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
|
||||||
|
|
||||||
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 LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -nostdlib -nostartfiles -g $(SETTINGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
|
||||||
|
|
||||||
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||||
-Wl,--wrap,__cxa_throw \
|
-Wl,--wrap,__cxa_throw \
|
||||||
@@ -29,7 +29,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
|||||||
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
|
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
|
||||||
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
|
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
|
||||||
|
|
||||||
export LIBS := -l$(LIBMESOSPHERE_NAME)
|
export LIBS := -lmesosphere
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# list of directories containing libraries, this must be the top level containing
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Wextra -Werror -flto -fno-non-call-exceptions
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -flto -fno-non-call-exceptions
|
||||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||||
@@ -39,9 +39,23 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
|
|||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
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)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
@@ -112,7 +126,6 @@ $(OFILES) : $(GCH_FILES)
|
|||||||
$(OFILES_SRC) : $(HFILES_BIN)
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
|
|
||||||
libc.o: CFLAGS += -fno-builtin -fno-lto
|
libc.o: CFLAGS += -fno-builtin -fno-lto
|
||||||
libgcc_division.arch.arm.o: CFLAGS += -fno-builtin -fno-lto
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%_bin.h %.bin.o : %.bin
|
%_bin.h %.bin.o : %.bin
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Wextra -Werror -fno-non-call-exceptions
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Werror -fno-non-call-exceptions
|
||||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||||
@@ -39,9 +39,23 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
|
|||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
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)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
|
||||||
#include <exosphere/common.hpp>
|
#include <exosphere/common.hpp>
|
||||||
|
#include <exosphere/reg.hpp>
|
||||||
#include <exosphere/hw.hpp>
|
#include <exosphere/hw.hpp>
|
||||||
#include <exosphere/util.hpp>
|
#include <exosphere/util.hpp>
|
||||||
#include <exosphere/mmu.hpp>
|
#include <exosphere/mmu.hpp>
|
||||||
@@ -40,3 +41,4 @@
|
|||||||
#include <exosphere/actmon.hpp>
|
#include <exosphere/actmon.hpp>
|
||||||
#include <exosphere/pmc.hpp>
|
#include <exosphere/pmc.hpp>
|
||||||
#include <exosphere/secmon.hpp>
|
#include <exosphere/secmon.hpp>
|
||||||
|
#include <exosphere/tegra.hpp>
|
||||||
@@ -19,40 +19,34 @@
|
|||||||
namespace ams::pkg1 {
|
namespace ams::pkg1 {
|
||||||
|
|
||||||
enum AesKeySlot {
|
enum AesKeySlot {
|
||||||
AesKeySlot_UserStart = 0,
|
AesKeySlot_UserStart = 0,
|
||||||
|
|
||||||
AesKeySlot_TzramSaveKek = 2,
|
AesKeySlot_TzramSaveKek = 2,
|
||||||
AesKeySlot_TzramSaveKey = 3,
|
AesKeySlot_TzramSaveKey = 3,
|
||||||
|
|
||||||
AesKeySlot_UserLast = 5,
|
AesKeySlot_UserLast = 5,
|
||||||
AesKeySlot_UserEnd = AesKeySlot_UserLast + 1,
|
AesKeySlot_UserEnd = AesKeySlot_UserLast + 1,
|
||||||
|
|
||||||
AesKeySlot_SecmonStart = 8,
|
AesKeySlot_SecmonStart = 8,
|
||||||
|
|
||||||
AesKeySlot_Temporary = 8,
|
AesKeySlot_Temporary = 8,
|
||||||
AesKeySlot_Smc = 9,
|
AesKeySlot_Smc = 9,
|
||||||
AesKeySlot_RandomForUserWrap = 10,
|
AesKeySlot_RandomForUserWrap = 10,
|
||||||
AesKeySlot_RandomForKeyStorageWrap = 11,
|
AesKeySlot_RandomForKeyStorageWrap = 11,
|
||||||
AesKeySlot_DeviceMaster = 12,
|
AesKeySlot_DeviceMaster = 12,
|
||||||
AesKeySlot_Master = 13,
|
AesKeySlot_Master = 13,
|
||||||
AesKeySlot_Device = 15,
|
AesKeySlot_Device = 15,
|
||||||
|
|
||||||
AesKeySlot_Count = 16,
|
AesKeySlot_SecmonEnd = 16,
|
||||||
AesKeySlot_SecmonEnd = AesKeySlot_Count,
|
|
||||||
|
|
||||||
/* Used only during boot. */
|
/* Used only during boot. */
|
||||||
AesKeySlot_Tsec = 12,
|
AesKeySlot_Tsec = 12,
|
||||||
AesKeySlot_TsecRoot = 13,
|
AesKeySlot_TsecRoot = 13,
|
||||||
AesKeySlot_SecureBoot = 14,
|
AesKeySlot_SecureBoot = 14,
|
||||||
AesKeySlot_SecureStorage = 15,
|
AesKeySlot_SecureStorage = 15,
|
||||||
|
|
||||||
AesKeySlot_DeviceMasterKeySourceKekErista = 10,
|
AesKeySlot_MasterKek = 13,
|
||||||
AesKeySlot_MasterKek = 13,
|
AesKeySlot_DeviceMasterKeySourceKek = 14,
|
||||||
AesKeySlot_DeviceMasterKeySourceKekMariko = 14,
|
|
||||||
|
|
||||||
/* Mariko only keyslots, used during boot. */
|
|
||||||
AesKeySlot_MarikoKek = 12,
|
|
||||||
AesKeySlot_MarikoBek = 13,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RsaKeySlot {
|
enum RsaKeySlot {
|
||||||
|
|||||||
@@ -18,9 +18,6 @@
|
|||||||
|
|
||||||
namespace ams::reg {
|
namespace ams::reg {
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept UnsignedNonConstIntegral = std::unsigned_integral<T> && !std::is_const<T>::value;
|
|
||||||
|
|
||||||
using BitsValue = std::tuple<u16, u16, u32>;
|
using BitsValue = std::tuple<u16, u16, u32>;
|
||||||
using BitsMask = std::tuple<u16, u16>;
|
using BitsMask = std::tuple<u16, u16>;
|
||||||
|
|
||||||
@@ -51,137 +48,100 @@ namespace ams::reg {
|
|||||||
return (EncodeValue(values) | ...);
|
return (EncodeValue(values) | ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
ALWAYS_INLINE void Write(volatile u32 *reg, u32 val) { *reg = val; }
|
||||||
constexpr ALWAYS_INLINE u32 EncodeMask(const Masks... masks) {
|
ALWAYS_INLINE void Write(volatile u32 ®, u32 val) { reg = val; }
|
||||||
return (EncodeMask(masks) | ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE void Write(volatile IntType *reg, std::type_identity_t<IntType> val) { *reg = val; }
|
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE void Write(volatile IntType ®, std::type_identity_t<IntType> val) { reg = val; }
|
|
||||||
|
|
||||||
ALWAYS_INLINE void Write(uintptr_t reg, u32 val) { Write(reinterpret_cast<volatile u32 *>(reg), val); }
|
ALWAYS_INLINE void Write(uintptr_t reg, u32 val) { Write(reinterpret_cast<volatile u32 *>(reg), val); }
|
||||||
|
|
||||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE void Write(volatile IntType *reg, const Values... values) { return Write(reg, static_cast<IntType>((EncodeValue(values) | ...))); }
|
ALWAYS_INLINE void Write(volatile u32 *reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE void Write(volatile IntType ®, const Values... values) { return Write(reg, static_cast<IntType>((EncodeValue(values) | ...))); }
|
ALWAYS_INLINE void Write(volatile u32 ®, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
|
||||||
|
|
||||||
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE void Write(uintptr_t reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
|
ALWAYS_INLINE void Write(uintptr_t reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
ALWAYS_INLINE u32 Read(volatile u32 *reg) { return *reg; }
|
||||||
ALWAYS_INLINE IntType Read(volatile IntType *reg) { return *reg; }
|
ALWAYS_INLINE u32 Read(volatile u32 ®) { return reg; }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE IntType Read(volatile IntType ®) { return reg; }
|
|
||||||
|
|
||||||
ALWAYS_INLINE u32 Read(uintptr_t reg) { return Read(reinterpret_cast<volatile u32 *>(reg)); }
|
ALWAYS_INLINE u32 Read(uintptr_t reg) { return Read(reinterpret_cast<volatile u32 *>(reg)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
ALWAYS_INLINE u32 Read(volatile u32 *reg, u32 mask) { return *reg & mask; }
|
||||||
ALWAYS_INLINE IntType Read(volatile IntType *reg, std::type_identity_t<IntType> mask) { return *reg & mask; }
|
ALWAYS_INLINE u32 Read(volatile u32 ®, u32 mask) { return reg & mask; }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE IntType Read(volatile IntType ®, std::type_identity_t<IntType> mask) { return reg & mask; }
|
|
||||||
|
|
||||||
ALWAYS_INLINE u32 Read(uintptr_t reg, u32 mask) { return Read(reinterpret_cast<volatile u32 *>(reg), mask); }
|
ALWAYS_INLINE u32 Read(uintptr_t reg, u32 mask) { return Read(reinterpret_cast<volatile u32 *>(reg), mask); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE IntType Read(volatile IntType *reg, const Masks... masks) { return Read(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
ALWAYS_INLINE u32 Read(volatile u32 *reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
|
||||||
ALWAYS_INLINE IntType Read(volatile IntType ®, const Masks... masks) { return Read(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
|
||||||
|
|
||||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE u32 Read(uintptr_t reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
|
ALWAYS_INLINE u32 Read(volatile u32 ®, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE bool HasValue(volatile IntType *reg, const Values... values) { return Read(reg, static_cast<IntType>((EncodeMask(values) | ...))) == static_cast<IntType>(Encode(values...)); }
|
ALWAYS_INLINE u32 Read(uintptr_t reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE bool HasValue(volatile IntType ®, const Values... values) { return Read(reg, static_cast<IntType>((EncodeMask(values) | ...))) == static_cast<IntType>(Encode(values...)); }
|
ALWAYS_INLINE bool HasValue(volatile u32 *reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
|
||||||
|
|
||||||
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
|
ALWAYS_INLINE bool HasValue(volatile u32 ®, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
|
||||||
|
|
||||||
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE bool HasValue(uintptr_t reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
|
ALWAYS_INLINE bool HasValue(uintptr_t reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
ALWAYS_INLINE u32 GetValue(volatile u32 *reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||||
ALWAYS_INLINE IntType GetValue(volatile IntType *reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
ALWAYS_INLINE u32 GetValue(volatile u32 ®, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||||
|
ALWAYS_INLINE u32 GetValue(uintptr_t reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE IntType GetValue(volatile IntType ®, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
|
||||||
|
|
||||||
ALWAYS_INLINE u32 GetValue(uintptr_t reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE void ReadWrite(volatile IntType *reg, std::type_identity_t<IntType> val, std::type_identity_t<IntType> mask) { *reg = (*reg & (~mask)) | (val & mask); }
|
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE void ReadWrite(volatile IntType ®, std::type_identity_t<IntType> val, std::type_identity_t<IntType> mask) { reg = ( reg & (~mask)) | (val & mask); }
|
|
||||||
|
|
||||||
|
ALWAYS_INLINE void ReadWrite(volatile u32 *reg, u32 val, u32 mask) { *reg = (*reg & (~mask)) | (val & mask); }
|
||||||
|
ALWAYS_INLINE void ReadWrite(volatile u32 ®, u32 val, u32 mask) { reg = ( reg & (~mask)) | (val & mask); }
|
||||||
ALWAYS_INLINE void ReadWrite(uintptr_t reg, u32 val, u32 mask) { ReadWrite(reinterpret_cast<volatile u32 *>(reg), val, mask); }
|
ALWAYS_INLINE void ReadWrite(uintptr_t reg, u32 val, u32 mask) { ReadWrite(reinterpret_cast<volatile u32 *>(reg), val, mask); }
|
||||||
|
|
||||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE void ReadWrite(volatile IntType *reg, const Values... values) { return ReadWrite(reg, static_cast<IntType>((EncodeValue(values) | ...)), static_cast<IntType>((EncodeMask(values) | ...))); }
|
ALWAYS_INLINE void ReadWrite(volatile u32 *reg, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Values> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
|
||||||
ALWAYS_INLINE void ReadWrite(volatile IntType ®, const Values... values) { return ReadWrite(reg, static_cast<IntType>((EncodeValue(values) | ...)), static_cast<IntType>((EncodeMask(values) | ...))); }
|
|
||||||
|
|
||||||
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE void ReadWrite(uintptr_t reg, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
|
ALWAYS_INLINE void ReadWrite(volatile u32 ®, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE void SetBits(volatile IntType *reg, std::type_identity_t<IntType> mask) { *reg = *reg | mask; }
|
ALWAYS_INLINE void ReadWrite(uintptr_t reg, const Values... values) { return ReadWrite(reg, (EncodeValue(values) | ...), (EncodeMask(values) | ...)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE void SetBits(volatile IntType ®, std::type_identity_t<IntType> mask) { reg = reg | mask; }
|
|
||||||
|
|
||||||
|
ALWAYS_INLINE void SetBits(volatile u32 *reg, u32 mask) { *reg = *reg | mask; }
|
||||||
|
ALWAYS_INLINE void SetBits(volatile u32 ®, u32 mask) { reg = reg | mask; }
|
||||||
ALWAYS_INLINE void SetBits(uintptr_t reg, u32 mask) { SetBits(reinterpret_cast<volatile u32 *>(reg), mask); }
|
ALWAYS_INLINE void SetBits(uintptr_t reg, u32 mask) { SetBits(reinterpret_cast<volatile u32 *>(reg), mask); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void SetBits(volatile IntType *reg, const Masks... masks) { return SetBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
ALWAYS_INLINE void SetBits(volatile u32 *reg, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
|
||||||
ALWAYS_INLINE void SetBits(volatile IntType ®, const Masks... masks) { return SetBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
|
||||||
|
|
||||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void SetBits(uintptr_t reg, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
|
ALWAYS_INLINE void SetBits(volatile u32 ®, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void ClearBits(volatile IntType *reg, std::type_identity_t<IntType> mask) { *reg = *reg & ~mask; }
|
ALWAYS_INLINE void SetBits(uintptr_t reg, const Masks... masks) { return SetBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE void ClearBits(volatile IntType ®, std::type_identity_t<IntType> mask) { reg = reg & ~mask; }
|
|
||||||
|
|
||||||
|
ALWAYS_INLINE void ClearBits(volatile u32 *reg, u32 mask) { *reg = *reg & ~mask; }
|
||||||
|
ALWAYS_INLINE void ClearBits(volatile u32 ®, u32 mask) { reg = reg & ~mask; }
|
||||||
ALWAYS_INLINE void ClearBits(uintptr_t reg, u32 mask) { ClearBits(reinterpret_cast<volatile u32 *>(reg), mask); }
|
ALWAYS_INLINE void ClearBits(uintptr_t reg, u32 mask) { ClearBits(reinterpret_cast<volatile u32 *>(reg), mask); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void ClearBits(volatile IntType *reg, const Masks... masks) { return ClearBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
ALWAYS_INLINE void ClearBits(volatile u32 *reg, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
|
||||||
ALWAYS_INLINE void ClearBits(volatile IntType ®, const Masks... masks) { return ClearBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
|
||||||
|
|
||||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void ClearBits(uintptr_t reg, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
|
ALWAYS_INLINE void ClearBits(volatile u32 ®, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void MaskBits(volatile IntType *reg, std::type_identity_t<IntType> mask) { *reg = *reg & mask; }
|
ALWAYS_INLINE void ClearBits(uintptr_t reg, const Masks... masks) { return ClearBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType> requires UnsignedNonConstIntegral<IntType>
|
|
||||||
ALWAYS_INLINE void MaskBits(volatile IntType ®, std::type_identity_t<IntType> mask) { reg = reg & mask; }
|
|
||||||
|
|
||||||
|
ALWAYS_INLINE void MaskBits(volatile u32 *reg, u32 mask) { *reg = *reg & mask; }
|
||||||
|
ALWAYS_INLINE void MaskBits(volatile u32 ®, u32 mask) { reg = reg & mask; }
|
||||||
ALWAYS_INLINE void MaskBits(uintptr_t reg, u32 mask) { MaskBits(reinterpret_cast<volatile u32 *>(reg), mask); }
|
ALWAYS_INLINE void MaskBits(uintptr_t reg, u32 mask) { MaskBits(reinterpret_cast<volatile u32 *>(reg), mask); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void MaskBits(volatile IntType *reg, const Masks... masks) { return MaskBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
ALWAYS_INLINE void MaskBits(volatile u32 *reg, const Masks... masks) { return MaskBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
template<typename IntType, typename... Masks> requires UnsignedNonConstIntegral<IntType> && ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
|
||||||
ALWAYS_INLINE void MaskBits(volatile IntType ®, const Masks... masks) { return MaskBits(reg, static_cast<IntType>((EncodeMask(masks) | ...))); }
|
|
||||||
|
|
||||||
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
ALWAYS_INLINE void MaskBits(uintptr_t reg, const Masks... masks) { return MaskBits(reg, (EncodeMask(masks) | ...)); }
|
ALWAYS_INLINE void MaskBits(volatile u32 ®, const Masks... masks) { return MaskBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
|
template<typename... Masks> requires ((sizeof...(Masks) > 0) && (std::is_same<Masks, BitsMask>::value && ...))
|
||||||
|
ALWAYS_INLINE void MaskBits(uintptr_t reg, const Masks... masks) { return MaskBits(reg, (EncodeMask(masks) | ...)); }
|
||||||
|
|
||||||
#define REG_BITS_MASK(OFFSET, WIDTH) ::ams::reg::BitsMask{OFFSET, WIDTH}
|
#define REG_BITS_MASK(OFFSET, WIDTH) ::ams::reg::BitsMask{OFFSET, WIDTH}
|
||||||
#define REG_BITS_VALUE(OFFSET, WIDTH, VALUE) ::ams::reg::BitsValue{OFFSET, WIDTH, VALUE}
|
#define REG_BITS_VALUE(OFFSET, WIDTH, VALUE) ::ams::reg::BitsValue{OFFSET, WIDTH, VALUE}
|
||||||
@@ -26,9 +26,6 @@ namespace ams::se {
|
|||||||
void ClearAesKeyIv(int slot);
|
void ClearAesKeyIv(int slot);
|
||||||
void LockAesKeySlot(int slot, u32 flags);
|
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 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);
|
void SetEncryptedAesKey128(int dst_slot, int kek_slot, const void *key, size_t key_size);
|
||||||
|
|||||||
@@ -18,14 +18,13 @@
|
|||||||
|
|
||||||
namespace ams::se {
|
namespace ams::se {
|
||||||
|
|
||||||
void SetRegisterAddress(uintptr_t address, uintptr_t address2);
|
void SetRegisterAddress(uintptr_t address);
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
void SetSecure(bool secure);
|
void SetSecure(bool secure);
|
||||||
void SetTzramSecure();
|
void SetTzramSecure();
|
||||||
void SetPerKeySecure();
|
void SetPerKeySecure();
|
||||||
void SetContextSaveSecure();
|
|
||||||
|
|
||||||
void Lockout();
|
void Lockout();
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,4 @@ namespace ams::se {
|
|||||||
bool ValidateStickyBits(const StickyBits &bits);
|
bool ValidateStickyBits(const StickyBits &bits);
|
||||||
void SaveContext(Context *dst);
|
void SaveContext(Context *dst);
|
||||||
|
|
||||||
void ConfigureAutomaticContextSave();
|
|
||||||
void SaveContextAutomatic();
|
|
||||||
void SaveTzramAutomatic();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,13 +89,7 @@ namespace ams::secmon {
|
|||||||
|
|
||||||
constexpr inline const SecureMonitorConfiguration DefaultSecureMonitorConfiguration = {
|
constexpr inline const SecureMonitorConfiguration DefaultSecureMonitorConfiguration = {
|
||||||
.target_firmware = ams::TargetFirmware_Current,
|
.target_firmware = ams::TargetFirmware_Current,
|
||||||
.key_generation = {},
|
|
||||||
.hardware_type = {},
|
|
||||||
.soc_type = {},
|
|
||||||
.hardware_state = {},
|
|
||||||
.pad_0B = {},
|
|
||||||
.flags = SecureMonitorConfigurationFlag_Default,
|
.flags = SecureMonitorConfigurationFlag_Default,
|
||||||
.reserved = {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user