Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46146bd71c | ||
|
|
f7d4960cd3 | ||
|
|
a6c6a95053 | ||
|
|
5120b70231 | ||
|
|
96476a227b | ||
|
|
4586dce57b | ||
|
|
e3900de6c0 | ||
|
|
22fb4ff095 | ||
|
|
9a41e19004 | ||
|
|
b2f4e0c1b4 | ||
|
|
a0f1971353 | ||
|
|
37704d670b | ||
|
|
397d0c4295 | ||
|
|
3981527bb8 | ||
|
|
631de13133 | ||
|
|
2c7f32bbde | ||
|
|
443d43ed7e | ||
|
|
2532ceea2a | ||
|
|
0e8efbb9e9 | ||
|
|
9340183541 | ||
|
|
bd9b01e405 | ||
|
|
53957bb5c7 | ||
|
|
2b84a49ed7 | ||
|
|
895b332a86 | ||
|
|
88b81e5fb0 | ||
|
|
ac04e02a08 | ||
|
|
1c71d12d9d | ||
|
|
37738699f2 | ||
|
|
e973ef7533 | ||
|
|
2ee2a4f1ac | ||
|
|
2a2bffeb35 | ||
|
|
d04046ecaf | ||
|
|
f24171dc41 | ||
|
|
5b02c77400 | ||
|
|
2e7214b6fa | ||
|
|
d52179c708 | ||
|
|
388f9e6455 | ||
|
|
c547c7f0e7 | ||
|
|
4138abbefa | ||
|
|
1275eb0bf3 | ||
|
|
5ac9e45d86 | ||
|
|
feba788bc6 | ||
|
|
f4d10a4481 | ||
|
|
ff310a0647 | ||
|
|
85505db9b7 | ||
|
|
48b4dd48a4 | ||
|
|
8d46d901d9 | ||
|
|
1930880270 | ||
|
|
fa0df994ba | ||
|
|
909a1767a6 | ||
|
|
dbe59fd041 | ||
|
|
9b65daf439 | ||
|
|
4acdc899f5 | ||
|
|
76957e502d | ||
|
|
909397233c | ||
|
|
211a828730 | ||
|
|
28ceedb533 | ||
|
|
f551ca4461 | ||
|
|
2cf5c65bc5 | ||
|
|
47d0d5c6ab | ||
|
|
fd0e3e2160 | ||
|
|
074364753f | ||
|
|
b7d99b732a | ||
|
|
1cccb6efc4 |
10
Makefile
10
Makefile
@@ -70,8 +70,8 @@ dist-no-debug: all
|
|||||||
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.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/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
|
||||||
@@ -99,9 +99,13 @@ dist-no-debug: all
|
|||||||
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
|
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
|
||||||
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
||||||
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
|
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
|
||||||
|
cd atmosphere-$(AMSVER); zip -r ../atmosphere-EXPERIMENTAL-$(AMSVER).zip ./*; cd ../;
|
||||||
|
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
|
||||||
|
|
||||||
@@ -120,7 +124,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.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
||||||
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
|
cp sept/sept-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
|
||||||
|
|||||||
@@ -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 in to using Atmosphere's NCM reimplementation, add enable_ncm = 1
|
; To opt out of using Atmosphere's NCM reimplementation, add disable_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 or 3](https://www.python.org) (optional)
|
+ [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed)
|
||||||
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
|
|||||||
@@ -1,4 +1,54 @@
|
|||||||
# 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
|
## 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.
|
+ 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.
|
+ General system stability improvements to enhance the user's experience.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ This file is located under the `/atmosphere/config/` folder on your SD card and
|
|||||||
Atmosphère provides its own default splashscreen which is displayed at boot time. However, this can be replaced at will.
|
Atmosphère provides its own default splashscreen which is displayed at boot time. However, this can be replaced at will.
|
||||||
|
|
||||||
The boot splashscreen must be a BMP file, it must be 720x1280 (1280x720 rotated 90 degrees left/counterclockwise/anti-clockwise) resolution, and be in 32-bit ARGB format. You can use image editing software such as GIMP or Photoshop to export the image in this format.
|
The boot splashscreen must be a BMP file, it must be 720x1280 (1280x720 rotated 90 degrees left/counterclockwise/anti-clockwise) resolution, and be in 32-bit ARGB format. You can use image editing software such as GIMP or Photoshop to export the image in this format.
|
||||||
|
|
||||||
Add the following lines to BCT.ini and change the value of `custom_splash` to the actual path and filename of your boot splashscreen:
|
Add the following lines to BCT.ini and change the value of `custom_splash` to the actual path and filename of your boot splashscreen:
|
||||||
```
|
```
|
||||||
[stage2]
|
[stage2]
|
||||||
@@ -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-in
|
### NCM opt-out
|
||||||
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:
|
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module. If you wish to disable this reimplementation add the following line to the `stratosphere` section:
|
||||||
```
|
```
|
||||||
[stratosphere]
|
[stratosphere]
|
||||||
enable_ncm = 1
|
disable_ncm = 1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/m4xw/emuMMC
|
remote = https://github.com/m4xw/emuMMC
|
||||||
branch = exo2
|
branch = exo2
|
||||||
commit = 06ab9b895c4264ecc14d3bf9be1260e2096f6037
|
commit = 6a814ebbe72cf5245b863b9edea9cd3801437a12
|
||||||
parent = dccd41f6d25498c191a157123a27724203d3bc37
|
parent = f551ca4461a79908c37307db10cd8cacf8b98f17
|
||||||
method = rebase
|
method = rebase
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -47,6 +47,8 @@
|
|||||||
#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
|
||||||
@@ -104,6 +106,8 @@ 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) {
|
||||||
@@ -169,6 +173,10 @@ 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,6 +68,9 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
58
emummc/source/FS/offsets/1020.h
Normal file
58
emummc/source/FS/offsets/1020.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
||||||
|
* Copyright (c) 2019 Atmosphere-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef __FS_1020_H__
|
||||||
|
#define __FS_1020_H__
|
||||||
|
|
||||||
|
// Accessor vtable getters
|
||||||
|
#define FS_OFFSET_1020_SDMMC_ACCESSOR_GC 0x14E0F0
|
||||||
|
#define FS_OFFSET_1020_SDMMC_ACCESSOR_SD 0x14C200
|
||||||
|
#define FS_OFFSET_1020_SDMMC_ACCESSOR_NAND 0x147080
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
#define FS_OFFSET_1020_SDMMC_WRAPPER_READ 0x1427E0
|
||||||
|
#define FS_OFFSET_1020_SDMMC_WRAPPER_WRITE 0x1428C0
|
||||||
|
#define FS_OFFSET_1020_RTLD 0x634
|
||||||
|
#define FS_OFFSET_1020_RTLD_DESTINATION 0x9C
|
||||||
|
|
||||||
|
#define FS_OFFSET_1020_CLKRST_SET_MIN_V_CLK_RATE 0x141A00
|
||||||
|
|
||||||
|
// Misc funcs
|
||||||
|
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910
|
||||||
|
#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960
|
||||||
|
|
||||||
|
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||||
|
|
||||||
|
// Misc Data
|
||||||
|
#define FS_OFFSET_1020_SD_MUTEX 0xE273E8
|
||||||
|
#define FS_OFFSET_1020_NAND_MUTEX 0xE22DA0
|
||||||
|
#define FS_OFFSET_1020_ACTIVE_PARTITION 0xE22DE0
|
||||||
|
#define FS_OFFSET_1020_SDMMC_DAS_HANDLE 0xE0AB90
|
||||||
|
|
||||||
|
// NOPs
|
||||||
|
#define FS_OFFSET_1020_SD_DAS_INIT 0x15214C
|
||||||
|
|
||||||
|
// Nintendo Paths
|
||||||
|
#define FS_OFFSET_1020_NINTENDO_PATHS \
|
||||||
|
{ \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __FS_1020_H__
|
||||||
58
emummc/source/FS/offsets/1020_exfat.h
Normal file
58
emummc/source/FS/offsets/1020_exfat.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
||||||
|
* Copyright (c) 2019 Atmosphere-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef __FS_1020_EXFAT_H__
|
||||||
|
#define __FS_1020_EXFAT_H__
|
||||||
|
|
||||||
|
// Accessor vtable getters
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_GC 0x14E0F0
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_SD 0x14C200
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_NAND 0x147080
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_READ 0x1427E0
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_WRITE 0x1428C0
|
||||||
|
#define FS_OFFSET_1020_EXFAT_RTLD 0x634
|
||||||
|
#define FS_OFFSET_1020_EXFAT_RTLD_DESTINATION 0x9C
|
||||||
|
|
||||||
|
#define FS_OFFSET_1020_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x141A00
|
||||||
|
|
||||||
|
// Misc funcs
|
||||||
|
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
|
||||||
|
#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960
|
||||||
|
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||||
|
|
||||||
|
// Misc Data
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SD_MUTEX 0xE353E8
|
||||||
|
#define FS_OFFSET_1020_EXFAT_NAND_MUTEX 0xE30DA0
|
||||||
|
#define FS_OFFSET_1020_EXFAT_ACTIVE_PARTITION 0xE30DE0
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SDMMC_DAS_HANDLE 0xE18B90
|
||||||
|
|
||||||
|
// NOPs
|
||||||
|
#define FS_OFFSET_1020_EXFAT_SD_DAS_INIT 0x15214C
|
||||||
|
|
||||||
|
// Nintendo Paths
|
||||||
|
#define FS_OFFSET_1020_EXFAT_NINTENDO_PATHS \
|
||||||
|
{ \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __FS_1020_EXFAT_H__
|
||||||
@@ -96,10 +96,6 @@ 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() {
|
||||||
@@ -130,6 +126,10 @@ 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,6 +18,7 @@
|
|||||||
|
|
||||||
namespace ams::secmon {
|
namespace ams::secmon {
|
||||||
|
|
||||||
|
bool IsPhysicalMemoryAddress(uintptr_t address);
|
||||||
size_t GetPhysicalMemorySize();
|
size_t GetPhysicalMemorySize();
|
||||||
|
|
||||||
void UnmapTzram();
|
void UnmapTzram();
|
||||||
|
|||||||
@@ -648,7 +648,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);
|
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 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 +907,7 @@ namespace ams::secmon {
|
|||||||
reg::Write(MC + MC_SMMU_PPCS1_ASID, MC_REG_BITS_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_PPCS1_ASID_PPCS1_ASID, BpmpAsid));
|
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);
|
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 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. */
|
||||||
|
|||||||
@@ -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); /* 0x034 */
|
SetRegisterAllowed(MC_SMMU_PTC_FLUSH_0); /* 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_NVENC_ASID); /* 0x264 */
|
SetRegisterAllowed(MC_SMMU_MSENC_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 */
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ 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,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
#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"
|
||||||
@@ -157,6 +158,8 @@ 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:
|
||||||
@@ -267,6 +270,14 @@ namespace ams::secmon::smc {
|
|||||||
/* NOTE: This may return values other than 1 in the future. */
|
/* NOTE: This may return values other than 1 in the future. */
|
||||||
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0);
|
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0);
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
@@ -309,6 +320,17 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace ams::secmon::smc {
|
|||||||
ExosphereBlankProdInfo = 65005,
|
ExosphereBlankProdInfo = 65005,
|
||||||
ExosphereAllowCalWrites = 65006,
|
ExosphereAllowCalWrites = 65006,
|
||||||
ExosphereEmummcType = 65007,
|
ExosphereEmummcType = 65007,
|
||||||
|
ExospherePayloadAddress = 65008,
|
||||||
};
|
};
|
||||||
|
|
||||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||||
|
|||||||
108
exosphere/sdmmc_test/Makefile
Normal file
108
exosphere/sdmmc_test/Makefile
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Define the atmosphere board and cpu
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export ATMOSPHERE_BOARD := nx-hac-001
|
||||||
|
export ATMOSPHERE_CPU := arm7tdmi
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# pull in common atmosphere configuration
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
||||||
|
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
||||||
|
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES))))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I.
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib -L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD) check_libexo
|
||||||
|
|
||||||
|
$(BUILD): check_libexo
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
check_libexo:
|
||||||
|
@$(MAKE) --no-print-directory -C ../../libraries/libexosphere arm
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf *.lz4
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
|
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
$(OUTPUT).elf : $(OFILES) ../../../libraries/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/libexosphere.a
|
||||||
|
|
||||||
|
%.elf:
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||||
|
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||||
|
|
||||||
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o %_bin.h: %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
194
exosphere/sdmmc_test/sdmmc_test.ld
Normal file
194
exosphere/sdmmc_test/sdmmc_test.ld
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_ZN3ams10sdmmc_test5StartEv)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
NULL : ORIGIN = 0, LENGTH = 4K
|
||||||
|
test_fw : ORIGIN = 0x40010000, LENGTH = 32K
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* =========== CODE section =========== */
|
||||||
|
PROVIDE(__start__ = ORIGIN(test_fw));
|
||||||
|
. = __start__;
|
||||||
|
__code_start = . ;
|
||||||
|
|
||||||
|
.crt0 :
|
||||||
|
{
|
||||||
|
KEEP (*(.crt0 .crt0.*))
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.vectors :
|
||||||
|
{
|
||||||
|
KEEP (*(.vectors .vectors.*))
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP( *(.init) )
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.plt :
|
||||||
|
{
|
||||||
|
*(.plt)
|
||||||
|
*(.iplt)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP( *(.fini) )
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
|
||||||
|
/* =========== RODATA section =========== */
|
||||||
|
. = ALIGN(8);
|
||||||
|
__rodata_start = . ;
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >test_fw
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >test_fw
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >test_fw
|
||||||
|
|
||||||
|
.hash : { *(.hash) } >test_fw
|
||||||
|
|
||||||
|
/* =========== DATA section =========== */
|
||||||
|
. = ALIGN(8);
|
||||||
|
__data_start = . ;
|
||||||
|
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >test_fw
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >test_fw
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >test_fw
|
||||||
|
|
||||||
|
.preinit_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.init_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.fini_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.ctors ALIGN(8) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
.dtors ALIGN(8) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
__got_start__ = .;
|
||||||
|
|
||||||
|
.got : { *(.got) *(.igot) } >test_fw
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) } >test_fw
|
||||||
|
|
||||||
|
__got_end__ = .;
|
||||||
|
|
||||||
|
.data ALIGN(8) :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
} >test_fw
|
||||||
|
|
||||||
|
__bss_start__ = .;
|
||||||
|
.bss ALIGN(8) :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(16);
|
||||||
|
} >test_fw
|
||||||
|
__bss_end__ = .;
|
||||||
|
|
||||||
|
__end__ = ABSOLUTE(.) ;
|
||||||
|
|
||||||
|
__total_size__ = (__end__ - __start__);
|
||||||
|
|
||||||
|
__stack_top__ = 0x40031000;
|
||||||
|
__stack_bottom__ = 0x40030000;
|
||||||
|
|
||||||
|
/* ==================
|
||||||
|
==== Metadata ====
|
||||||
|
================== */
|
||||||
|
|
||||||
|
/* Discard sections that difficult post-processing */
|
||||||
|
/DISCARD/ : { *(.group .comment .note .interp) }
|
||||||
|
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
}
|
||||||
7
exosphere/sdmmc_test/sdmmc_test.specs
Normal file
7
exosphere/sdmmc_test/sdmmc_test.specs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T %:getenv(TOPDIR /sdmmc_test.ld) --gc-sections --nmagic -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
||||||
146
exosphere/sdmmc_test/source/sdmmc_test_main.cpp
Normal file
146
exosphere/sdmmc_test/source/sdmmc_test_main.cpp
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::sdmmc_test {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
|
||||||
|
constexpr inline auto Port = sdmmc::Port_SdCard0;
|
||||||
|
alignas(8) constinit u8 g_sd_work_buffer[sdmmc::SdCardWorkBufferSize];
|
||||||
|
|
||||||
|
constexpr inline u32 SectorIndex = 0;
|
||||||
|
constexpr inline u32 SectorCount = 2;
|
||||||
|
|
||||||
|
NORETURN void PmcMainReboot() {
|
||||||
|
/* Write enable to MAIN_RESET. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
|
||||||
|
|
||||||
|
/* Wait forever until we're reset. */
|
||||||
|
AMS_INFINITE_LOOP();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckResult(const Result result) {
|
||||||
|
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
|
||||||
|
if (R_FAILED(result)) {
|
||||||
|
DEBUG[1] = result.GetValue();
|
||||||
|
PmcMainReboot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Main() {
|
||||||
|
/* Perform butchered hwinit. */
|
||||||
|
/* TODO: replace with simpler, non-C logic. */
|
||||||
|
/* nx_hwinit(); */
|
||||||
|
|
||||||
|
/* Clear output buffer for debug. */
|
||||||
|
std::memset((void *)0x40038000, 0xAA, 0x400);
|
||||||
|
|
||||||
|
/* Normally, these pins get configured by boot sysmodule during initial pinmux config. */
|
||||||
|
/* However, they're required to access the SD card. */
|
||||||
|
{
|
||||||
|
const uintptr_t apb_misc = dd::QueryIoMapping(0x70000000, 0x4000);
|
||||||
|
|
||||||
|
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CLK, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CLK_PM, SDMMC1));
|
||||||
|
|
||||||
|
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CMD, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CMD_PM, SDMMC1));
|
||||||
|
|
||||||
|
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT3, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT3_PM, SDMMC1));
|
||||||
|
|
||||||
|
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT2, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT2_PM, SDMMC1));
|
||||||
|
|
||||||
|
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT1, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT1_PM, SDMMC1));
|
||||||
|
|
||||||
|
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT0, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, SDMMC1));
|
||||||
|
|
||||||
|
reg::ReadWrite(apb_misc + PINMUX_AUX_DMIC3_CLK, PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, RSVD2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Debug signaler. */
|
||||||
|
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
|
||||||
|
DEBUG[0] = 0;
|
||||||
|
DEBUG[1] = 0xAAAAAAAA;
|
||||||
|
|
||||||
|
/* Initialize sdmmc library. */
|
||||||
|
sdmmc::Initialize(Port);
|
||||||
|
DEBUG[0] = 1;
|
||||||
|
|
||||||
|
sdmmc::SetSdCardWorkBuffer(Port, g_sd_work_buffer, sizeof(g_sd_work_buffer));
|
||||||
|
DEBUG[0] = 2;
|
||||||
|
|
||||||
|
Result result = sdmmc::Activate(Port);
|
||||||
|
DEBUG[0] = 3;
|
||||||
|
CheckResult(result);
|
||||||
|
|
||||||
|
/* Read the first two sectors from disk. */
|
||||||
|
void * const sector_dst = reinterpret_cast<void *>(0x40038000);
|
||||||
|
result = sdmmc::Read(sector_dst, SectorCount * sdmmc::SectorSize, Port, SectorIndex, SectorCount);
|
||||||
|
DEBUG[0] = 4;
|
||||||
|
CheckResult(result);
|
||||||
|
|
||||||
|
/* Get the connection status. */
|
||||||
|
sdmmc::SpeedMode speed_mode;
|
||||||
|
sdmmc::BusWidth bus_width;
|
||||||
|
result = sdmmc::CheckSdCardConnection(std::addressof(speed_mode), std::addressof(bus_width), Port);
|
||||||
|
|
||||||
|
/* Save status for debug. */
|
||||||
|
DEBUG[0] = 5;
|
||||||
|
DEBUG[1] = result.GetValue();
|
||||||
|
DEBUG[2] = static_cast<u32>(speed_mode);
|
||||||
|
DEBUG[3] = static_cast<u32>(bus_width);
|
||||||
|
|
||||||
|
/* Perform a reboot. */
|
||||||
|
PmcMainReboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void ExceptionHandler() {
|
||||||
|
PmcMainReboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ams::diag {
|
||||||
|
|
||||||
|
void AbortImpl() {
|
||||||
|
sdmmc_test::ExceptionHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
37
exosphere/sdmmc_test/source/sdmmc_test_start.s
Normal file
37
exosphere/sdmmc_test/source/sdmmc_test_start.s
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section .crt0.text._ZN3ams10sdmmc_test5StartEv, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.global _ZN3ams10sdmmc_test5StartEv
|
||||||
|
_ZN3ams10sdmmc_test5StartEv:
|
||||||
|
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||||
|
msr cpsr_cxsf, #0xDF
|
||||||
|
|
||||||
|
/* Set the stack pointer. */
|
||||||
|
ldr sp, =__stack_top__
|
||||||
|
|
||||||
|
/* Set our link register to the exception handler. */
|
||||||
|
ldr lr, =_ZN3ams10sdmmc_test16ExceptionHandlerEv
|
||||||
|
|
||||||
|
/* Call init array functions. */
|
||||||
|
bl __libc_init_array
|
||||||
|
|
||||||
|
/* Invoke main. */
|
||||||
|
b _ZN3ams10sdmmc_test4MainEv
|
||||||
|
|
||||||
|
/* Infinite loop. */
|
||||||
|
2: b 2b
|
||||||
@@ -30,7 +30,7 @@ _ZN3ams8warmboot5StartEv:
|
|||||||
|
|
||||||
/* Invoke main. */
|
/* Invoke main. */
|
||||||
ldr r0, =_metadata
|
ldr r0, =_metadata
|
||||||
bl _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
b _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
||||||
|
|
||||||
/* Infinite loop. */
|
/* Infinite loop. */
|
||||||
1: b 1b
|
1: b 1b
|
||||||
@@ -24,6 +24,9 @@
|
|||||||
#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) {
|
||||||
@@ -42,6 +45,8 @@ 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:
|
case 0xFFD:
|
||||||
return "Stack overflow";
|
return "Stack overflow";
|
||||||
case 0xFFE:
|
case 0xFFE:
|
||||||
@@ -51,6 +56,61 @@ static const char *get_error_desc_str(uint32_t error_desc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _try_suggest_fix(const atmosphere_fatal_error_ctx *ctx) {
|
||||||
|
/* Try to recognize certain errors automatically, and suggest fixes for them. */
|
||||||
|
const char *suggestion = NULL;
|
||||||
|
|
||||||
|
if (ctx->error_desc == 0xFFE) {
|
||||||
|
if (ctx->program_id == PROGRAM_ID_AMS_MITM) {
|
||||||
|
/* When a user has archive bits set improperly, attempting to create an automatic backup will fail */
|
||||||
|
/* to create the file path with error 0x202 (fs::ResultPathNotFound()) */
|
||||||
|
if (ctx->gprs[0] == 0x202) {
|
||||||
|
/* When the archive bit error is occurring, it manifests as failure to create automatic backup. */
|
||||||
|
/* Thus, we can search the stack for the automatic backups path. */
|
||||||
|
const char * const automatic_backups_prefix = "automatic_backups/X" /* ..... */;
|
||||||
|
const int prefix_len = strlen(automatic_backups_prefix);
|
||||||
|
|
||||||
|
for (size_t i = 0; i + prefix_len < ctx->stack_dump_size; ++i) {
|
||||||
|
if (memcmp(&ctx->stack_dump[i], automatic_backups_prefix, prefix_len) == 0) {
|
||||||
|
suggestion = "The atmosphere directory may improperly have archive\n"
|
||||||
|
"bits set. Please try running an archive bit fixer tool\n"
|
||||||
|
"(for example, the one in Hekate).\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ctx->gprs[0] == 0x249A02) { /* fs::ResultResultExFatUnavailable() */
|
||||||
|
/* When a user installs non-exFAT firm but has an exFAT formatted SD card, this error will */
|
||||||
|
/* be returned on attempt to access the SD card. */
|
||||||
|
suggestion = "Your console has non-exFAT firmware installed, but your SD card\n"
|
||||||
|
"is formatted as exFAT. Format your SD card as FAT32, or manually\n"
|
||||||
|
"flash exFAT firmware to package2.\n";
|
||||||
|
}
|
||||||
|
} else if (ctx->program_id == PROGRAM_ID_BOOT) {
|
||||||
|
/* 9.x -> 10.x updated the API for SvcQueryIoMapping. */
|
||||||
|
/* This can cause the kernel to reject incorrect-ABI calls by boot when a partial update is applied */
|
||||||
|
/* (older kernel in package2, for some reason). */
|
||||||
|
for (size_t i = 0; i < 8; ++i) {
|
||||||
|
if (ctx->gprs[i] == 0xF201) {
|
||||||
|
suggestion = "A partial update may have been improperly performed.\n"
|
||||||
|
"To fix, try manually flashing latest package2 to MMC.\n"
|
||||||
|
"\n"
|
||||||
|
"For help doing this, seek support in the ReSwitched or\n"
|
||||||
|
"Nintendo Homebrew discord servers.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ctx->error_desc == 0xF00) { /* Kernel Panic */
|
||||||
|
suggestion = "Please contact SciresM#0524 on Discord, or create an issue\n"
|
||||||
|
"on the Atmosphere GitHub issue tracker. Thank you very much\n"
|
||||||
|
"for helping to test mesosphere.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suggestion != NULL) {
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n%s", suggestion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void _check_and_display_atmosphere_fatal_error(void) {
|
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 &&
|
||||||
@@ -84,7 +144,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, "Title ID: %016llx\n", ctx.title_id);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Program ID: %016llx\n", ctx.program_id);
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc);
|
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. */
|
||||||
@@ -99,6 +159,9 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t error_desc;
|
uint32_t error_desc;
|
||||||
uint64_t title_id;
|
uint64_t program_id;
|
||||||
union {
|
union {
|
||||||
uint64_t gprs[32];
|
uint64_t gprs[32];
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -186,11 +186,15 @@ DEPENDS := $(OFILES:.o=.d)
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all : $(OUTPUT).bin
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
$(OUTPUT).bin : $(OUTPUT).elf
|
$(OUTPUT).bin : $(OUTPUT)-experimental.bin
|
||||||
|
@python $(TOPDIR)/fusee_make_standard.py $(OUTPUT)-experimental.bin $(OUTPUT).bin
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
$(OUTPUT)-experimental.bin : $(OUTPUT)-experimental.elf
|
||||||
$(OBJCOPY) -S -O binary $< $@
|
$(OBJCOPY) -S -O binary $< $@
|
||||||
@echo built ... $(notdir $@)
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
$(OUTPUT).elf : $(OFILES)
|
$(OUTPUT)-experimental.elf : $(OFILES)
|
||||||
|
|
||||||
%.elf: $(OFILES)
|
%.elf: $(OFILES)
|
||||||
@echo linking $(notdir $@)
|
@echo linking $(notdir $@)
|
||||||
|
|||||||
37
fusee/fusee-secondary/fusee_make_standard.py
Normal file
37
fusee/fusee-secondary/fusee_make_standard.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import sys, os
|
||||||
|
from struct import pack as pk, unpack as up
|
||||||
|
|
||||||
|
def make_standard(exp):
|
||||||
|
std = exp[:]
|
||||||
|
_, metadata_offset, is_exp = up('<III', exp[:12])
|
||||||
|
assert is_exp == 1
|
||||||
|
|
||||||
|
# Patch the experimental flag to zero.
|
||||||
|
std = std[:8] + pk('<I', 0) + std[12:]
|
||||||
|
|
||||||
|
# Locate the mesosphere content header, patch to be experimental.
|
||||||
|
magic, size, code_ofs, content_ofs, num_contents, ver, sup_ver, rev = up('<IIIIIIII', exp[metadata_offset:metadata_offset + 0x20])
|
||||||
|
for i in range(num_contents):
|
||||||
|
start, size, cnt_type, flag0, flag1, flag2, pad = up('<IIBBBBI', exp[content_ofs + 0x20 * i:content_ofs + 0x20 * i + 0x10])
|
||||||
|
if cnt_type == 10: # CONTENT_TYPE_KRN
|
||||||
|
assert exp[content_ofs + 0x20 * i + 0x10:content_ofs + 0x20 * i + 0x10 + len(b'mesosphere') + 1] == (b'mesosphere\x00')
|
||||||
|
assert flag0 == 0 and flag1 == 0 and flag2 == 0
|
||||||
|
std = std[:content_ofs + 0x20 * i] + pk('<IIBBBBI', start, size, cnt_type, flag0 | 0x1, flag1, flag2, pad) + std[content_ofs + 0x20 * i + 0x10:]
|
||||||
|
|
||||||
|
return std
|
||||||
|
|
||||||
|
|
||||||
|
def main(argc, argv):
|
||||||
|
if argc != 3:
|
||||||
|
print('Usage: %s input output' % argv[0])
|
||||||
|
return 1
|
||||||
|
with open(argv[1], 'rb') as f:
|
||||||
|
experimental = f.read()
|
||||||
|
with open(argv[2], 'wb') as f:
|
||||||
|
f.write(make_standard(experimental))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main(len(sys.argv), sys.argv))
|
||||||
@@ -254,4 +254,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -420,6 +420,9 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
|
|||||||
|
|
||||||
"\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", /* FS_VER_10_0_0 */
|
"\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) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
#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,6 +67,8 @@
|
|||||||
|
|
||||||
extern const uint8_t warmboot_bin[];
|
extern const uint8_t warmboot_bin[];
|
||||||
|
|
||||||
|
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,
|
||||||
0xCB, 0x4E, 0x4A, 0x52, 0x0B, 0x1A, 0x8E, 0xDE, 0x41, 0x87, 0x6F, 0xB7, 0x31, 0x05, 0x5F, 0xAA,
|
0xCB, 0x4E, 0x4A, 0x52, 0x0B, 0x1A, 0x8E, 0xDE, 0x41, 0x87, 0x6F, 0xB7, 0x31, 0x05, 0x5F, 0xAA,
|
||||||
@@ -209,11 +212,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_ENABLE_NCM_KEY) == 0) {
|
} else if (strcmp(name, STRATOSPHERE_DISABLE_NCM_KEY) == 0) {
|
||||||
sscanf(value, "%d", &tmp);
|
sscanf(value, "%d", &tmp);
|
||||||
strat_cfg->ncm_enabled = tmp != 0;
|
strat_cfg->ncm_disabled = tmp != 0;
|
||||||
if (strat_cfg->ncm_enabled) {
|
if (strat_cfg->ncm_disabled) {
|
||||||
stratosphere_enable_ncm();
|
stratosphere_disable_ncm();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -236,6 +239,7 @@ 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("5077973537f6735b564dd7475b779f87", 10_1_1); /* Exclusive to China. */
|
||||||
CHECK_NCA("fd1faed0ca750700d254c0915b93d506", 10_1_0);
|
CHECK_NCA("fd1faed0ca750700d254c0915b93d506", 10_1_0);
|
||||||
CHECK_NCA("34728c771299443420820d8ae490ea41", 10_0_4);
|
CHECK_NCA("34728c771299443420820d8ae490ea41", 10_0_4);
|
||||||
@@ -623,6 +627,7 @@ 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;
|
||||||
@@ -932,7 +937,6 @@ uint32_t nxboot_main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Configure mesosphere. */
|
/* Configure mesosphere. */
|
||||||
/* TODO: Support non-SD/embedded mesosphere. */
|
|
||||||
{
|
{
|
||||||
size_t sd_meso_size = get_file_size("atmosphere/mesosphere.bin");
|
size_t sd_meso_size = get_file_size("atmosphere/mesosphere.bin");
|
||||||
if (sd_meso_size != 0) {
|
if (sd_meso_size != 0) {
|
||||||
@@ -947,6 +951,20 @@ uint32_t nxboot_main(void) {
|
|||||||
fatal_error("Error: failed to read atmosphere/mesosphere.bin!\n");
|
fatal_error("Error: failed to read atmosphere/mesosphere.bin!\n");
|
||||||
}
|
}
|
||||||
mesosphere_size = sd_meso_size;
|
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 {
|
} else {
|
||||||
mesosphere = NULL;
|
mesosphere = NULL;
|
||||||
mesosphere_size = 0;
|
mesosphere_size = 0;
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ _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
|
||||||
@@ -68,6 +71,14 @@ _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:
|
||||||
@@ -135,6 +146,17 @@ _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__
|
||||||
@@ -249,7 +271,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_FLAG0_EXPERIMENTAL
|
.byte CONTENT_FLAG_NONE
|
||||||
.byte CONTENT_FLAG_NONE
|
.byte CONTENT_FLAG_NONE
|
||||||
.byte CONTENT_FLAG_NONE
|
.byte CONTENT_FLAG_NONE
|
||||||
.word 0xCCCCCCCC
|
.word 0xCCCCCCCC
|
||||||
@@ -267,17 +289,6 @@ _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,7 +48,7 @@ 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 = false;
|
static bool g_stratosphere_ncm_enabled = true;
|
||||||
|
|
||||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
|
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
|
||||||
|
|
||||||
@@ -58,17 +58,17 @@ emummc_fs_ver_t stratosphere_get_fs_version(void) {
|
|||||||
return g_fs_ver;
|
return g_fs_ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stratosphere_enable_ncm(void) {
|
void stratosphere_disable_ncm(void) {
|
||||||
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
|
/* 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 will default to off for some time, until the code has been thoroughly */
|
/* the implementation may be optionally disabled for those not comfortable using it. */
|
||||||
/* tested in practice. */
|
|
||||||
|
|
||||||
/* PLEASE NOTE: The default behavior will be NCM on in a future atmosphere release, */
|
|
||||||
/* and this opt-in functionality will be removed at that time. */
|
|
||||||
|
|
||||||
g_stratosphere_ncm_enabled = true;
|
/* PLEASE NOTE: The NCM reimplementation has been well-tested, and correspondingly opt-out */
|
||||||
|
/* functionality will be removed in Atmosphere 1.0.0. */
|
||||||
|
|
||||||
|
g_stratosphere_ncm_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GCC doesn't consider the size as const... we have to write it ourselves. */
|
/* 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_enable_ncm(void);
|
void stratosphere_disable_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_enabled;
|
bool ncm_disabled;
|
||||||
} stratosphere_cfg_t;
|
} stratosphere_cfg_t;
|
||||||
|
|
||||||
#define STRATOSPHERE_NOGC_KEY "nogc"
|
#define STRATOSPHERE_NOGC_KEY "nogc"
|
||||||
#define STRATOSPHERE_ENABLE_NCM_KEY "enable_ncm"
|
#define STRATOSPHERE_DISABLE_NCM_KEY "disable_ncm"
|
||||||
|
|
||||||
#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 = 2d522dc6a12b2eb5eb3f103a8c5b5126ca301b1a
|
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
||||||
parent = 35fffade4ea4fdbba9cf2443c321e724c9e70c3d
|
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ endif
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS ?=
|
||||||
|
|
||||||
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
||||||
export ATMOSPHERE_SETTINGS := -fPIE -g
|
export ATMOSPHERE_SETTINGS := -fPIE -g $(ATMOSPHERE_BUILD_SETTINGS)
|
||||||
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
|
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 -Wno-format-zero-length -Wno-stringop-truncation
|
||||||
@@ -132,10 +134,15 @@ FIND_SOURCE_FILES=$(foreach dir,$1,$(filter-out $(notdir $(wildcard $(dir)/*.arc
|
|||||||
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),os,$(ATMOSPHERE_OS_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))
|
$(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
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%.gch: %.hpp
|
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
|
||||||
@echo $<
|
@echo Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
|
||||||
$(CXX) -w -x c++-header -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).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)
|
||||||
|
|||||||
@@ -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 := -lmesosphere
|
export LIBS := -l$(LIBMESOSPHERE_NAME)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# list of directories containing libraries, this must be the top level containing
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ $(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
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#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>
|
||||||
@@ -41,4 +40,3 @@
|
|||||||
#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>
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#include <vapours.hpp>
|
|
||||||
|
|
||||||
#include <exosphere/tegra/tegra_ahb_arbc.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_apb_misc.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_avp_cache.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_clkrst.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_emc.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_evp.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_flow_ctlr.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_ictlr.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_mc.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_mselect.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_pinmux.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_pg_up.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_pmc.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_sb.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_sysctr0.hpp>
|
|
||||||
#include <exosphere/tegra/tegra_timer.hpp>
|
|
||||||
@@ -20,14 +20,6 @@ namespace ams::util {
|
|||||||
|
|
||||||
void SetRegisterAddress(uintptr_t address);
|
void SetRegisterAddress(uintptr_t address);
|
||||||
|
|
||||||
u32 GetMicroSeconds();
|
|
||||||
void WaitMicroSeconds(int us);
|
|
||||||
|
|
||||||
void ClearMemory(void *ptr, size_t size);
|
void ClearMemory(void *ptr, size_t size);
|
||||||
|
|
||||||
template<typename T, typename U> requires std::integral<T> && std::integral<U>
|
|
||||||
constexpr T DivideUp(T x, U y) {
|
|
||||||
return (x + (y - 1)) / y;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
27
libraries/libexosphere/source/libc/libexo_cxx.cpp
Normal file
27
libraries/libexosphere/source/libc/libexo_cxx.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* cxx implementation details to be stubbed here, as needed. */
|
||||||
|
void __cxa_pure_virtual() { AMS_ABORT("pure virtual function call"); }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
160
libraries/libexosphere/source/libc/libgcc_division.arch.arm.c
Normal file
160
libraries/libexosphere/source/libc/libgcc_division.arch.arm.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, STMicroelectronics International N.V.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Form ABI specifications:
|
||||||
|
* int __aeabi_idiv(int numerator, int denominator);
|
||||||
|
* unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
|
||||||
|
*
|
||||||
|
* typedef struct { int quot; int rem; } idiv_return;
|
||||||
|
* typedef struct { unsigned quot; unsigned rem; } uidiv_return;
|
||||||
|
*
|
||||||
|
* __value_in_regs idiv_return __aeabi_idivmod(int numerator,
|
||||||
|
* int *denominator);
|
||||||
|
* __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator,
|
||||||
|
* unsigned denominator);
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */
|
||||||
|
struct qr {
|
||||||
|
unsigned q; /* computed quotient */
|
||||||
|
unsigned r; /* computed remainder */
|
||||||
|
unsigned q_n; /* specficies if quotient shall be negative */
|
||||||
|
unsigned r_n; /* specficies if remainder shall be negative */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void uint_div_qr(unsigned numerator, unsigned denominator,
|
||||||
|
struct qr *qr);
|
||||||
|
|
||||||
|
/* returns in R0 and R1 by tail calling an asm function */
|
||||||
|
unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator);
|
||||||
|
|
||||||
|
unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
|
||||||
|
|
||||||
|
/* returns in R0 and R1 by tail calling an asm function */
|
||||||
|
signed __aeabi_idivmod(signed numerator, signed denominator);
|
||||||
|
|
||||||
|
signed __aeabi_idiv(signed numerator, signed denominator);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator)
|
||||||
|
* Numerator and Denominator are received in R0 and R1.
|
||||||
|
* Where __ste_idivmod_ret_t is returned in R0 and R1.
|
||||||
|
*
|
||||||
|
* __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator,
|
||||||
|
* unsigned denominator)
|
||||||
|
* Numerator and Denominator are received in R0 and R1.
|
||||||
|
* Where __ste_uidivmod_ret_t is returned in R0 and R1.
|
||||||
|
*/
|
||||||
|
#ifdef __GNUC__
|
||||||
|
signed ret_idivmod_values(signed quotient, signed remainder);
|
||||||
|
unsigned ret_uidivmod_values(unsigned quotient, unsigned remainder);
|
||||||
|
#else
|
||||||
|
#error "Compiler not supported"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void division_qr(unsigned n, unsigned p, struct qr *qr)
|
||||||
|
{
|
||||||
|
unsigned i = 1, q = 0;
|
||||||
|
if (p == 0) {
|
||||||
|
qr->r = 0xFFFFFFFF; /* division by 0 */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((p >> 31) == 0) {
|
||||||
|
i = i << 1; /* count the max division steps */
|
||||||
|
p = p << 1; /* increase p until it has maximum size*/
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
q = q << 1; /* write bit in q at index (size-1) */
|
||||||
|
if (n >= p)
|
||||||
|
{
|
||||||
|
n -= p;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
p = p >> 1; /* decrease p */
|
||||||
|
i = i >> 1; /* decrease remaining size in q */
|
||||||
|
}
|
||||||
|
qr->r = n;
|
||||||
|
qr->q = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uint_div_qr(unsigned numerator, unsigned denominator, struct qr *qr)
|
||||||
|
{
|
||||||
|
|
||||||
|
division_qr(numerator, denominator, qr);
|
||||||
|
|
||||||
|
/* negate quotient and/or remainder according to requester */
|
||||||
|
if (qr->q_n)
|
||||||
|
qr->q = -qr->q;
|
||||||
|
if (qr->r_n)
|
||||||
|
qr->r = -qr->r;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
|
||||||
|
{
|
||||||
|
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||||
|
|
||||||
|
uint_div_qr(numerator, denominator, &qr);
|
||||||
|
|
||||||
|
return qr.q;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator)
|
||||||
|
{
|
||||||
|
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||||
|
|
||||||
|
uint_div_qr(numerator, denominator, &qr);
|
||||||
|
|
||||||
|
return ret_uidivmod_values(qr.q, qr.r);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed __aeabi_idiv(signed numerator, signed denominator)
|
||||||
|
{
|
||||||
|
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||||
|
|
||||||
|
if (((numerator < 0) && (denominator > 0)) ||
|
||||||
|
((numerator > 0) && (denominator < 0)))
|
||||||
|
qr.q_n = 1; /* quotient shall be negate */
|
||||||
|
if (numerator < 0) {
|
||||||
|
numerator = -numerator;
|
||||||
|
qr.r_n = 1; /* remainder shall be negate */
|
||||||
|
}
|
||||||
|
if (denominator < 0)
|
||||||
|
denominator = -denominator;
|
||||||
|
|
||||||
|
uint_div_qr(numerator, denominator, &qr);
|
||||||
|
|
||||||
|
return qr.q;
|
||||||
|
}
|
||||||
|
|
||||||
|
signed __aeabi_idivmod(signed numerator, signed denominator)
|
||||||
|
{
|
||||||
|
struct qr qr = { .q_n = 0, .r_n = 0 };
|
||||||
|
|
||||||
|
if (((numerator < 0) && (denominator > 0)) ||
|
||||||
|
((numerator > 0) && (denominator < 0)))
|
||||||
|
qr.q_n = 1; /* quotient shall be negate */
|
||||||
|
if (numerator < 0) {
|
||||||
|
numerator = -numerator;
|
||||||
|
qr.r_n = 1; /* remainder shall be negate */
|
||||||
|
}
|
||||||
|
if (denominator < 0)
|
||||||
|
denominator = -denominator;
|
||||||
|
|
||||||
|
uint_div_qr(numerator, denominator, &qr);
|
||||||
|
|
||||||
|
return ret_idivmod_values(qr.q, qr.r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, STMicroelectronics International N.V.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* signed ret_idivmod_values(signed quot, signed rem);
|
||||||
|
* return quotient and remaining the EABI way (regs r0,r1)
|
||||||
|
*/
|
||||||
|
.section .text.ret_idivmod_values, "ax", %progbits
|
||||||
|
.globl ret_idivmod_values
|
||||||
|
.align 0
|
||||||
|
.syntax unified
|
||||||
|
ret_idivmod_values:
|
||||||
|
bx lr
|
||||||
|
.type ret_idivmod_values, %function
|
||||||
|
.size ret_idivmod_values, .-ret_idivmod_values
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unsigned ret_uidivmod_values(unsigned quot, unsigned rem);
|
||||||
|
* return quotient and remaining the EABI way (regs r0,r1)
|
||||||
|
*/
|
||||||
|
.section .text.ret_uidivmod_values, "ax", %progbits
|
||||||
|
.globl ret_uidivmod_values
|
||||||
|
.align 0
|
||||||
|
.syntax unified
|
||||||
|
ret_uidivmod_values:
|
||||||
|
bx lr
|
||||||
|
.type ret_uidivmod_values, %function
|
||||||
|
.size ret_uidivmod_values, .-ret_uidivmod_values
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
|
||||||
|
This file is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 3, or (at your option) any
|
||||||
|
later version.
|
||||||
|
This file is distributed in the hope that 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.
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
|
.section .text.__gnu_thumb1_case_uqi, "ax", %progbits
|
||||||
|
.globl __gnu_thumb1_case_uqi
|
||||||
|
.align 0
|
||||||
|
.thumb_func
|
||||||
|
.syntax unified
|
||||||
|
__gnu_thumb1_case_uqi:
|
||||||
|
push {r1}
|
||||||
|
mov r1, lr
|
||||||
|
lsrs r1, r1, #1
|
||||||
|
lsls r1, r1, #1
|
||||||
|
ldrb r1, [r1, r0]
|
||||||
|
lsls r1, r1, #1
|
||||||
|
add lr, lr, r1
|
||||||
|
pop {r1}
|
||||||
|
bx lr
|
||||||
|
.type __gnu_thumb1_case_uqi, %function
|
||||||
|
.size __gnu_thumb1_case_uqi, .-__gnu_thumb1_case_uqi
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in common atmosphere configuration
|
# pull in common atmosphere configuration
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
|
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||||
@@ -28,7 +30,7 @@ LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
|
|||||||
# no real need to edit anything past this point unless you need to add additional
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
# rules for different file extensions
|
# rules for different file extensions
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
ifneq ($(__RECURSIVE__),1)
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
||||||
@@ -54,7 +56,7 @@ endif
|
|||||||
|
|
||||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
export GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.gch),$(notdir $(hdr)))
|
export GCH_DIRS := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
|
||||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
@@ -62,41 +64,70 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
-I.
|
-I.
|
||||||
|
|
||||||
.PHONY: clean all
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS :=
|
||||||
|
all: release
|
||||||
|
|
||||||
|
define ATMOSPHERE_ADD_TARGET
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
|
||||||
|
|
||||||
|
$(strip $1): $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||||
|
|
||||||
|
$$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2) : $$(ATMOSPHERE_LIBRARY_DIR) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(SOURCES) $$(INCLUDES) $$(GCH_DIRS)
|
||||||
|
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(CURDIR)/$$@ $(3) \
|
||||||
|
ATMOSPHERE_GCH_IDENTIFIER="$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1)" \
|
||||||
|
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
-f $$(THIS_MAKEFILE)
|
||||||
|
|
||||||
|
clean-$(strip $1):
|
||||||
|
@echo clean $(strip $1) ...
|
||||||
|
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||||
|
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
|
||||||
|
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, $(TARGET)_debug.a, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
|
||||||
|
))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: lib/$(TARGET).a
|
|
||||||
|
|
||||||
lib:
|
-include $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME).mk
|
||||||
|
|
||||||
|
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
|
||||||
|
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
|
||||||
|
|
||||||
|
.PHONY: clean all $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||||
|
|
||||||
|
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
|
||||||
release:
|
$(ATMOSPHERE_BUILD_DIR)/%:
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
|
||||||
lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
|
|
||||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
|
||||||
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
|
|
||||||
DEPSDIR=$(CURDIR)/release \
|
|
||||||
--no-print-directory -C release \
|
|
||||||
-f $(CURDIR)/Makefile
|
|
||||||
|
|
||||||
dist-bin: all
|
|
||||||
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib
|
|
||||||
|
|
||||||
dist-src:
|
|
||||||
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile
|
|
||||||
|
|
||||||
dist: dist-src dist-bin
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@rm -fr release lib *.bz2
|
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2 $(ALL_GCH_FILES)
|
||||||
|
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
|
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
|
||||||
|
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES),$(notdir $(patsubst %.hpp.gch/,%.d,$(dir $(hdr)))))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# main targets
|
# main targets
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
|
|
||||||
/* Power management. */
|
/* Power management. */
|
||||||
static void SleepSystem();
|
static void SleepSystem();
|
||||||
static NORETURN void StopSystem();
|
static NORETURN void StopSystem(void *arg = nullptr);
|
||||||
|
|
||||||
/* User access. */
|
/* User access. */
|
||||||
static void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
|
static void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if 1 || defined(AMS_BUILD_FOR_AUDITING)
|
#if defined(AMS_BUILD_FOR_AUDITING)
|
||||||
#define MESOSPHERE_BUILD_FOR_AUDITING
|
#define MESOSPHERE_BUILD_FOR_AUDITING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -28,4 +28,5 @@
|
|||||||
#define MESOSPHERE_ENABLE_DEBUG_PRINT
|
#define MESOSPHERE_ENABLE_DEBUG_PRINT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MESOSPHERE_BUILD_FOR_TRACING
|
//#define MESOSPHERE_BUILD_FOR_TRACING
|
||||||
|
#define MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace ams::kern {
|
|||||||
#ifndef MESOSPHERE_DEBUG_LOG_SELECTED
|
#ifndef MESOSPHERE_DEBUG_LOG_SELECTED
|
||||||
|
|
||||||
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
|
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
|
||||||
#define MESOSPHERE_DEBUG_LOG_USE_UART_C
|
#define MESOSPHERE_DEBUG_LOG_USE_UART_A
|
||||||
#else
|
#else
|
||||||
#error "Unknown board for Default Debug Log Source"
|
#error "Unknown board for Default Debug Log Source"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace ams::kern {
|
|||||||
private:
|
private:
|
||||||
friend class KScopedSchedulerLock;
|
friend class KScopedSchedulerLock;
|
||||||
friend class KScopedSchedulerLockAndSleep;
|
friend class KScopedSchedulerLockAndSleep;
|
||||||
|
friend class KScopedDisableDispatch;
|
||||||
private:
|
private:
|
||||||
SchedulingState state;
|
SchedulingState state;
|
||||||
bool is_active;
|
bool is_active;
|
||||||
@@ -161,8 +162,9 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void ScheduleOnInterrupt() {
|
ALWAYS_INLINE void ScheduleOnInterrupt() {
|
||||||
KScopedDisableDispatch dd;
|
GetCurrentThread().DisableDispatch();
|
||||||
this->Schedule();
|
this->Schedule();
|
||||||
|
GetCurrentThread().EnableDispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RescheduleOtherCores(u64 cores_needing_scheduling);
|
void RescheduleOtherCores(u64 cores_needing_scheduling);
|
||||||
|
|||||||
@@ -559,20 +559,7 @@ namespace ams::kern {
|
|||||||
GetCurrentThread().DisableDispatch();
|
GetCurrentThread().DisableDispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE ~KScopedDisableDispatch() {
|
~KScopedDisableDispatch();
|
||||||
GetCurrentThread().EnableDispatch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class KScopedEnableDispatch {
|
|
||||||
public:
|
|
||||||
explicit ALWAYS_INLINE KScopedEnableDispatch() {
|
|
||||||
GetCurrentThread().EnableDispatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE ~KScopedEnableDispatch() {
|
|
||||||
GetCurrentThread().DisableDispatch();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ALWAYS_INLINE KExceptionContext *GetExceptionContext(KThread *thread) {
|
ALWAYS_INLINE KExceptionContext *GetExceptionContext(KThread *thread) {
|
||||||
|
|||||||
88
libraries/libmesosphere/source/arch/arm64/kern_panic_asm.s
Normal file
88
libraries/libmesosphere/source/arch/arm64/kern_panic_asm.s
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere/kern_build_config.hpp>
|
||||||
|
|
||||||
|
#if defined(MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP)
|
||||||
|
|
||||||
|
#define MESOSPHERE_GENERATE_PANIC_EXCEPTION_CONTEXT \
|
||||||
|
/* Save x0/x1 to stack. */ \
|
||||||
|
stp x0, x1, [sp, #-16]!; \
|
||||||
|
\
|
||||||
|
/* Get the exception context for the core. */ \
|
||||||
|
adr x0, _ZN3ams4kern26g_panic_exception_contextsE; \
|
||||||
|
mrs x1, mpidr_el1; \
|
||||||
|
and x1, x1, #0xFF; \
|
||||||
|
lsl x1, x1, #0x8; \
|
||||||
|
add x0, x0, x1; \
|
||||||
|
lsr x1, x1, #0x3; \
|
||||||
|
add x0, x0, x1; \
|
||||||
|
\
|
||||||
|
/* Save x0/x1/sp to the context. */ \
|
||||||
|
ldr x1, [sp, #(8 * 0)]; \
|
||||||
|
str x1, [x0, #(8 * 0)]; \
|
||||||
|
ldr x1, [sp, #(8 * 1)]; \
|
||||||
|
str x1, [x0, #(8 * 1)]; \
|
||||||
|
\
|
||||||
|
/* Save all other registers to the context. */ \
|
||||||
|
stp x2, x3, [x0, #(8 * 2)]; \
|
||||||
|
stp x4, x5, [x0, #(8 * 4)]; \
|
||||||
|
stp x6, x7, [x0, #(8 * 6)]; \
|
||||||
|
stp x8, x9, [x0, #(8 * 8)]; \
|
||||||
|
stp x10, x11, [x0, #(8 * 10)]; \
|
||||||
|
stp x12, x13, [x0, #(8 * 12)]; \
|
||||||
|
stp x14, x15, [x0, #(8 * 14)]; \
|
||||||
|
stp x16, x17, [x0, #(8 * 16)]; \
|
||||||
|
stp x18, x19, [x0, #(8 * 18)]; \
|
||||||
|
stp x20, x21, [x0, #(8 * 20)]; \
|
||||||
|
stp x22, x23, [x0, #(8 * 22)]; \
|
||||||
|
stp x24, x25, [x0, #(8 * 24)]; \
|
||||||
|
stp x26, x27, [x0, #(8 * 26)]; \
|
||||||
|
stp x28, x29, [x0, #(8 * 28)]; \
|
||||||
|
\
|
||||||
|
add x1, sp, #16; \
|
||||||
|
stp x30, x1, [x0, #(8 * 30)]; \
|
||||||
|
\
|
||||||
|
/* Restore x0/x1. */ \
|
||||||
|
ldp x0, x1, [sp], #16;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MESOSPHERE_GENERATE_PANIC_EXCEPTION_CONTEXT
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ams::kern::Panic(const char *file, int line, const char *format, ...) */
|
||||||
|
.section .text._ZN3ams4kern5PanicEPKciS2_z, "ax", %progbits
|
||||||
|
.global _ZN3ams4kern5PanicEPKciS2_z
|
||||||
|
.type _ZN3ams4kern5PanicEPKciS2_z, %function
|
||||||
|
_ZN3ams4kern5PanicEPKciS2_z:
|
||||||
|
/* Generate the exception context. */
|
||||||
|
MESOSPHERE_GENERATE_PANIC_EXCEPTION_CONTEXT
|
||||||
|
|
||||||
|
/* Jump to the architecturally-common implementation function. */
|
||||||
|
b _ZN3ams4kern9PanicImplEPKciS2_z
|
||||||
|
|
||||||
|
|
||||||
|
/* ams::kern::Panic() */
|
||||||
|
.section .text._ZN3ams4kern5PanicEv, "ax", %progbits
|
||||||
|
.global _ZN3ams4kern5PanicEv
|
||||||
|
.type _ZN3ams4kern5PanicEv, %function
|
||||||
|
_ZN3ams4kern5PanicEv:
|
||||||
|
/* Generate the exception context. */
|
||||||
|
MESOSPHERE_GENERATE_PANIC_EXCEPTION_CONTEXT
|
||||||
|
|
||||||
|
/* Jump to the architecturally-common implementation function. */
|
||||||
|
b _ZN3ams4kern9PanicImplEv
|
||||||
@@ -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 <mesosphere.hpp>
|
#include <mesosphere.hpp>
|
||||||
#include "kern_mc_registers.hpp"
|
|
||||||
|
|
||||||
#if defined(MESOSPHERE_BUILD_FOR_DEBUGGING) || defined(MESOSPHERE_BUILD_FOR_AUDITING)
|
#if defined(MESOSPHERE_BUILD_FOR_DEBUGGING) || defined(MESOSPHERE_BUILD_FOR_AUDITING)
|
||||||
#define MESOSPHERE_ENABLE_MEMORY_CONTROLLER_INTERRUPT
|
#define MESOSPHERE_ENABLE_MEMORY_CONTROLLER_INTERRUPT
|
||||||
|
|||||||
@@ -78,13 +78,11 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
|
|
||||||
void WaitOtherCpuPowerOff() {
|
void WaitOtherCpuPowerOff() {
|
||||||
constexpr u64 PmcPhysicalAddress = 0x7000E400;
|
constexpr u64 PmcPhysicalAddress = 0x7000E400;
|
||||||
constexpr u64 APBDEV_PMC_PWRGATE_STATUS = PmcPhysicalAddress + 0x38;
|
|
||||||
|
|
||||||
constexpr u32 PWRGATE_STATUS_CE123_MASK = ((1u << 3) - 1) << 9;
|
constexpr u32 PWRGATE_STATUS_CE123_MASK = ((1u << 3) - 1) << 9;
|
||||||
|
|
||||||
u32 value;
|
u32 value;
|
||||||
do {
|
do {
|
||||||
bool res = smc::ReadWriteRegister(std::addressof(value), APBDEV_PMC_PWRGATE_STATUS, 0, 0);
|
bool res = smc::ReadWriteRegister(std::addressof(value), PmcPhysicalAddress + APBDEV_PMC_PWRGATE_STATUS, 0, 0);
|
||||||
MESOSPHERE_ASSERT(res);
|
MESOSPHERE_ASSERT(res);
|
||||||
} while ((value & PWRGATE_STATUS_CE123_MASK) != 0);
|
} while ((value & PWRGATE_STATUS_CE123_MASK) != 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,6 +308,15 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
g_secure_applet_memory_used = false;
|
g_secure_applet_memory_used = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 GetVersionIdentifier() {
|
||||||
|
u64 value = kern::GetTargetFirmware();
|
||||||
|
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MICRO) << 32;
|
||||||
|
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MINOR) << 40;
|
||||||
|
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MAJOR) << 48;
|
||||||
|
value |= static_cast<u64>('M') << 56;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialization. */
|
/* Initialization. */
|
||||||
@@ -532,13 +541,90 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
KSleepManager::SleepSystem();
|
KSleepManager::SleepSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KSystemControl::StopSystem() {
|
void KSystemControl::StopSystem(void *arg) {
|
||||||
|
if (arg != nullptr) {
|
||||||
|
/* Get the address of the legacy IRAM region. */
|
||||||
|
const KVirtualAddress iram_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 64_KB;
|
||||||
|
constexpr size_t RebootPayloadSize = 0x2E000;
|
||||||
|
|
||||||
|
/* NOTE: Atmosphere extension; if we received an exception context from Panic(), */
|
||||||
|
/* generate a fatal error report using it. */
|
||||||
|
const KExceptionContext *e_ctx = static_cast<const KExceptionContext *>(arg);
|
||||||
|
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(iram_address + RebootPayloadSize);
|
||||||
|
|
||||||
|
/* Clear the fatal context. */
|
||||||
|
std::memset(f_ctx, 0xCC, sizeof(*f_ctx));
|
||||||
|
|
||||||
|
/* Set metadata. */
|
||||||
|
f_ctx->magic = ::ams::impl::FatalErrorContext::Magic;
|
||||||
|
f_ctx->error_desc = ::ams::impl::FatalErrorContext::KernelPanicDesc;
|
||||||
|
f_ctx->program_id = (static_cast<u64>(util::FourCC<'M', 'E', 'S', 'O'>::Code) << 0) | (static_cast<u64>(util::FourCC<'S', 'P', 'H', 'R'>::Code) << 32);
|
||||||
|
|
||||||
|
/* Set identifier. */
|
||||||
|
f_ctx->report_identifier = KHardwareTimer::GetTick();
|
||||||
|
|
||||||
|
/* Set module base. */
|
||||||
|
f_ctx->module_base = KMemoryLayout::GetKernelCodeRegionExtents().GetAddress();
|
||||||
|
|
||||||
|
/* Set afsr1. */
|
||||||
|
f_ctx->afsr0 = 0;
|
||||||
|
f_ctx->afsr1 = GetVersionIdentifier();
|
||||||
|
|
||||||
|
/* Copy registers. */
|
||||||
|
for (size_t i = 0; i < util::size(e_ctx->x); ++i) {
|
||||||
|
f_ctx->gprs[i] = e_ctx->x[i];
|
||||||
|
}
|
||||||
|
f_ctx->sp = e_ctx->sp;
|
||||||
|
|
||||||
|
/* Dump stack trace. */
|
||||||
|
{
|
||||||
|
uintptr_t fp = e_ctx->x[29];
|
||||||
|
for (f_ctx->stack_trace_size = 0; f_ctx->stack_trace_size < ::ams::impl::FatalErrorContext::MaxStackTrace && fp != 0 && util::IsAligned(fp, 0x10) && cpu::GetPhysicalAddressWritable(nullptr, fp, true); ++(f_ctx->stack_trace_size)) {
|
||||||
|
struct {
|
||||||
|
uintptr_t fp;
|
||||||
|
uintptr_t lr;
|
||||||
|
} *stack_frame = reinterpret_cast<decltype(stack_frame)>(fp);
|
||||||
|
|
||||||
|
f_ctx->stack_trace[f_ctx->stack_trace_size] = stack_frame->lr;
|
||||||
|
fp = stack_frame->fp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump stack. */
|
||||||
|
{
|
||||||
|
uintptr_t sp = e_ctx->sp;
|
||||||
|
for (f_ctx->stack_dump_size = 0; f_ctx->stack_dump_size < ::ams::impl::FatalErrorContext::MaxStackDumpSize && cpu::GetPhysicalAddressWritable(nullptr, sp + f_ctx->stack_dump_size, true); f_ctx->stack_dump_size += sizeof(u64)) {
|
||||||
|
*reinterpret_cast<u64 *>(f_ctx->stack_dump + f_ctx->stack_dump_size) = *reinterpret_cast<u64 *>(sp + f_ctx->stack_dump_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get a payload address. */
|
||||||
|
const KMemoryRegion *cached_region = nullptr;
|
||||||
|
u64 reboot_payload_paddr = 0;
|
||||||
|
if (smc::TryGetConfig(std::addressof(reboot_payload_paddr), 1, smc::ConfigItem::ExospherePayloadAddress) && KMemoryLayout::IsLinearMappedPhysicalAddress(cached_region, reboot_payload_paddr, RebootPayloadSize)) {
|
||||||
|
/* If we have a payload, reboot to it. */
|
||||||
|
const KVirtualAddress reboot_payload = KMemoryLayout::GetLinearVirtualAddress(KPhysicalAddress(reboot_payload_paddr));
|
||||||
|
|
||||||
|
/* Clear IRAM. */
|
||||||
|
std::memset(GetVoidPointer(iram_address), 0xCC, RebootPayloadSize);
|
||||||
|
|
||||||
|
/* Copy the payload to iram. */
|
||||||
|
for (size_t i = 0; i < RebootPayloadSize / sizeof(u32); ++i) {
|
||||||
|
GetPointer<volatile u32>(iram_address)[i] = GetPointer<volatile u32>(reboot_payload)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reboot. */
|
||||||
|
smc::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToPayload);
|
||||||
|
} else {
|
||||||
|
/* If we don't have a payload, reboot to rcm. */
|
||||||
|
smc::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToRcm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_call_smc_on_panic) {
|
if (g_call_smc_on_panic) {
|
||||||
/* Display a panic screen via secure monitor. */
|
/* If we should, instruct the secure monitor to display a panic screen. */
|
||||||
smc::Panic(0xF00);
|
smc::Panic(0xF00);
|
||||||
}
|
}
|
||||||
u32 dummy;
|
|
||||||
smc::init::ReadWriteRegister(std::addressof(dummy), 0x7000E400, 0x10, 0x10);
|
|
||||||
AMS_INFINITE_LOOP();
|
AMS_INFINITE_LOOP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,7 @@
|
|||||||
|
|
||||||
#include "kern_bpmp_api.hpp"
|
#include "kern_bpmp_api.hpp"
|
||||||
#include "kern_atomics_registers.hpp"
|
#include "kern_atomics_registers.hpp"
|
||||||
#include "kern_clkrst_registers.hpp"
|
|
||||||
#include "kern_evp_registers.hpp"
|
|
||||||
#include "kern_flow_registers.hpp"
|
|
||||||
#include "kern_ictlr_registers.hpp"
|
#include "kern_ictlr_registers.hpp"
|
||||||
#include "kern_pmc_registers.hpp"
|
|
||||||
#include "kern_sema_registers.hpp"
|
#include "kern_sema_registers.hpp"
|
||||||
|
|
||||||
namespace ams::kern::board::nintendo::nx::lps {
|
namespace ams::kern::board::nintendo::nx::lps {
|
||||||
|
|||||||
@@ -1,526 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define MC_INTSTATUS 0x0
|
|
||||||
#define MC_INTMASK 0x4
|
|
||||||
#define MC_ERR_STATUS 0x8
|
|
||||||
#define MC_ERR_ADR 0xc
|
|
||||||
#define MC_SMMU_CONFIG 0x10
|
|
||||||
#define MC_SMMU_TLB_CONFIG 0x14
|
|
||||||
#define MC_SMMU_PTC_CONFIG 0x18
|
|
||||||
#define MC_SMMU_PTB_ASID 0x1c
|
|
||||||
#define MC_SMMU_PTB_DATA 0x20
|
|
||||||
#define MC_SMMU_TLB_FLUSH 0x30
|
|
||||||
#define MC_SMMU_PTC_FLUSH_0 0x34
|
|
||||||
#define MC_SMMU_PTC_FLUSH_1 0x9b8
|
|
||||||
#define MC_SMMU_ASID_SECURITY 0x38
|
|
||||||
#define MC_SMMU_ASID_SECURITY_1 0x3c
|
|
||||||
#define MC_SMMU_ASID_SECURITY_2 0x9e0
|
|
||||||
#define MC_SMMU_ASID_SECURITY_3 0x9e4
|
|
||||||
#define MC_SMMU_ASID_SECURITY_4 0x9e8
|
|
||||||
#define MC_SMMU_ASID_SECURITY_5 0x9ec
|
|
||||||
#define MC_SMMU_ASID_SECURITY_6 0x9f0
|
|
||||||
#define MC_SMMU_ASID_SECURITY_7 0x9f4
|
|
||||||
#define MC_SMMU_AFI_ASID 0x238
|
|
||||||
#define MC_SMMU_AVPC_ASID 0x23c
|
|
||||||
#define MC_SMMU_DC_ASID 0x240
|
|
||||||
#define MC_SMMU_DCB_ASID 0x244
|
|
||||||
#define MC_SMMU_HC_ASID 0x250
|
|
||||||
#define MC_SMMU_HDA_ASID 0x254
|
|
||||||
#define MC_SMMU_ISP2_ASID 0x258
|
|
||||||
#define MC_SMMU_MSENC_NVENC_ASID 0x264
|
|
||||||
#define MC_SMMU_NV_ASID 0x268
|
|
||||||
#define MC_SMMU_NV2_ASID 0x26c
|
|
||||||
#define MC_SMMU_PPCS_ASID 0x270
|
|
||||||
#define MC_SMMU_SATA_ASID 0x274
|
|
||||||
#define MC_SMMU_VDE_ASID 0x27c
|
|
||||||
#define MC_SMMU_VI_ASID 0x280
|
|
||||||
#define MC_SMMU_VIC_ASID 0x284
|
|
||||||
#define MC_SMMU_XUSB_HOST_ASID 0x288
|
|
||||||
#define MC_SMMU_XUSB_DEV_ASID 0x28c
|
|
||||||
#define MC_SMMU_TSEC_ASID 0x294
|
|
||||||
#define MC_SMMU_PPCS1_ASID 0x298
|
|
||||||
#define MC_SMMU_DC1_ASID 0xa88
|
|
||||||
#define MC_SMMU_SDMMC1A_ASID 0xa94
|
|
||||||
#define MC_SMMU_SDMMC2A_ASID 0xa98
|
|
||||||
#define MC_SMMU_SDMMC3A_ASID 0xa9c
|
|
||||||
#define MC_SMMU_SDMMC4A_ASID 0xaa0
|
|
||||||
#define MC_SMMU_ISP2B_ASID 0xaa4
|
|
||||||
#define MC_SMMU_GPU_ASID 0xaa8
|
|
||||||
#define MC_SMMU_GPUB_ASID 0xaac
|
|
||||||
#define MC_SMMU_PPCS2_ASID 0xab0
|
|
||||||
#define MC_SMMU_NVDEC_ASID 0xab4
|
|
||||||
#define MC_SMMU_APE_ASID 0xab8
|
|
||||||
#define MC_SMMU_SE_ASID 0xabc
|
|
||||||
#define MC_SMMU_NVJPG_ASID 0xac0
|
|
||||||
#define MC_SMMU_HC1_ASID 0xac4
|
|
||||||
#define MC_SMMU_SE1_ASID 0xac8
|
|
||||||
#define MC_SMMU_AXIAP_ASID 0xacc
|
|
||||||
#define MC_SMMU_ETR_ASID 0xad0
|
|
||||||
#define MC_SMMU_TSECB_ASID 0xad4
|
|
||||||
#define MC_SMMU_TSEC1_ASID 0xad8
|
|
||||||
#define MC_SMMU_TSECB1_ASID 0xadc
|
|
||||||
#define MC_SMMU_NVDEC1_ASID 0xae0
|
|
||||||
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
|
|
||||||
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
|
|
||||||
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
|
|
||||||
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
|
|
||||||
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
|
|
||||||
#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0
|
|
||||||
#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4
|
|
||||||
#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8
|
|
||||||
#define MC_PCFIFO_CLIENT_CONFIG3 0xddc
|
|
||||||
#define MC_PCFIFO_CLIENT_CONFIG4 0xde0
|
|
||||||
#define MC_EMEM_CFG 0x50
|
|
||||||
#define MC_EMEM_ADR_CFG 0x54
|
|
||||||
#define MC_EMEM_ADR_CFG_DEV0 0x58
|
|
||||||
#define MC_EMEM_ADR_CFG_DEV1 0x5c
|
|
||||||
#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60
|
|
||||||
#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64
|
|
||||||
#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68
|
|
||||||
#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c
|
|
||||||
#define MC_SECURITY_CFG0 0x70
|
|
||||||
#define MC_SECURITY_CFG1 0x74
|
|
||||||
#define MC_SECURITY_CFG3 0x9bc
|
|
||||||
#define MC_SECURITY_RSV 0x7c
|
|
||||||
#define MC_EMEM_ARB_CFG 0x90
|
|
||||||
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
|
|
||||||
#define MC_EMEM_ARB_TIMING_RCD 0x98
|
|
||||||
#define MC_EMEM_ARB_TIMING_RP 0x9c
|
|
||||||
#define MC_EMEM_ARB_TIMING_RC 0xa0
|
|
||||||
#define MC_EMEM_ARB_TIMING_RAS 0xa4
|
|
||||||
#define MC_EMEM_ARB_TIMING_FAW 0xa8
|
|
||||||
#define MC_EMEM_ARB_TIMING_RRD 0xac
|
|
||||||
#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
|
|
||||||
#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
|
|
||||||
#define MC_EMEM_ARB_TIMING_R2R 0xb8
|
|
||||||
#define MC_EMEM_ARB_TIMING_W2W 0xbc
|
|
||||||
#define MC_EMEM_ARB_TIMING_R2W 0xc0
|
|
||||||
#define MC_EMEM_ARB_TIMING_W2R 0xc4
|
|
||||||
#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
|
|
||||||
#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
|
|
||||||
#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
|
|
||||||
#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
|
|
||||||
#define MC_EMEM_ARB_DA_TURNS 0xd0
|
|
||||||
#define MC_EMEM_ARB_DA_COVERS 0xd4
|
|
||||||
#define MC_EMEM_ARB_MISC0 0xd8
|
|
||||||
#define MC_EMEM_ARB_MISC1 0xdc
|
|
||||||
#define MC_EMEM_ARB_MISC2 0xc8
|
|
||||||
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
|
|
||||||
#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
|
|
||||||
#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0
|
|
||||||
#define MC_EMEM_ARB_OVERRIDE 0xe8
|
|
||||||
#define MC_EMEM_ARB_RSV 0xec
|
|
||||||
#define MC_CLKEN_OVERRIDE 0xf4
|
|
||||||
#define MC_TIMING_CONTROL_DBG 0xf8
|
|
||||||
#define MC_TIMING_CONTROL 0xfc
|
|
||||||
#define MC_STAT_CONTROL 0x100
|
|
||||||
#define MC_STAT_STATUS 0x104
|
|
||||||
#define MC_STAT_EMC_CLOCK_LIMIT 0x108
|
|
||||||
#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c
|
|
||||||
#define MC_STAT_EMC_CLOCKS 0x110
|
|
||||||
#define MC_STAT_EMC_CLOCKS_MSBS 0x114
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134
|
|
||||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174
|
|
||||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c
|
|
||||||
#define MC_STAT_EMC_SET0_COUNT 0x138
|
|
||||||
#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c
|
|
||||||
#define MC_STAT_EMC_SET1_COUNT 0x178
|
|
||||||
#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c
|
|
||||||
#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140
|
|
||||||
#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144
|
|
||||||
#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180
|
|
||||||
#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184
|
|
||||||
#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148
|
|
||||||
#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c
|
|
||||||
#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188
|
|
||||||
#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c
|
|
||||||
#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150
|
|
||||||
#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190
|
|
||||||
#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8
|
|
||||||
#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc
|
|
||||||
#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8
|
|
||||||
#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc
|
|
||||||
#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0
|
|
||||||
#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0
|
|
||||||
#define MC_CLIENT_HOTRESET_CTRL 0x200
|
|
||||||
#define MC_CLIENT_HOTRESET_CTRL_1 0x970
|
|
||||||
#define MC_CLIENT_HOTRESET_STATUS 0x204
|
|
||||||
#define MC_CLIENT_HOTRESET_STATUS_1 0x974
|
|
||||||
#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208
|
|
||||||
#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c
|
|
||||||
#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210
|
|
||||||
#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214
|
|
||||||
#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94
|
|
||||||
#define MC_EMEM_ARB_HYSTERESIS_0 0x218
|
|
||||||
#define MC_EMEM_ARB_HYSTERESIS_1 0x21c
|
|
||||||
#define MC_EMEM_ARB_HYSTERESIS_2 0x220
|
|
||||||
#define MC_EMEM_ARB_HYSTERESIS_3 0x224
|
|
||||||
#define MC_EMEM_ARB_HYSTERESIS_4 0xb84
|
|
||||||
#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0
|
|
||||||
#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4
|
|
||||||
#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8
|
|
||||||
#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc
|
|
||||||
#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0
|
|
||||||
#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
|
|
||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
|
|
||||||
#define MC_RESERVED_RSV 0x3fc
|
|
||||||
#define MC_DISB_EXTRA_SNAP_LEVELS 0x408
|
|
||||||
#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4
|
|
||||||
#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0
|
|
||||||
#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18
|
|
||||||
#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08
|
|
||||||
#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10
|
|
||||||
#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c
|
|
||||||
#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40
|
|
||||||
#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414
|
|
||||||
#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc
|
|
||||||
#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c
|
|
||||||
#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14
|
|
||||||
#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0
|
|
||||||
#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac
|
|
||||||
#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c
|
|
||||||
#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48
|
|
||||||
#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8
|
|
||||||
#define MC_USBX_EXTRA_SNAP_LEVELS 0x404
|
|
||||||
#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8
|
|
||||||
#define MC_SD_EXTRA_SNAP_LEVELS 0xa04
|
|
||||||
#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c
|
|
||||||
#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8
|
|
||||||
#define MC_GK_EXTRA_SNAP_LEVELS 0xa00
|
|
||||||
#define MC_VE2_EXTRA_SNAP_LEVELS 0x410
|
|
||||||
#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44
|
|
||||||
#define MC_VIDEO_PROTECT_BOM 0x648
|
|
||||||
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
|
|
||||||
#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978
|
|
||||||
#define MC_VIDEO_PROTECT_REG_CTRL 0x650
|
|
||||||
#define MC_ERR_VPR_STATUS 0x654
|
|
||||||
#define MC_ERR_VPR_ADR 0x658
|
|
||||||
#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418
|
|
||||||
#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590
|
|
||||||
#define MC_IRAM_BOM 0x65c
|
|
||||||
#define MC_IRAM_TOM 0x660
|
|
||||||
#define MC_IRAM_ADR_HI 0x980
|
|
||||||
#define MC_IRAM_REG_CTRL 0x964
|
|
||||||
#define MC_EMEM_CFG_ACCESS_CTRL 0x664
|
|
||||||
#define MC_TZ_SECURITY_CTRL 0x668
|
|
||||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c
|
|
||||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4
|
|
||||||
#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc
|
|
||||||
#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8
|
|
||||||
#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80
|
|
||||||
#define MC_SEC_CARVEOUT_BOM 0x670
|
|
||||||
#define MC_SEC_CARVEOUT_SIZE_MB 0x674
|
|
||||||
#define MC_SEC_CARVEOUT_ADR_HI 0x9d4
|
|
||||||
#define MC_SEC_CARVEOUT_REG_CTRL 0x678
|
|
||||||
#define MC_ERR_SEC_STATUS 0x67c
|
|
||||||
#define MC_ERR_SEC_ADR 0x680
|
|
||||||
#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684
|
|
||||||
#define MC_STUTTER_CONTROL 0x688
|
|
||||||
#define MC_RESERVED_RSV_1 0x958
|
|
||||||
#define MC_DVFS_PIPE_SELECT 0x95c
|
|
||||||
#define MC_AHB_PTSA_MIN 0x4e0
|
|
||||||
#define MC_AUD_PTSA_MIN 0x54c
|
|
||||||
#define MC_MLL_MPCORER_PTSA_RATE 0x44c
|
|
||||||
#define MC_RING2_PTSA_RATE 0x440
|
|
||||||
#define MC_USBD_PTSA_RATE 0x530
|
|
||||||
#define MC_USBX_PTSA_MIN 0x528
|
|
||||||
#define MC_USBD_PTSA_MIN 0x534
|
|
||||||
#define MC_APB_PTSA_MAX 0x4f0
|
|
||||||
#define MC_JPG_PTSA_RATE 0x584
|
|
||||||
#define MC_DIS_PTSA_MIN 0x420
|
|
||||||
#define MC_AVP_PTSA_MAX 0x4fc
|
|
||||||
#define MC_AVP_PTSA_RATE 0x4f4
|
|
||||||
#define MC_RING1_PTSA_MIN 0x480
|
|
||||||
#define MC_DIS_PTSA_MAX 0x424
|
|
||||||
#define MC_SD_PTSA_MAX 0x4d8
|
|
||||||
#define MC_MSE_PTSA_RATE 0x4c4
|
|
||||||
#define MC_VICPC_PTSA_MIN 0x558
|
|
||||||
#define MC_PCX_PTSA_MAX 0x4b4
|
|
||||||
#define MC_ISP_PTSA_RATE 0x4a0
|
|
||||||
#define MC_A9AVPPC_PTSA_MIN 0x48c
|
|
||||||
#define MC_RING2_PTSA_MAX 0x448
|
|
||||||
#define MC_AUD_PTSA_RATE 0x548
|
|
||||||
#define MC_HOST_PTSA_MIN 0x51c
|
|
||||||
#define MC_MLL_MPCORER_PTSA_MAX 0x454
|
|
||||||
#define MC_SD_PTSA_MIN 0x4d4
|
|
||||||
#define MC_RING1_PTSA_RATE 0x47c
|
|
||||||
#define MC_JPG_PTSA_MIN 0x588
|
|
||||||
#define MC_HDAPC_PTSA_MIN 0x62c
|
|
||||||
#define MC_AVP_PTSA_MIN 0x4f8
|
|
||||||
#define MC_JPG_PTSA_MAX 0x58c
|
|
||||||
#define MC_VE_PTSA_MAX 0x43c
|
|
||||||
#define MC_DFD_PTSA_MAX 0x63c
|
|
||||||
#define MC_VICPC_PTSA_RATE 0x554
|
|
||||||
#define MC_GK_PTSA_MAX 0x544
|
|
||||||
#define MC_VICPC_PTSA_MAX 0x55c
|
|
||||||
#define MC_SDM_PTSA_MAX 0x624
|
|
||||||
#define MC_SAX_PTSA_RATE 0x4b8
|
|
||||||
#define MC_PCX_PTSA_MIN 0x4b0
|
|
||||||
#define MC_APB_PTSA_MIN 0x4ec
|
|
||||||
#define MC_GK2_PTSA_MIN 0x614
|
|
||||||
#define MC_PCX_PTSA_RATE 0x4ac
|
|
||||||
#define MC_RING1_PTSA_MAX 0x484
|
|
||||||
#define MC_HDAPC_PTSA_RATE 0x628
|
|
||||||
#define MC_MLL_MPCORER_PTSA_MIN 0x450
|
|
||||||
#define MC_GK2_PTSA_MAX 0x618
|
|
||||||
#define MC_AUD_PTSA_MAX 0x550
|
|
||||||
#define MC_GK2_PTSA_RATE 0x610
|
|
||||||
#define MC_ISP_PTSA_MAX 0x4a8
|
|
||||||
#define MC_DISB_PTSA_RATE 0x428
|
|
||||||
#define MC_VE2_PTSA_MAX 0x49c
|
|
||||||
#define MC_DFD_PTSA_MIN 0x638
|
|
||||||
#define MC_FTOP_PTSA_RATE 0x50c
|
|
||||||
#define MC_A9AVPPC_PTSA_RATE 0x488
|
|
||||||
#define MC_VE2_PTSA_MIN 0x498
|
|
||||||
#define MC_USBX_PTSA_MAX 0x52c
|
|
||||||
#define MC_DIS_PTSA_RATE 0x41c
|
|
||||||
#define MC_USBD_PTSA_MAX 0x538
|
|
||||||
#define MC_A9AVPPC_PTSA_MAX 0x490
|
|
||||||
#define MC_USBX_PTSA_RATE 0x524
|
|
||||||
#define MC_FTOP_PTSA_MAX 0x514
|
|
||||||
#define MC_HDAPC_PTSA_MAX 0x630
|
|
||||||
#define MC_SD_PTSA_RATE 0x4d0
|
|
||||||
#define MC_DFD_PTSA_RATE 0x634
|
|
||||||
#define MC_FTOP_PTSA_MIN 0x510
|
|
||||||
#define MC_SDM_PTSA_RATE 0x61c
|
|
||||||
#define MC_AHB_PTSA_RATE 0x4dc
|
|
||||||
#define MC_SMMU_SMMU_PTSA_MAX 0x460
|
|
||||||
#define MC_RING2_PTSA_MIN 0x444
|
|
||||||
#define MC_SDM_PTSA_MIN 0x620
|
|
||||||
#define MC_APB_PTSA_RATE 0x4e8
|
|
||||||
#define MC_MSE_PTSA_MIN 0x4c8
|
|
||||||
#define MC_HOST_PTSA_RATE 0x518
|
|
||||||
#define MC_VE_PTSA_RATE 0x434
|
|
||||||
#define MC_AHB_PTSA_MAX 0x4e4
|
|
||||||
#define MC_SAX_PTSA_MIN 0x4bc
|
|
||||||
#define MC_SMMU_SMMU_PTSA_MIN 0x45c
|
|
||||||
#define MC_ISP_PTSA_MIN 0x4a4
|
|
||||||
#define MC_HOST_PTSA_MAX 0x520
|
|
||||||
#define MC_SAX_PTSA_MAX 0x4c0
|
|
||||||
#define MC_VE_PTSA_MIN 0x438
|
|
||||||
#define MC_GK_PTSA_MIN 0x540
|
|
||||||
#define MC_MSE_PTSA_MAX 0x4cc
|
|
||||||
#define MC_DISB_PTSA_MAX 0x430
|
|
||||||
#define MC_DISB_PTSA_MIN 0x42c
|
|
||||||
#define MC_SMMU_SMMU_PTSA_RATE 0x458
|
|
||||||
#define MC_VE2_PTSA_RATE 0x494
|
|
||||||
#define MC_GK_PTSA_RATE 0x53c
|
|
||||||
#define MC_PTSA_GRANT_DECREMENT 0x960
|
|
||||||
#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
|
|
||||||
#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0
|
|
||||||
#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
|
|
||||||
#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384
|
|
||||||
#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
|
|
||||||
#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
|
|
||||||
#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
|
|
||||||
#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0
|
|
||||||
#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
|
|
||||||
#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8
|
|
||||||
#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
|
|
||||||
#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8
|
|
||||||
#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
|
|
||||||
#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc
|
|
||||||
#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
|
|
||||||
#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0
|
|
||||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694
|
|
||||||
#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
|
|
||||||
#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
|
|
||||||
#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
|
|
||||||
#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0
|
|
||||||
#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0
|
|
||||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698
|
|
||||||
#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec
|
|
||||||
#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc
|
|
||||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0
|
|
||||||
#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4
|
|
||||||
#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
|
|
||||||
#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4
|
|
||||||
#define MC_LATENCY_ALLOWANCE_HC_1 0x314
|
|
||||||
#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
|
|
||||||
#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4
|
|
||||||
#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c
|
|
||||||
#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec
|
|
||||||
#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
|
|
||||||
#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
|
|
||||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c
|
|
||||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4
|
|
||||||
#define MC_LATENCY_ALLOWANCE_SATA_0 0x350
|
|
||||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690
|
|
||||||
#define MC_LATENCY_ALLOWANCE_HC_0 0x310
|
|
||||||
#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8
|
|
||||||
#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
|
|
||||||
#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
|
|
||||||
#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388
|
|
||||||
#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
|
|
||||||
#define MC_LATENCY_ALLOWANCE_HDA_0 0x318
|
|
||||||
#define MC_MIN_LENGTH_APE_0 0xb34
|
|
||||||
#define MC_MIN_LENGTH_DCB_2 0x8a8
|
|
||||||
#define MC_MIN_LENGTH_A9AVP_0 0x950
|
|
||||||
#define MC_MIN_LENGTH_TSEC_0 0x93c
|
|
||||||
#define MC_MIN_LENGTH_DC_1 0x898
|
|
||||||
#define MC_MIN_LENGTH_AXIAP_0 0x94c
|
|
||||||
#define MC_MIN_LENGTH_ISP2B_0 0x930
|
|
||||||
#define MC_MIN_LENGTH_VI2_0 0x944
|
|
||||||
#define MC_MIN_LENGTH_DCB_0 0x8a0
|
|
||||||
#define MC_MIN_LENGTH_DCB_1 0x8a4
|
|
||||||
#define MC_MIN_LENGTH_PPCS_1 0x8f4
|
|
||||||
#define MC_MIN_LENGTH_NVJPG_0 0xb3c
|
|
||||||
#define MC_MIN_LENGTH_HDA_0 0x8c4
|
|
||||||
#define MC_MIN_LENGTH_NVENC_0 0x8d4
|
|
||||||
#define MC_MIN_LENGTH_SDMMC_0 0xb18
|
|
||||||
#define MC_MIN_LENGTH_ISP2B_1 0x934
|
|
||||||
#define MC_MIN_LENGTH_HC_1 0x8c0
|
|
||||||
#define MC_MIN_LENGTH_DC_3 0xb20
|
|
||||||
#define MC_MIN_LENGTH_AVPC_0 0x890
|
|
||||||
#define MC_MIN_LENGTH_VIC_0 0x940
|
|
||||||
#define MC_MIN_LENGTH_ISP2_0 0x91c
|
|
||||||
#define MC_MIN_LENGTH_HC_0 0x8bc
|
|
||||||
#define MC_MIN_LENGTH_SE_0 0xb38
|
|
||||||
#define MC_MIN_LENGTH_NVDEC_0 0xb30
|
|
||||||
#define MC_MIN_LENGTH_SATA_0 0x8fc
|
|
||||||
#define MC_MIN_LENGTH_DC_0 0x894
|
|
||||||
#define MC_MIN_LENGTH_XUSB_1 0x92c
|
|
||||||
#define MC_MIN_LENGTH_DC_2 0x89c
|
|
||||||
#define MC_MIN_LENGTH_SDMMCAA_0 0xb14
|
|
||||||
#define MC_MIN_LENGTH_GPU_0 0xb04
|
|
||||||
#define MC_MIN_LENGTH_ETR_0 0xb44
|
|
||||||
#define MC_MIN_LENGTH_AFI_0 0x88c
|
|
||||||
#define MC_MIN_LENGTH_PPCS_0 0x8f0
|
|
||||||
#define MC_MIN_LENGTH_ISP2_1 0x920
|
|
||||||
#define MC_MIN_LENGTH_XUSB_0 0x928
|
|
||||||
#define MC_MIN_LENGTH_MPCORE_0 0x8cc
|
|
||||||
#define MC_MIN_LENGTH_TSECB_0 0xb48
|
|
||||||
#define MC_MIN_LENGTH_SDMMCA_0 0xb10
|
|
||||||
#define MC_MIN_LENGTH_GPU2_0 0xb40
|
|
||||||
#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c
|
|
||||||
#define MC_MIN_LENGTH_PTC_0 0x8f8
|
|
||||||
#define MC_EMEM_ARB_OVERRIDE_1 0x968
|
|
||||||
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984
|
|
||||||
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988
|
|
||||||
#define MC_EMEM_ARB_STATS_0 0x990
|
|
||||||
#define MC_EMEM_ARB_STATS_1 0x994
|
|
||||||
#define MC_MTS_CARVEOUT_BOM 0x9a0
|
|
||||||
#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4
|
|
||||||
#define MC_MTS_CARVEOUT_ADR_HI 0x9a8
|
|
||||||
#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac
|
|
||||||
#define MC_ERR_MTS_STATUS 0x9b0
|
|
||||||
#define MC_ERR_MTS_ADR 0x9b4
|
|
||||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
|
|
||||||
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10
|
|
||||||
#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c
|
|
||||||
#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CFG0 0xc58
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CFG0 0xc08
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68
|
|
||||||
#define MC_SECURITY_CARVEOUT3_BOM 0xcac
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CFG0 0xca8
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88
|
|
||||||
#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64
|
|
||||||
#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50
|
|
||||||
#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14
|
|
||||||
#define MC_SECURITY_CARVEOUT1_BOM 0xc0c
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c
|
|
||||||
#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8
|
|
||||||
#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60
|
|
||||||
#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80
|
|
||||||
#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc
|
|
||||||
#define MC_SECURITY_CARVEOUT4_BOM 0xcfc
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CFG0 0xd48
|
|
||||||
#define MC_SECURITY_CARVEOUT2_BOM 0xc5c
|
|
||||||
#define MC_SECURITY_CARVEOUT5_BOM 0xd4c
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24
|
|
||||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c
|
|
||||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0
|
|
||||||
#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20
|
|
||||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c
|
|
||||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
|
|
||||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
|
|
||||||
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
|
|
||||||
#define MC_DA_CONFIG0 0x9dc
|
|
||||||
@@ -24,6 +24,10 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
u64 x[8];
|
u64 x[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum UserFunctionId : u32 {
|
||||||
|
UserFunctionId_SetConfig = 0xC3000401,
|
||||||
|
};
|
||||||
|
|
||||||
enum FunctionId : u32 {
|
enum FunctionId : u32 {
|
||||||
FunctionId_CpuSuspend = 0xC4000001,
|
FunctionId_CpuSuspend = 0xC4000001,
|
||||||
FunctionId_CpuOff = 0x84000002,
|
FunctionId_CpuOff = 0x84000002,
|
||||||
@@ -33,6 +37,9 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
FunctionId_Panic = 0xC3000006,
|
FunctionId_Panic = 0xC3000006,
|
||||||
FunctionId_ConfigureCarveout = 0xC3000007,
|
FunctionId_ConfigureCarveout = 0xC3000007,
|
||||||
FunctionId_ReadWriteRegister = 0xC3000008,
|
FunctionId_ReadWriteRegister = 0xC3000008,
|
||||||
|
|
||||||
|
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
|
||||||
|
FunctionId_SetConfig = 0xC3000409,
|
||||||
};
|
};
|
||||||
|
|
||||||
void CallPrivilegedSecureMonitorFunction(SecureMonitorArguments &args) {
|
void CallPrivilegedSecureMonitorFunction(SecureMonitorArguments &args) {
|
||||||
@@ -179,13 +186,28 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
bool TryGetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||||
SecureMonitorArguments args = { FunctionId_GetConfig, static_cast<u32>(config_item) };
|
SecureMonitorArguments args = { FunctionId_GetConfig, static_cast<u32>(config_item) };
|
||||||
CallPrivilegedSecureMonitorFunction(args);
|
CallPrivilegedSecureMonitorFunction(args);
|
||||||
MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success));
|
if (static_cast<SmcResult>(args.x[0]) != SmcResult::Success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < num_qwords && i < 7; i++) {
|
for (size_t i = 0; i < num_qwords && i < 7; i++) {
|
||||||
out[i] = args.x[1 + i];
|
out[i] = args.x[1 + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||||
|
MESOSPHERE_ABORT_UNLESS(TryGetConfig(out, num_qwords, config_item));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetConfig(ConfigItem config_item, u64 value) {
|
||||||
|
SecureMonitorArguments args = { FunctionId_SetConfig, static_cast<u32>(config_item), 0, value };
|
||||||
|
CallPrivilegedSecureMonitorFunction(args);
|
||||||
|
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value) {
|
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value) {
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
ExosphereNeedsShutdown = 65002,
|
ExosphereNeedsShutdown = 65002,
|
||||||
ExosphereGitCommitHash = 65003,
|
ExosphereGitCommitHash = 65003,
|
||||||
ExosphereHasRcmBugPatch = 65004,
|
ExosphereHasRcmBugPatch = 65004,
|
||||||
|
ExosphereBlankProdInfo = 65005,
|
||||||
|
ExosphereAllowCalWrites = 65006,
|
||||||
|
ExosphereEmummcType = 65007,
|
||||||
|
ExospherePayloadAddress = 65008,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SmcResult {
|
enum class SmcResult {
|
||||||
@@ -83,12 +87,20 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
using MemorySize = util::BitPack32::Field<Reserved9::Next, 2, smc::MemorySize>;
|
using MemorySize = util::BitPack32::Field<Reserved9::Next, 2, smc::MemorySize>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO: Rest of Secure Monitor API. */
|
enum UserRebootType {
|
||||||
|
UserRebootType_None = 0,
|
||||||
|
UserRebootType_ToRcm = 1,
|
||||||
|
UserRebootType_ToPayload = 2,
|
||||||
|
};
|
||||||
|
|
||||||
void GenerateRandomBytes(void *dst, size_t size);
|
void GenerateRandomBytes(void *dst, size_t size);
|
||||||
|
bool TryGetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
||||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
||||||
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
||||||
void ConfigureCarveout(size_t which, uintptr_t address, size_t size);
|
void ConfigureCarveout(size_t which, uintptr_t address, size_t size);
|
||||||
|
|
||||||
|
bool SetConfig(ConfigItem config_item, u64 value);
|
||||||
|
|
||||||
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
|
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
|
||||||
|
|
||||||
void NORETURN Panic(u32 color);
|
void NORETURN Panic(u32 color);
|
||||||
|
|||||||
@@ -17,386 +17,9 @@
|
|||||||
#include "kern_debug_log_impl.hpp"
|
#include "kern_debug_log_impl.hpp"
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
#pragma GCC push_options
|
|
||||||
#pragma GCC optimize ("-Os")
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* Useful definitions for our VSNPrintf implementation. */
|
|
||||||
enum FormatSpecifierFlag : u32 {
|
|
||||||
FormatSpecifierFlag_None = 0,
|
|
||||||
FormatSpecifierFlag_EmptySign = (1 << 0),
|
|
||||||
FormatSpecifierFlag_ForceSign = (1 << 1),
|
|
||||||
FormatSpecifierFlag_Hash = (1 << 2),
|
|
||||||
FormatSpecifierFlag_LeftJustify = (1 << 3),
|
|
||||||
FormatSpecifierFlag_ZeroPad = (1 << 4),
|
|
||||||
FormatSpecifierFlag_Char = (1 << 5),
|
|
||||||
FormatSpecifierFlag_Short = (1 << 6),
|
|
||||||
FormatSpecifierFlag_Long = (1 << 7),
|
|
||||||
FormatSpecifierFlag_LongLong = (1 << 8),
|
|
||||||
FormatSpecifierFlag_Uppercase = (1 << 9),
|
|
||||||
FormatSpecifierFlag_HasPrecision = (1 << 10),
|
|
||||||
};
|
|
||||||
|
|
||||||
using FormatSpecifierFlagStorage = std::underlying_type<FormatSpecifierFlag>::type;
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsDigit(char c) {
|
|
||||||
return '0' <= c && c <= '9';
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u32 ParseU32(const char *&str) {
|
|
||||||
u32 value = 0;
|
|
||||||
do {
|
|
||||||
value = (value * 10) + static_cast<u32>(*(str++) - '0');
|
|
||||||
} while (IsDigit(*str));
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE size_t Strnlen(const char *str, size_t max) {
|
|
||||||
const char *cur = str;
|
|
||||||
while (*cur && max--) {
|
|
||||||
cur++;
|
|
||||||
}
|
|
||||||
return static_cast<size_t>(cur - str);
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE void VSNPrintfImpl(char * const dst, const size_t dst_size, const char *format, ::std::va_list vl) {
|
|
||||||
size_t dst_index = 0;
|
|
||||||
|
|
||||||
auto WriteCharacter = [dst, dst_size, &dst_index](char c) ALWAYS_INLINE_LAMBDA {
|
|
||||||
if (dst_index < dst_size) {
|
|
||||||
dst[dst_index++] = c;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Loop over every character in the string, looking for format specifiers. */
|
|
||||||
while (*format) {
|
|
||||||
if (const char c = *(format++); c != '%') {
|
|
||||||
WriteCharacter(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have to parse a format specifier. */
|
|
||||||
/* Start by parsing flags. */
|
|
||||||
FormatSpecifierFlagStorage flags = FormatSpecifierFlag_None;
|
|
||||||
auto SetFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { flags |= f; };
|
|
||||||
auto ClearFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { flags &= ~f; };
|
|
||||||
auto HasFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { return (flags & f) != 0; };
|
|
||||||
{
|
|
||||||
bool parsed_flags = false;
|
|
||||||
while (!parsed_flags) {
|
|
||||||
switch (*format) {
|
|
||||||
case ' ': SetFlag(FormatSpecifierFlag_EmptySign); format++; break;
|
|
||||||
case '+': SetFlag(FormatSpecifierFlag_ForceSign); format++; break;
|
|
||||||
case '#': SetFlag(FormatSpecifierFlag_Hash); format++; break;
|
|
||||||
case '-': SetFlag(FormatSpecifierFlag_LeftJustify); format++; break;
|
|
||||||
case '0': SetFlag(FormatSpecifierFlag_ZeroPad); format++; break;
|
|
||||||
default:
|
|
||||||
parsed_flags = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next, parse width. */
|
|
||||||
u32 width = 0;
|
|
||||||
if (IsDigit(*format)) {
|
|
||||||
/* Integer width. */
|
|
||||||
width = ParseU32(format);
|
|
||||||
} else if (*format == '*') {
|
|
||||||
/* Dynamic width. */
|
|
||||||
const int _width = va_arg(vl, int);
|
|
||||||
if (_width >= 0) {
|
|
||||||
width = static_cast<u32>(_width);
|
|
||||||
} else {
|
|
||||||
SetFlag(FormatSpecifierFlag_LeftJustify);
|
|
||||||
width = static_cast<u32>(-_width);
|
|
||||||
}
|
|
||||||
format++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next, parse precision if present. */
|
|
||||||
u32 precision = 0;
|
|
||||||
if (*format == '.') {
|
|
||||||
SetFlag(FormatSpecifierFlag_HasPrecision);
|
|
||||||
format++;
|
|
||||||
|
|
||||||
if (IsDigit(*format)) {
|
|
||||||
/* Integer precision. */
|
|
||||||
precision = ParseU32(format);
|
|
||||||
} else if (*format == '*') {
|
|
||||||
/* Dynamic precision. */
|
|
||||||
const int _precision = va_arg(vl, int);
|
|
||||||
if (_precision > 0) {
|
|
||||||
precision = static_cast<u32>(_precision);
|
|
||||||
}
|
|
||||||
format++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse length. */
|
|
||||||
constexpr bool SizeIsLong = sizeof(size_t) == sizeof(long);
|
|
||||||
constexpr bool IntMaxIsLong = sizeof(intmax_t) == sizeof(long);
|
|
||||||
constexpr bool PtrDiffIsLong = sizeof(ptrdiff_t) == sizeof(long);
|
|
||||||
switch (*format) {
|
|
||||||
case 'z':
|
|
||||||
SetFlag(SizeIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
|
|
||||||
format++;
|
|
||||||
break;
|
|
||||||
case 'j':
|
|
||||||
SetFlag(IntMaxIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
|
|
||||||
format++;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
SetFlag(PtrDiffIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
|
|
||||||
format++;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
SetFlag(FormatSpecifierFlag_Short);
|
|
||||||
format++;
|
|
||||||
if (*format == 'h') {
|
|
||||||
SetFlag(FormatSpecifierFlag_Char);
|
|
||||||
format++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
SetFlag(FormatSpecifierFlag_Long);
|
|
||||||
format++;
|
|
||||||
if (*format == 'l') {
|
|
||||||
SetFlag(FormatSpecifierFlag_LongLong);
|
|
||||||
format++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char specifier = *(format++);
|
|
||||||
switch (specifier) {
|
|
||||||
case 'p':
|
|
||||||
if constexpr (sizeof(uintptr_t) == sizeof(long long)) {
|
|
||||||
SetFlag(FormatSpecifierFlag_LongLong);
|
|
||||||
} else {
|
|
||||||
SetFlag(FormatSpecifierFlag_Long);
|
|
||||||
}
|
|
||||||
SetFlag(FormatSpecifierFlag_Hash);
|
|
||||||
[[fallthrough]];
|
|
||||||
case 'd':
|
|
||||||
case 'i':
|
|
||||||
case 'u':
|
|
||||||
case 'b':
|
|
||||||
case 'o':
|
|
||||||
case 'x':
|
|
||||||
case 'X':
|
|
||||||
{
|
|
||||||
/* Determine the base to print with. */
|
|
||||||
u32 base;
|
|
||||||
switch (specifier) {
|
|
||||||
case 'b':
|
|
||||||
base = 2;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
base = 8;
|
|
||||||
break;
|
|
||||||
case 'X':
|
|
||||||
SetFlag(FormatSpecifierFlag_Uppercase);
|
|
||||||
[[fallthrough]];
|
|
||||||
case 'p':
|
|
||||||
case 'x':
|
|
||||||
base = 16;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
base = 10;
|
|
||||||
ClearFlag(FormatSpecifierFlag_Hash);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Precision implies no zero-padding. */
|
|
||||||
if (HasFlag(FormatSpecifierFlag_HasPrecision)) {
|
|
||||||
ClearFlag(FormatSpecifierFlag_ZeroPad);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unsigned types don't get signs. */
|
|
||||||
const bool is_unsigned = base != 10 || specifier == 'u';
|
|
||||||
if (is_unsigned) {
|
|
||||||
ClearFlag(FormatSpecifierFlag_EmptySign);
|
|
||||||
ClearFlag(FormatSpecifierFlag_ForceSign);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PrintInteger = [&](bool negative, uintmax_t value) {
|
|
||||||
constexpr size_t BufferSize = 64; /* Binary digits for 64-bit numbers may use 64 digits. */
|
|
||||||
char buf[BufferSize];
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
/* No hash flag for zero. */
|
|
||||||
if (value == 0) {
|
|
||||||
ClearFlag(FormatSpecifierFlag_Hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!HasFlag(FormatSpecifierFlag_HasPrecision) || value != 0) {
|
|
||||||
do {
|
|
||||||
const char digit = static_cast<char>(value % base);
|
|
||||||
buf[len++] = (digit < 10) ? ('0' + digit) : ((HasFlag(FormatSpecifierFlag_Uppercase) ? 'A' : 'a') + digit - 10);
|
|
||||||
value /= base;
|
|
||||||
} while (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine our prefix length. */
|
|
||||||
size_t prefix_len = 0;
|
|
||||||
const bool has_sign = negative || HasFlag(FormatSpecifierFlag_ForceSign) || HasFlag(FormatSpecifierFlag_EmptySign);
|
|
||||||
if (has_sign) {
|
|
||||||
prefix_len++;
|
|
||||||
}
|
|
||||||
if (HasFlag(FormatSpecifierFlag_Hash)) {
|
|
||||||
prefix_len += (base != 8) ? 2 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine zero-padding count. */
|
|
||||||
size_t num_zeroes = (len < precision) ? precision - len : 0;
|
|
||||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify) && HasFlag(FormatSpecifierFlag_ZeroPad)) {
|
|
||||||
num_zeroes = (len + prefix_len < width) ? width - len - prefix_len : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out left padding. */
|
|
||||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
|
||||||
for (size_t i = len + prefix_len + num_zeroes; i < static_cast<size_t>(width); i++) {
|
|
||||||
WriteCharacter(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out sign. */
|
|
||||||
if (negative) {
|
|
||||||
WriteCharacter('-');
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_ForceSign)) {
|
|
||||||
WriteCharacter('+');
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_EmptySign)) {
|
|
||||||
WriteCharacter(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out base prefix. */
|
|
||||||
if (HasFlag(FormatSpecifierFlag_Hash)) {
|
|
||||||
WriteCharacter('0');
|
|
||||||
if (base == 2) {
|
|
||||||
WriteCharacter('b');
|
|
||||||
} else if (base == 16) {
|
|
||||||
WriteCharacter('x');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out zeroes. */
|
|
||||||
for (size_t i = 0; i < num_zeroes; i++) {
|
|
||||||
WriteCharacter('0');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out digits. */
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
WriteCharacter(buf[len - 1 - i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out right padding. */
|
|
||||||
if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
|
||||||
for (size_t i = len + prefix_len + num_zeroes; i < static_cast<size_t>(width); i++) {
|
|
||||||
WriteCharacter(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Output the integer. */
|
|
||||||
if (is_unsigned) {
|
|
||||||
uintmax_t n = 0;
|
|
||||||
if (HasFlag(FormatSpecifierFlag_LongLong)) {
|
|
||||||
n = static_cast<unsigned long long>(va_arg(vl, unsigned long long));
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_Long)) {
|
|
||||||
n = static_cast<unsigned long>(va_arg(vl, unsigned long));
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_Char)) {
|
|
||||||
n = static_cast<unsigned char>(va_arg(vl, unsigned int));
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_Short)) {
|
|
||||||
n = static_cast<unsigned short>(va_arg(vl, unsigned int));
|
|
||||||
} else {
|
|
||||||
n = static_cast<unsigned int>(va_arg(vl, unsigned int));
|
|
||||||
}
|
|
||||||
if (specifier == 'p' && n == 0) {
|
|
||||||
WriteCharacter('(');
|
|
||||||
WriteCharacter('n');
|
|
||||||
WriteCharacter('i');
|
|
||||||
WriteCharacter('l');
|
|
||||||
WriteCharacter(')');
|
|
||||||
} else {
|
|
||||||
PrintInteger(false, n);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
intmax_t n = 0;
|
|
||||||
if (HasFlag(FormatSpecifierFlag_LongLong)) {
|
|
||||||
n = static_cast<signed long long>(va_arg(vl, signed long long));
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_Long)) {
|
|
||||||
n = static_cast<signed long>(va_arg(vl, signed long));
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_Char)) {
|
|
||||||
n = static_cast<signed char>(va_arg(vl, signed int));
|
|
||||||
} else if (HasFlag(FormatSpecifierFlag_Short)) {
|
|
||||||
n = static_cast<signed short>(va_arg(vl, signed int));
|
|
||||||
} else {
|
|
||||||
n = static_cast<signed int>(va_arg(vl, signed int));
|
|
||||||
}
|
|
||||||
const bool negative = n < 0;
|
|
||||||
const uintmax_t u = (negative) ? static_cast<uintmax_t>(-n) : static_cast<uintmax_t>(n);
|
|
||||||
PrintInteger(negative, u);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
{
|
|
||||||
size_t len = 1;
|
|
||||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
|
||||||
while (len++ < width) {
|
|
||||||
WriteCharacter(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WriteCharacter(static_cast<char>(va_arg(vl, int)));
|
|
||||||
if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
|
||||||
while (len++ < width) {
|
|
||||||
WriteCharacter(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
{
|
|
||||||
const char *str = va_arg(vl, char *);
|
|
||||||
if (str == nullptr) {
|
|
||||||
str = "(null)";
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len = Strnlen(str, precision > 0 ? precision : std::numeric_limits<size_t>::max());
|
|
||||||
if (HasFlag(FormatSpecifierFlag_HasPrecision)) {
|
|
||||||
len = (len < precision) ? len : precision;
|
|
||||||
}
|
|
||||||
if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
|
||||||
while (len++ < width) {
|
|
||||||
WriteCharacter(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (*str && (!HasFlag(FormatSpecifierFlag_HasPrecision) || (precision--) != 0)) {
|
|
||||||
WriteCharacter(*(str++));
|
|
||||||
}
|
|
||||||
if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
|
|
||||||
while (len++ < width) {
|
|
||||||
WriteCharacter(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
default:
|
|
||||||
WriteCharacter(specifier);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure null termination. */
|
|
||||||
WriteCharacter('\0');
|
|
||||||
dst[dst_size - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
KSpinLock g_debug_log_lock;
|
KSpinLock g_debug_log_lock;
|
||||||
bool g_initialized_impl;
|
bool g_initialized_impl;
|
||||||
|
|
||||||
@@ -452,9 +75,6 @@ namespace ams::kern {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma GCC pop_options
|
|
||||||
|
|
||||||
void KDebugLog::Initialize() {
|
void KDebugLog::Initialize() {
|
||||||
if (KTargetSystem::IsDebugLoggingEnabled()) {
|
if (KTargetSystem::IsDebugLoggingEnabled()) {
|
||||||
KScopedInterruptDisable di;
|
KScopedInterruptDisable di;
|
||||||
@@ -486,7 +106,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void KDebugLog::VSNPrintf(char *dst, const size_t dst_size, const char *format, ::std::va_list vl) {
|
void KDebugLog::VSNPrintf(char *dst, const size_t dst_size, const char *format, ::std::va_list vl) {
|
||||||
VSNPrintfImpl(dst, dst_size, format, vl);
|
::ams::util::TVSNPrintf(dst, dst_size, format, vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KDebugLog::PrintUserString(ams::kern::svc::KUserPointer<const char *> user_str, size_t len) {
|
Result KDebugLog::PrintUserString(ams::kern::svc::KUserPointer<const char *> user_str, size_t len) {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
|
#if defined(MESOSPHERE_DEBUG_LOG_USE_UART_A) || defined(MESOSPHERE_DEBUG_LOG_USE_UART_B) || defined(MESOSPHERE_DEBUG_LOG_USE_UART_C) || defined(MESOSPHERE_DEBUG_LOG_USE_UART_D)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum UartRegister {
|
enum UartRegister {
|
||||||
@@ -138,4 +140,52 @@ namespace ams::kern {
|
|||||||
ReadUartRegister(UartRegister_FCR);
|
ReadUartRegister(UartRegister_FCR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(MESOSPHERE_DEBUG_LOG_USE_IRAM_RINGBUFFER)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constinit KVirtualAddress g_debug_iram_address = 0;
|
||||||
|
|
||||||
|
constexpr size_t RingBufferSize = 0x5000;
|
||||||
|
constinit uintptr_t g_offset = 0;
|
||||||
|
|
||||||
|
constinit u8 g_saved_buffer[RingBufferSize];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDebugLogImpl::Initialize() {
|
||||||
|
/* Set the base address. */
|
||||||
|
g_debug_iram_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 0x38000;
|
||||||
|
|
||||||
|
std::memset(GetVoidPointer(g_debug_iram_address), 0xFF, RingBufferSize);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDebugLogImpl::PutChar(char c) {
|
||||||
|
GetPointer<char>(g_debug_iram_address)[g_offset++] = c;
|
||||||
|
|
||||||
|
if (g_offset == RingBufferSize) {
|
||||||
|
g_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDebugLogImpl::Flush() {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDebugLogImpl::Save() {
|
||||||
|
std::memcpy(g_saved_buffer, GetVoidPointer(g_debug_iram_address), RingBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDebugLogImpl::Restore() {
|
||||||
|
std::memcpy(GetVoidPointer(g_debug_iram_address), g_saved_buffer, RingBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error "Unknown Debug UART device!"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,15 +73,16 @@ namespace ams::kern {
|
|||||||
s32 num_waiters = 0;
|
s32 num_waiters = 0;
|
||||||
{
|
{
|
||||||
KScopedSchedulerLock sl;
|
KScopedSchedulerLock sl;
|
||||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
|
||||||
|
|
||||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
|
||||||
|
|
||||||
/* Check the userspace value. */
|
/* Check the userspace value. */
|
||||||
s32 user_value;
|
s32 user_value;
|
||||||
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
||||||
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
||||||
|
|
||||||
|
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||||
|
|
||||||
|
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||||
|
|
||||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
KThread *target_thread = std::addressof(*it);
|
KThread *target_thread = std::addressof(*it);
|
||||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||||
@@ -108,26 +109,54 @@ namespace ams::kern {
|
|||||||
|
|
||||||
/* Determine the updated value. */
|
/* Determine the updated value. */
|
||||||
s32 new_value;
|
s32 new_value;
|
||||||
if (count <= 0) {
|
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {
|
||||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
if (count <= 0) {
|
||||||
new_value = value - 1;
|
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
|
new_value = value - 2;
|
||||||
|
} else {
|
||||||
|
new_value = value + 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
new_value = value + 1;
|
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
|
auto tmp_it = it;
|
||||||
|
s32 tmp_num_waiters = 0;
|
||||||
|
while ((++tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
|
||||||
|
if ((tmp_num_waiters++) >= count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp_num_waiters < count) {
|
||||||
|
new_value = value - 1;
|
||||||
|
} else {
|
||||||
|
new_value = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new_value = value + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto tmp_it = it;
|
if (count <= 0) {
|
||||||
int tmp_num_waiters = 0;
|
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
while ((tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
new_value = value - 1;
|
||||||
++tmp_num_waiters;
|
} else {
|
||||||
++tmp_it;
|
new_value = value + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp_num_waiters == 0) {
|
|
||||||
new_value = value + 1;
|
|
||||||
} else if (tmp_num_waiters <= count) {
|
|
||||||
new_value = value - 1;
|
|
||||||
} else {
|
} else {
|
||||||
new_value = value;
|
auto tmp_it = it;
|
||||||
|
s32 tmp_num_waiters = 0;
|
||||||
|
while ((tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
||||||
|
++tmp_num_waiters;
|
||||||
|
++tmp_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp_num_waiters == 0) {
|
||||||
|
new_value = value + 1;
|
||||||
|
} else if (tmp_num_waiters <= count) {
|
||||||
|
new_value = value - 1;
|
||||||
|
} else {
|
||||||
|
new_value = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Map the memory. */
|
/* Map the memory. */
|
||||||
R_TRY(GetCurrentProcess().GetPageTable().MapPageGroup(address, GetReference(this->page_group), KMemoryState_GeneratedCode, k_perm));
|
R_TRY(this->owner->GetPageTable().MapPageGroup(address, GetReference(this->page_group), KMemoryState_GeneratedCode, k_perm));
|
||||||
|
|
||||||
/* Mark ourselves as mapped. */
|
/* Mark ourselves as mapped. */
|
||||||
this->is_owner_mapped = true;
|
this->is_owner_mapped = true;
|
||||||
@@ -151,7 +151,7 @@ namespace ams::kern {
|
|||||||
KScopedLightLock lk(this->lock);
|
KScopedLightLock lk(this->lock);
|
||||||
|
|
||||||
/* Unmap the memory. */
|
/* Unmap the memory. */
|
||||||
R_TRY(GetCurrentProcess().GetPageTable().UnmapPageGroup(address, GetReference(this->page_group), KMemoryState_GeneratedCode));
|
R_TRY(this->owner->GetPageTable().UnmapPageGroup(address, GetReference(this->page_group), KMemoryState_GeneratedCode));
|
||||||
|
|
||||||
/* Mark ourselves as unmapped. */
|
/* Mark ourselves as unmapped. */
|
||||||
MESOSPHERE_ASSERT(this->is_owner_mapped);
|
MESOSPHERE_ASSERT(this->is_owner_mapped);
|
||||||
|
|||||||
@@ -205,13 +205,8 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Close threads in the list. */
|
/* Close threads in the list. */
|
||||||
if (num_waiters > MaxThreads) {
|
for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) {
|
||||||
auto it = thread_list.begin();
|
(*it).Close();
|
||||||
while (it != thread_list.end()) {
|
|
||||||
KThread *thread = std::addressof(*it);
|
|
||||||
thread->Close();
|
|
||||||
it = thread_list.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ namespace ams::kern {
|
|||||||
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006200, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006200, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
||||||
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_D)
|
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_D)
|
||||||
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006300, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006300, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
||||||
|
#elif defined(MESOSPHERE_DEBUG_LOG_USE_IRAM_RINGBUFFER)
|
||||||
|
return true;
|
||||||
#else
|
#else
|
||||||
#error "Unknown Debug UART device!"
|
#error "Unknown Debug UART device!"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
KScopedDisableDispatch::~KScopedDisableDispatch() {
|
||||||
|
if (GetCurrentThread().GetDisableDispatchCount() <= 1) {
|
||||||
|
Kernel::GetScheduler().RescheduleCurrentCore();
|
||||||
|
} else {
|
||||||
|
GetCurrentThread().EnableDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,11 @@ namespace ams::result::impl {
|
|||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
|
/* NOTE: This is not exposed via a header, but is referenced via assembly. */
|
||||||
|
/* NOTE: Nintendo does not save register contents on panic; we use this */
|
||||||
|
/* to generate an atmosphere fatal report on panic. */
|
||||||
|
constinit KExceptionContext g_panic_exception_contexts[cpu::NumCores];
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr std::array<s32, cpu::NumCores> NegativeArray = [] {
|
constexpr std::array<s32, cpu::NumCores> NegativeArray = [] {
|
||||||
@@ -73,18 +78,38 @@ namespace ams::kern {
|
|||||||
} while (!g_current_ticket.compare_exchange_weak(compare, desired));
|
} while (!g_current_ticket.compare_exchange_weak(compare, desired));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KExceptionContext *GetPanicExceptionContext(int core_id) {
|
||||||
|
#if defined(MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP)
|
||||||
|
return std::addressof(g_panic_exception_contexts[core_id]);
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
[[gnu::unused]] void PrintCurrentState() {
|
[[gnu::unused]] void PrintCurrentState() {
|
||||||
/* Wait for it to be our turn to print. */
|
/* Wait for it to be our turn to print. */
|
||||||
WaitCoreTicket();
|
WaitCoreTicket();
|
||||||
|
|
||||||
const s32 core_id = GetCurrentCoreId();
|
/* Get the current exception context. */
|
||||||
|
const s32 core_id = GetCurrentCoreId();
|
||||||
|
const auto *core_ctx = GetPanicExceptionContext(core_id);
|
||||||
|
|
||||||
|
/* Print the state. */
|
||||||
MESOSPHERE_RELEASE_LOG("Core[%d] Current State:\n", core_id);
|
MESOSPHERE_RELEASE_LOG("Core[%d] Current State:\n", core_id);
|
||||||
|
|
||||||
/* TODO: Dump register state. */
|
|
||||||
|
|
||||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||||
|
/* Print registers. */
|
||||||
|
if (core_ctx != nullptr) {
|
||||||
|
MESOSPHERE_RELEASE_LOG(" Registers:\n");
|
||||||
|
for (size_t i = 0; i < util::size(core_ctx->x); ++i) {
|
||||||
|
MESOSPHERE_RELEASE_LOG(" X[%02zx]: %p\n", i, reinterpret_cast<void *>(core_ctx->x[i]));
|
||||||
|
}
|
||||||
|
MESOSPHERE_RELEASE_LOG(" SP: %p\n", reinterpret_cast<void *>(core_ctx->x[30]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print backtrace. */
|
||||||
MESOSPHERE_RELEASE_LOG(" Backtrace:\n");
|
MESOSPHERE_RELEASE_LOG(" Backtrace:\n");
|
||||||
uintptr_t fp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
|
uintptr_t fp = core_ctx != nullptr ? core_ctx->x[29] : reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
|
||||||
for (size_t i = 0; i < 32 && fp && util::IsAligned(fp, 0x10) && cpu::GetPhysicalAddressWritable(nullptr, fp, true); i++) {
|
for (size_t i = 0; i < 32 && fp && util::IsAligned(fp, 0x10) && cpu::GetPhysicalAddressWritable(nullptr, fp, true); i++) {
|
||||||
struct {
|
struct {
|
||||||
uintptr_t fp;
|
uintptr_t fp;
|
||||||
@@ -107,12 +132,12 @@ namespace ams::kern {
|
|||||||
PrintCurrentState();
|
PrintCurrentState();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KSystemControl::StopSystem();
|
KSystemControl::StopSystem(GetPanicExceptionContext(GetCurrentCoreId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN WEAK_SYMBOL void Panic(const char *file, int line, const char *format, ...) {
|
NORETURN void PanicImpl(const char *file, int line, const char *format, ...) {
|
||||||
#ifdef MESOSPHERE_BUILD_FOR_DEBUGGING
|
#ifdef MESOSPHERE_BUILD_FOR_DEBUGGING
|
||||||
/* Wait for it to be our turn to print. */
|
/* Wait for it to be our turn to print. */
|
||||||
WaitCoreTicket();
|
WaitCoreTicket();
|
||||||
@@ -133,7 +158,7 @@ namespace ams::kern {
|
|||||||
StopSystem();
|
StopSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN WEAK_SYMBOL void Panic() {
|
NORETURN void PanicImpl() {
|
||||||
StopSystem();
|
StopSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ namespace ams::kern::svc {
|
|||||||
case ams::svc::CodeMemoryOperation_MapToOwner:
|
case ams::svc::CodeMemoryOperation_MapToOwner:
|
||||||
{
|
{
|
||||||
/* Check that the region is in range. */
|
/* Check that the region is in range. */
|
||||||
R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_GeneratedCode), svc::ResultInvalidMemoryRegion());
|
R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size, KMemoryState_GeneratedCode), svc::ResultInvalidMemoryRegion());
|
||||||
|
|
||||||
/* Check the memory permission. */
|
/* Check the memory permission. */
|
||||||
R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), svc::ResultInvalidNewMemoryPermission());
|
R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), svc::ResultInvalidNewMemoryPermission());
|
||||||
@@ -122,7 +122,7 @@ namespace ams::kern::svc {
|
|||||||
case ams::svc::CodeMemoryOperation_UnmapFromOwner:
|
case ams::svc::CodeMemoryOperation_UnmapFromOwner:
|
||||||
{
|
{
|
||||||
/* Check that the region is in range. */
|
/* Check that the region is in range. */
|
||||||
R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_GeneratedCode), svc::ResultInvalidMemoryRegion());
|
R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size, KMemoryState_GeneratedCode), svc::ResultInvalidMemoryRegion());
|
||||||
|
|
||||||
/* Check the memory permission. */
|
/* Check the memory permission. */
|
||||||
R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), svc::ResultInvalidNewMemoryPermission());
|
R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), svc::ResultInvalidNewMemoryPermission());
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in common atmosphere configuration
|
# pull in common atmosphere configuration
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in switch rules
|
# pull in switch rules
|
||||||
@@ -15,7 +17,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/stratosphere.hpp
|
PRECOMPILED_HEADERS := $(CURRENT_DIRECTORY)/include/stratosphere.hpp
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
||||||
@@ -66,7 +68,7 @@ endif
|
|||||||
|
|
||||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
export GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.gch),$(notdir $(hdr)))
|
export GCH_FILES := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
|
||||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
@@ -103,12 +105,12 @@ dist: dist-src dist-bin
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@rm -fr release lib *.bz2 include/stratosphere.hpp.gch
|
@rm -fr release lib *.bz2 $(GCH_FILES)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
|
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES:.gch=.d),$(notdir $(hdr)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# main targets
|
# main targets
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include <stratosphere/erpt.hpp>
|
#include <stratosphere/erpt.hpp>
|
||||||
#include <stratosphere/err.hpp>
|
#include <stratosphere/err.hpp>
|
||||||
#include <stratosphere/fatal.hpp>
|
#include <stratosphere/fatal.hpp>
|
||||||
|
#include <stratosphere/gpio.hpp>
|
||||||
#include <stratosphere/hid.hpp>
|
#include <stratosphere/hid.hpp>
|
||||||
#include <stratosphere/hos.hpp>
|
#include <stratosphere/hos.hpp>
|
||||||
#include <stratosphere/kvdb.hpp>
|
#include <stratosphere/kvdb.hpp>
|
||||||
@@ -60,7 +61,6 @@
|
|||||||
#include <stratosphere/pgl.hpp>
|
#include <stratosphere/pgl.hpp>
|
||||||
#include <stratosphere/psc.hpp>
|
#include <stratosphere/psc.hpp>
|
||||||
#include <stratosphere/pm.hpp>
|
#include <stratosphere/pm.hpp>
|
||||||
#include <stratosphere/reg.hpp>
|
|
||||||
#include <stratosphere/ro.hpp>
|
#include <stratosphere/ro.hpp>
|
||||||
#include <stratosphere/settings.hpp>
|
#include <stratosphere/settings.hpp>
|
||||||
#include <stratosphere/sf.hpp>
|
#include <stratosphere/sf.hpp>
|
||||||
|
|||||||
@@ -65,47 +65,9 @@ namespace ams::exosphere {
|
|||||||
|
|
||||||
namespace ams {
|
namespace ams {
|
||||||
|
|
||||||
struct FatalErrorContext : sf::LargeData, sf::PrefersMapAliasTransferMode {
|
struct FatalErrorContext : ::ams::impl::FatalErrorContext, sf::LargeData, sf::PrefersMapAliasTransferMode {};
|
||||||
static constexpr size_t MaxStackTrace = 0x20;
|
|
||||||
static constexpr size_t MaxStackDumpSize = 0x100;
|
|
||||||
static constexpr size_t ThreadLocalSize = 0x100;
|
|
||||||
static constexpr size_t NumGprs = 29;
|
|
||||||
static constexpr uintptr_t StdAbortMagicAddress = 0x8;
|
|
||||||
static constexpr u64 StdAbortMagicValue = 0xA55AF00DDEADCAFEul;
|
|
||||||
static constexpr u32 StdAbortErrorDesc = 0xFFE;
|
|
||||||
static constexpr u32 StackOverflowErrorDesc = 0xFFD;
|
|
||||||
static constexpr u32 DataAbortErrorDesc = 0x101;
|
|
||||||
static constexpr u32 Magic = util::FourCC<'A', 'F', 'E', '2'>::Code;
|
|
||||||
|
|
||||||
u32 magic;
|
static_assert(sizeof(FatalErrorContext) == sizeof(::ams::impl::FatalErrorContext));
|
||||||
u32 error_desc;
|
|
||||||
u64 program_id;
|
|
||||||
union {
|
|
||||||
u64 gprs[32];
|
|
||||||
struct {
|
|
||||||
u64 _gprs[29];
|
|
||||||
u64 fp;
|
|
||||||
u64 lr;
|
|
||||||
u64 sp;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
u64 pc;
|
|
||||||
u64 module_base;
|
|
||||||
u32 pstate;
|
|
||||||
u32 afsr0;
|
|
||||||
u32 afsr1;
|
|
||||||
u32 esr;
|
|
||||||
u64 far;
|
|
||||||
u64 report_identifier; /* Normally just system tick. */
|
|
||||||
u64 stack_trace_size;
|
|
||||||
u64 stack_dump_size;
|
|
||||||
u64 stack_trace[MaxStackTrace];
|
|
||||||
u8 stack_dump[MaxStackDumpSize];
|
|
||||||
u8 tls[ThreadLocalSize];
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(FatalErrorContext) == 0x450, "sizeof(FatalErrorContext)");
|
|
||||||
static_assert(util::is_pod<FatalErrorContext>::value, "FatalErrorContext");
|
|
||||||
|
|
||||||
#ifdef ATMOSPHERE_GIT_BRANCH
|
#ifdef ATMOSPHERE_GIT_BRANCH
|
||||||
NX_CONSTEXPR const char *GetGitBranch() {
|
NX_CONSTEXPR const char *GetGitBranch() {
|
||||||
|
|||||||
@@ -39,19 +39,21 @@ namespace ams::impl {
|
|||||||
AMS_DEFINE_SYSTEM_THREAD(21, pm, Main);
|
AMS_DEFINE_SYSTEM_THREAD(21, pm, Main);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(21, pm, ProcessTrack);
|
AMS_DEFINE_SYSTEM_THREAD(21, pm, ProcessTrack);
|
||||||
|
|
||||||
|
|
||||||
/* NCM. */
|
/* NCM. */
|
||||||
AMS_DEFINE_SYSTEM_THREAD(21, ncm, MainWaitThreads);
|
AMS_DEFINE_SYSTEM_THREAD(21, ncm, MainWaitThreads);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(21, ncm, ContentManagerServerIpcSession);
|
AMS_DEFINE_SYSTEM_THREAD(21, ncm, ContentManagerServerIpcSession);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(21, ncm, LocationResolverServerIpcSession);
|
AMS_DEFINE_SYSTEM_THREAD(21, ncm, LocationResolverServerIpcSession);
|
||||||
|
|
||||||
/* FS. */
|
/* FS. */
|
||||||
AMS_DEFINE_SYSTEM_THREAD(16, fs, WorkerThreadPool);
|
AMS_DEFINE_SYSTEM_THREAD(11, sdmmc, DeviceDetector);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(17, fs, Main);
|
AMS_DEFINE_SYSTEM_THREAD(16, fs, WorkerThreadPool);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(17, fs, WorkerRealTimeAccess);
|
AMS_DEFINE_SYSTEM_THREAD(17, fs, Main);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(18, fs, WorkerNormalPriorityAccess);
|
AMS_DEFINE_SYSTEM_THREAD(17, fs, WorkerRealTimeAccess);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(19, fs, WorkerLowPriorityAccess);
|
AMS_DEFINE_SYSTEM_THREAD(18, fs, WorkerNormalPriorityAccess);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(30, fs, WorkerBackgroundAccess);
|
AMS_DEFINE_SYSTEM_THREAD(19, fs, WorkerLowPriorityAccess);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(30, fs, PatrolReader);
|
AMS_DEFINE_SYSTEM_THREAD(30, fs, WorkerBackgroundAccess);
|
||||||
|
AMS_DEFINE_SYSTEM_THREAD(30, fs, PatrolReader);
|
||||||
|
|
||||||
/* Boot. */
|
/* Boot. */
|
||||||
AMS_DEFINE_SYSTEM_THREAD(-1, boot, Main);
|
AMS_DEFINE_SYSTEM_THREAD(-1, boot, Main);
|
||||||
|
|||||||
@@ -19,16 +19,13 @@
|
|||||||
|
|
||||||
namespace ams::dd {
|
namespace ams::dd {
|
||||||
|
|
||||||
uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size);
|
u32 ReadRegister(dd::PhysicalAddress phys_addr);
|
||||||
|
void WriteRegister(dd::PhysicalAddress phys_addr, u32 value);
|
||||||
u32 ReadRegister(uintptr_t phys_addr);
|
u32 ReadWriteRegister(dd::PhysicalAddress phys_addr, u32 value, u32 mask);
|
||||||
void WriteRegister(uintptr_t phys_addr, u32 value);
|
|
||||||
u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask);
|
|
||||||
|
|
||||||
/* Convenience Helper. */
|
/* Convenience Helper. */
|
||||||
|
inline uintptr_t GetIoMapping(dd::PhysicalAddress phys_addr, size_t size) {
|
||||||
inline uintptr_t GetIoMapping(uintptr_t phys_addr, size_t size) {
|
const uintptr_t io_mapping = dd::QueryIoMapping(phys_addr, size);
|
||||||
const uintptr_t io_mapping = QueryIoMapping(phys_addr, size);
|
|
||||||
AMS_ABORT_UNLESS(io_mapping);
|
AMS_ABORT_UNLESS(io_mapping);
|
||||||
return io_mapping;
|
return io_mapping;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License
|
* under the terms and conditions of the GNU General Public License,
|
||||||
* version 2, as published by the Free Software Foundation.
|
* version 2, as published by the Free Software Foundation.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
* 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
|
#pragma once
|
||||||
|
|
||||||
#define EVP_COP_RESET_VECTOR 0x200
|
#include <stratosphere/ddsf/ddsf_types.hpp>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
|
||||||
|
namespace ams::ddsf {
|
||||||
|
|
||||||
|
enum AccessMode {
|
||||||
|
AccessMode_None = (0u << 0),
|
||||||
|
AccessMode_Read = (1u << 0),
|
||||||
|
AccessMode_Write = (1u << 1),
|
||||||
|
|
||||||
|
AccessMode_ReadWrite = AccessMode_Read | AccessMode_Write,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,17 +19,17 @@
|
|||||||
|
|
||||||
namespace ams::fs {
|
namespace ams::fs {
|
||||||
|
|
||||||
struct CodeInfo {
|
struct CodeVerificationData {
|
||||||
u8 signature[crypto::Rsa2048PssSha256Verifier::SignatureSize];
|
u8 signature[crypto::Rsa2048PssSha256Verifier::SignatureSize];
|
||||||
u8 hash[crypto::Rsa2048PssSha256Verifier::HashSize];
|
u8 target_hash[crypto::Rsa2048PssSha256Verifier::HashSize];
|
||||||
bool is_signed;
|
bool has_data;
|
||||||
u8 reserved[3];
|
u8 reserved[3];
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CodeInfo) == crypto::Rsa2048PssSha256Verifier::SignatureSize + crypto::Rsa2048PssSha256Verifier::HashSize + 4);
|
static_assert(sizeof(CodeVerificationData) == crypto::Rsa2048PssSha256Verifier::SignatureSize + crypto::Rsa2048PssSha256Verifier::HashSize + 4);
|
||||||
|
|
||||||
Result MountCode(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id);
|
Result MountCode(CodeVerificationData *out, const char *name, const char *path, ncm::ProgramId program_id);
|
||||||
|
|
||||||
Result MountCodeForAtmosphereWithRedirection(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific);
|
Result MountCodeForAtmosphereWithRedirection(CodeVerificationData *out, const char *name, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific);
|
||||||
Result MountCodeForAtmosphere(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id);
|
Result MountCodeForAtmosphere(CodeVerificationData *out, const char *name, const char *path, ncm::ProgramId program_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
22
libraries/libstratosphere/include/stratosphere/gpio.hpp
Normal file
22
libraries/libstratosphere/include/stratosphere/gpio.hpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere/gpio/gpio_types.hpp>
|
||||||
|
#include <stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp>
|
||||||
|
#include <stratosphere/gpio/sf/gpio_sf_i_manager.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_api.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_pad_api.hpp>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License
|
* under the terms and conditions of the GNU General Public License,
|
||||||
* version 2, as published by the Free Software Foundation.
|
* version 2, as published by the Free Software Foundation.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
@@ -14,8 +14,12 @@
|
|||||||
* 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
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_types.hpp>
|
||||||
|
|
||||||
#define APBDEV_PMC_DPD_ENABLE 0x024
|
namespace ams::gpio {
|
||||||
#define APBDEV_PMC_SCRATCH0 0x050
|
|
||||||
#define APBDEV_PMC_SCRATCH4 0x060
|
void Initialize();
|
||||||
#define APBDEV_PMC_SCRATCH39 0x138
|
void Finalize();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/ddsf/ddsf_types.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_types.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_select_pad_name.hpp>
|
||||||
|
|
||||||
|
namespace ams::gpio {
|
||||||
|
|
||||||
|
struct GpioPadSession {
|
||||||
|
void *_session;
|
||||||
|
os::SystemEventType *_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
Result OpenSession(GpioPadSession *out_session, ams::DeviceCode device_code);
|
||||||
|
void CloseSession(GpioPadSession *session);
|
||||||
|
|
||||||
|
Direction GetDirection(GpioPadSession *session);
|
||||||
|
void SetDirection(GpioPadSession *session, Direction direction);
|
||||||
|
|
||||||
|
GpioValue GetValue(GpioPadSession *session);
|
||||||
|
void SetValue(GpioPadSession *session, GpioValue value);
|
||||||
|
|
||||||
|
InterruptMode GetInterruptMode(GpioPadSession *session);
|
||||||
|
void SetInterruptMode(GpioPadSession *session, InterruptMode mode);
|
||||||
|
|
||||||
|
bool GetInterruptEnable(GpioPadSession *session);
|
||||||
|
void SetInterruptEnable(GpioPadSession *session, bool en);
|
||||||
|
|
||||||
|
InterruptStatus GetInterruptStatus(GpioPadSession *session);
|
||||||
|
void ClearInterruptStatus(GpioPadSession *session);
|
||||||
|
|
||||||
|
int GetDebounceTime(GpioPadSession *session);
|
||||||
|
void SetDebounceTime(GpioPadSession *session, int ms);
|
||||||
|
|
||||||
|
bool GetDebounceEnabled(GpioPadSession *session);
|
||||||
|
void SetDebounceEnabled(GpioPadSession *session, bool en);
|
||||||
|
|
||||||
|
Result BindInterrupt(os::SystemEventType *event, GpioPadSession *session);
|
||||||
|
void UnbindInterrupt(GpioPadSession *session);
|
||||||
|
|
||||||
|
Result IsWakeEventActive(bool *out_is_active, ams::DeviceCode device_code);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_types.hpp>
|
||||||
|
|
||||||
|
namespace ams::gpio {
|
||||||
|
|
||||||
|
enum GpioPadName : u32 {
|
||||||
|
GpioPadName_CodecLdoEnTemp = 1,
|
||||||
|
GpioPadName_ButtonVolUp = 25,
|
||||||
|
GpioPadName_ButtonVolDn = 26,
|
||||||
|
GpioPadName_SdCd = 56,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO: Better place for this? */
|
||||||
|
constexpr inline const DeviceCode DeviceCode_CodecLdoEnTemp = 0x33000002;
|
||||||
|
constexpr inline const DeviceCode DeviceCode_ButtonVolUp = 0x35000002;
|
||||||
|
constexpr inline const DeviceCode DeviceCode_ButtonVolDn = 0x35000003;
|
||||||
|
constexpr inline const DeviceCode DeviceCode_SdCd = 0x3C000002;
|
||||||
|
|
||||||
|
constexpr inline GpioPadName ConvertToGpioPadName(DeviceCode dc) {
|
||||||
|
switch (dc.GetInternalValue()) {
|
||||||
|
case DeviceCode_CodecLdoEnTemp.GetInternalValue(): return GpioPadName_CodecLdoEnTemp;
|
||||||
|
case DeviceCode_ButtonVolUp .GetInternalValue(): return GpioPadName_ButtonVolUp;
|
||||||
|
case DeviceCode_ButtonVolDn .GetInternalValue(): return GpioPadName_ButtonVolDn;
|
||||||
|
case DeviceCode_SdCd .GetInternalValue(): return GpioPadName_SdCd;
|
||||||
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline DeviceCode ConvertToDeviceCode(GpioPadName gpn) {
|
||||||
|
switch (gpn) {
|
||||||
|
case GpioPadName_CodecLdoEnTemp: return DeviceCode_CodecLdoEnTemp;
|
||||||
|
case GpioPadName_ButtonVolUp: return DeviceCode_ButtonVolUp;
|
||||||
|
case GpioPadName_ButtonVolDn: return DeviceCode_ButtonVolDn;
|
||||||
|
case GpioPadName_SdCd: return DeviceCode_SdCd;
|
||||||
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_types.hpp>
|
||||||
|
|
||||||
|
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||||
|
#include <stratosphere/gpio/gpio_pad_name.board.nintendo_nx.hpp>
|
||||||
|
#else
|
||||||
|
/* Error? */
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
|
||||||
|
namespace ams::gpio {
|
||||||
|
|
||||||
|
enum InterruptMode : u32 {
|
||||||
|
InterruptMode_LowLevel = 0,
|
||||||
|
InterruptMode_HighLevel = 1,
|
||||||
|
InterruptMode_RisingEdge = 2,
|
||||||
|
InterruptMode_FallingEdge = 3,
|
||||||
|
InterruptMode_AnyEdge = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Direction : u32 {
|
||||||
|
Direction_Input = 0,
|
||||||
|
Direction_Output = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GpioValue : u32 {
|
||||||
|
GpioValue_Low = 0,
|
||||||
|
GpioValue_High = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InterruptStatus : u32 {
|
||||||
|
InterruptStatus_Inactive = 0,
|
||||||
|
InterruptStatus_Active = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
using WakeBitFlag = util::BitFlagSet<128>;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/ddsf/ddsf_types.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_types.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_select_pad_name.hpp>
|
||||||
|
#include <stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp>
|
||||||
|
|
||||||
|
namespace ams::gpio::sf {
|
||||||
|
|
||||||
|
#define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, s32 pad_descriptor) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTest, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActive, (ams::sf::Out<bool> out, gpio::GpioPadName pad_name), hos::Version_Min, hos::Version_6_2_0) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 4, Result, GetWakeEventActiveFlagSet, (ams::sf::Out<gpio::WakeBitFlag> out), hos::Version_Min, hos::Version_6_2_0) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 5, Result, SetWakeEventActiveFlagSetForDebug, (gpio::GpioPadName pad_name, bool is_enabled), hos::Version_Min, hos::Version_6_2_0) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 6, Result, SetWakePinDebugMode, (s32 mode) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 7, Result, OpenSession2, (ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, DeviceCode device_code, ddsf::AccessMode access_mode), hos::Version_5_0_0 ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 8, Result, IsWakeEventActive2, (ams::sf::Out<bool> out, DeviceCode device_code), hos::Version_5_0_0 ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 9, Result, SetWakeEventActiveFlagSetForDebug2, (DeviceCode device_code, bool is_enabled), hos::Version_5_0_0 ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 10, Result, SetRetryValues, (u32 arg0, u32 arg1), hos::Version_6_0_0 )
|
||||||
|
|
||||||
|
AMS_SF_DEFINE_INTERFACE(IManager, AMS_GPIO_I_MANAGER_INTERFACE_INFO)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/gpio/gpio_types.hpp>
|
||||||
|
|
||||||
|
namespace ams::gpio::sf {
|
||||||
|
|
||||||
|
#define AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO(C, H) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 0, Result, SetDirection, (gpio::Direction direction) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 1, Result, GetDirection, (ams::sf::Out<gpio::Direction> out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 2, Result, SetInterruptMode, (gpio::InterruptMode mode) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 3, Result, GetInterruptMode, (ams::sf::Out<gpio::InterruptMode> out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 4, Result, SetInterruptEnable, (bool enable) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 5, Result, GetInterruptEnable, (ams::sf::Out<bool> out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out<gpio::InterruptStatus> out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 7, Result, ClearInterruptStatus, () ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 8, Result, SetValue, (gpio::GpioValue value) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 9, Result, GetValue, (ams::sf::Out<gpio::GpioValue> out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 10, Result, BindInterrupt, (ams::sf::OutCopyHandle out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 11, Result, UnbindInterrupt, () ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 12, Result, SetDebounceEnabled, (bool enable) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 13, Result, GetDebounceEnabled, (ams::sf::Out<bool> out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 14, Result, SetDebounceTime, (s32 ms) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 15, Result, GetDebounceTime, (ams::sf::Out<s32> out) ) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 16, Result, SetValueForSleepState, (gpio::GpioValue value), hos::Version_4_0_0) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 16, Result, GetValueForSleepState, (ams::sf::Out<gpio::GpioValue> out), hos::Version_6_0_0)
|
||||||
|
|
||||||
|
AMS_SF_DEFINE_INTERFACE(IPadSession, AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <vapours.hpp>
|
|
||||||
|
|
||||||
namespace ams::reg {
|
|
||||||
|
|
||||||
inline void Write(volatile u32 *reg, u32 val) {
|
|
||||||
*reg = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Write(uintptr_t reg, u32 val) {
|
|
||||||
Write(reinterpret_cast<volatile u32 *>(reg), val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u32 Read(volatile u32 *reg) {
|
|
||||||
return *reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u32 Read(uintptr_t reg) {
|
|
||||||
return Read(reinterpret_cast<volatile u32 *>(reg));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SetBits(volatile u32 *reg, u32 mask) {
|
|
||||||
*reg = *reg | mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SetBits(uintptr_t reg, u32 mask) {
|
|
||||||
SetBits(reinterpret_cast<volatile u32 *>(reg), mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ClearBits(volatile u32 *reg, u32 mask) {
|
|
||||||
*reg = *reg & ~mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ClearBits(uintptr_t reg, u32 mask) {
|
|
||||||
ClearBits(reinterpret_cast<volatile u32 *>(reg), mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void MaskBits(volatile u32 *reg, u32 mask) {
|
|
||||||
*reg = *reg & mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void MaskBits(uintptr_t reg, u32 mask) {
|
|
||||||
MaskBits(reinterpret_cast<volatile u32 *>(reg), mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ReadWrite(volatile u32 *reg, u32 val, u32 mask) {
|
|
||||||
*reg = (*reg & (~mask)) | (val & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ReadWrite(uintptr_t reg, u32 val, u32 mask) {
|
|
||||||
ReadWrite(reinterpret_cast<volatile u32 *>(reg), val, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,7 @@ namespace ams::ro::impl {
|
|||||||
AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size)) \
|
AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address)) \
|
AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle process_h)) \
|
AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle process_h)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterModuleInfoEx, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h), hos::Version_7_0_0)
|
AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterProcessModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h), hos::Version_7_0_0)
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(IRoInterface, AMS_RO_I_RO_INTERFACE_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(IRoInterface, AMS_RO_I_RO_INTERFACE_INTERFACE_INFO)
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,11 @@
|
|||||||
|
|
||||||
namespace ams::ro {
|
namespace ams::ro {
|
||||||
|
|
||||||
enum class ModuleType : u8 {
|
enum NrrKind : u8 {
|
||||||
ForSelf = 0,
|
NrrKind_User = 0,
|
||||||
ForOthers = 1,
|
NrrKind_JitPlugin = 1,
|
||||||
Count
|
|
||||||
|
NrrKind_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModuleId {
|
struct ModuleId {
|
||||||
@@ -54,7 +55,7 @@ namespace ams::ro {
|
|||||||
u8 signature[0x100];
|
u8 signature[0x100];
|
||||||
ncm::ProgramId program_id;
|
ncm::ProgramId program_id;
|
||||||
u32 size;
|
u32 size;
|
||||||
u8 type; /* 7.0.0+ */
|
u8 nrr_kind; /* 7.0.0+ */
|
||||||
u8 reserved_33D[3];
|
u8 reserved_33D[3];
|
||||||
u32 hashes_offset;
|
u32 hashes_offset;
|
||||||
u32 num_hashes;
|
u32 num_hashes;
|
||||||
@@ -68,10 +69,10 @@ namespace ams::ro {
|
|||||||
return (static_cast<u64>(this->program_id) & this->certification.program_id_mask) == this->certification.program_id_pattern;
|
return (static_cast<u64>(this->program_id) & this->certification.program_id_mask) == this->certification.program_id_pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleType GetType() const {
|
NrrKind GetNrrKind() const {
|
||||||
const ModuleType type = static_cast<ModuleType>(this->type);
|
const NrrKind kind = static_cast<NrrKind>(this->nrr_kind);
|
||||||
AMS_ABORT_UNLESS(type < ModuleType::Count);
|
AMS_ABORT_UNLESS(kind < NrrKind_Count);
|
||||||
return type;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
ncm::ProgramId GetProgramId() const {
|
ncm::ProgramId GetProgramId() const {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace ams::spl::smc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Functions. */
|
/* Functions. */
|
||||||
Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords);
|
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords);
|
||||||
Result GetConfig(u64 *out, size_t num_qwords, spl::ConfigItem which);
|
Result GetConfig(u64 *out, size_t num_qwords, spl::ConfigItem which);
|
||||||
Result GetResult(Result *out, AsyncOperationKey op);
|
Result GetResult(Result *out, AsyncOperationKey op);
|
||||||
Result GetResultData(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op);
|
Result GetResultData(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op);
|
||||||
@@ -59,8 +59,12 @@ namespace ams::spl::smc {
|
|||||||
Result AtmosphereGetEmummcConfig(void *out_config, void *out_paths, u32 storage_id);
|
Result AtmosphereGetEmummcConfig(void *out_config, void *out_paths, u32 storage_id);
|
||||||
|
|
||||||
/* Helpers. */
|
/* Helpers. */
|
||||||
|
inline Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords) {
|
||||||
|
return SetConfig(which, nullptr, value, num_qwords);
|
||||||
|
}
|
||||||
|
|
||||||
inline Result SetConfig(spl::ConfigItem which, const u64 value) {
|
inline Result SetConfig(spl::ConfigItem which, const u64 value) {
|
||||||
return SetConfig(which, &value, 1);
|
return SetConfig(which, std::addressof(value), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ namespace ams::spl {
|
|||||||
ExosphereBlankProdInfo = 65005,
|
ExosphereBlankProdInfo = 65005,
|
||||||
ExosphereAllowCalWrites = 65006,
|
ExosphereAllowCalWrites = 65006,
|
||||||
ExosphereEmummcType = 65007,
|
ExosphereEmummcType = 65007,
|
||||||
|
ExospherePayloadAddress = 65008,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -235,3 +236,4 @@ constexpr inline SplConfigItem SplConfigItem_ExosphereHasRcmBugPatch = static_ca
|
|||||||
constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast<SplConfigItem>(65005);
|
constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast<SplConfigItem>(65005);
|
||||||
constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast<SplConfigItem>(65006);
|
constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast<SplConfigItem>(65006);
|
||||||
constexpr inline SplConfigItem SplConfigItem_ExosphereEmummcType = static_cast<SplConfigItem>(65007);
|
constexpr inline SplConfigItem SplConfigItem_ExosphereEmummcType = static_cast<SplConfigItem>(65007);
|
||||||
|
constexpr inline SplConfigItem SplConfigItem_ExospherePayloadAddress = static_cast<SplConfigItem>(65008);
|
||||||
|
|||||||
@@ -74,7 +74,10 @@ namespace ams {
|
|||||||
ams_ctx.pc = ctx->pc.x;
|
ams_ctx.pc = ctx->pc.x;
|
||||||
ams_ctx.pstate = ctx->pstate;
|
ams_ctx.pstate = ctx->pstate;
|
||||||
ams_ctx.afsr0 = ctx->afsr0;
|
ams_ctx.afsr0 = ctx->afsr0;
|
||||||
ams_ctx.afsr1 = ctx->afsr1;
|
ams_ctx.afsr1 = (static_cast<u64>(::ams::exosphere::GetVersion(ATMOSPHERE_RELEASE_VERSION)) << 32) | static_cast<u64>(hos::GetVersion());
|
||||||
|
if (svc::IsKernelMesosphere()) {
|
||||||
|
ams_ctx.afsr1 |= (static_cast<u64>('M') << (BITSIZEOF(u64) - BITSIZEOF(u8)));
|
||||||
|
}
|
||||||
ams_ctx.far = ctx->far.x;
|
ams_ctx.far = ctx->far.x;
|
||||||
ams_ctx.report_identifier = armGetSystemTick();
|
ams_ctx.report_identifier = armGetSystemTick();
|
||||||
|
|
||||||
|
|||||||
@@ -167,20 +167,19 @@ namespace ams::boot2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetGpioPadLow(GpioPadName pad) {
|
bool GetGpioPadLow(DeviceCode device_code) {
|
||||||
GpioPadSession button;
|
gpio::GpioPadSession button;
|
||||||
if (R_FAILED(gpioOpenSession(&button, pad))) {
|
if (R_FAILED(gpio::OpenSession(std::addressof(button), device_code))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure we close even on early return. */
|
/* Ensure we close even on early return. */
|
||||||
ON_SCOPE_EXIT { gpioPadClose(&button); };
|
ON_SCOPE_EXIT { gpio::CloseSession(std::addressof(button)); };
|
||||||
|
|
||||||
/* Set direction input. */
|
/* Set direction input. */
|
||||||
gpioPadSetDirection(&button, GpioDirection_Input);
|
gpio::SetDirection(std::addressof(button), gpio::Direction_Input);
|
||||||
|
|
||||||
GpioValue val;
|
return gpio::GetValue(std::addressof(button)) == gpio::GpioValue_Low;
|
||||||
return R_SUCCEEDED(gpioPadGetValue(&button, &val)) && val == GpioValue_Low;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsForceMaintenance() {
|
bool IsForceMaintenance() {
|
||||||
@@ -197,7 +196,7 @@ namespace ams::boot2 {
|
|||||||
|
|
||||||
/* Contact GPIO, read plus/minus buttons. */
|
/* Contact GPIO, read plus/minus buttons. */
|
||||||
{
|
{
|
||||||
return GetGpioPadLow(GpioPadName_ButtonVolUp) && GetGpioPadLow(GpioPadName_ButtonVolDown);
|
return GetGpioPadLow(gpio::DeviceCode_ButtonVolUp) && GetGpioPadLow(gpio::DeviceCode_ButtonVolDn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +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 <stratosphere.hpp>
|
|
||||||
|
|
||||||
namespace ams::dd {
|
|
||||||
|
|
||||||
uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size) {
|
|
||||||
u64 virtual_addr;
|
|
||||||
const u64 aligned_addr = util::AlignDown(phys_addr, os::MemoryPageSize);
|
|
||||||
const size_t offset = phys_addr - aligned_addr;
|
|
||||||
const u64 aligned_size = size + offset;
|
|
||||||
if (hos::GetVersion() >= hos::Version_10_0_0) {
|
|
||||||
u64 region_size;
|
|
||||||
R_TRY_CATCH(svcQueryIoMapping(&virtual_addr, ®ion_size, aligned_addr, aligned_size)) {
|
|
||||||
/* Official software handles this by returning 0. */
|
|
||||||
R_CATCH(svc::ResultNotFound) { return 0; }
|
|
||||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
|
||||||
AMS_ASSERT(region_size >= aligned_size);
|
|
||||||
} else {
|
|
||||||
R_TRY_CATCH(svcLegacyQueryIoMapping(&virtual_addr, aligned_addr, aligned_size)) {
|
|
||||||
/* Official software handles this by returning 0. */
|
|
||||||
R_CATCH(svc::ResultNotFound) { return 0; }
|
|
||||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<uintptr_t>(virtual_addr + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
inline u32 ReadWriteRegisterImpl(uintptr_t phys_addr, u32 value, u32 mask) {
|
|
||||||
u32 out_value;
|
|
||||||
R_ABORT_UNLESS(svcReadWriteRegister(&out_value, phys_addr, mask, value));
|
|
||||||
return out_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 ReadRegister(uintptr_t phys_addr) {
|
|
||||||
return ReadWriteRegisterImpl(phys_addr, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteRegister(uintptr_t phys_addr, u32 value) {
|
|
||||||
ReadWriteRegisterImpl(phys_addr, value, ~u32());
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask) {
|
|
||||||
return ReadWriteRegisterImpl(phys_addr, value, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,7 @@ namespace ams::erpt::srv {
|
|||||||
attachment_id.uuid.ToString(uuid_str, sizeof(uuid_str));
|
attachment_id.uuid.ToString(uuid_str, sizeof(uuid_str));
|
||||||
|
|
||||||
AttachmentFileName attachment_name;
|
AttachmentFileName attachment_name;
|
||||||
std::snprintf(attachment_name.name, sizeof(attachment_name.name), "%s/%s.att", ReportStoragePath, uuid_str);
|
std::snprintf(attachment_name.name, sizeof(attachment_name.name), "%s:/%s.att", ReportStoragePath, uuid_str);
|
||||||
return attachment_name;
|
return attachment_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,15 +20,15 @@ namespace ams::fs {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Result OpenCodeFileSystemImpl(CodeInfo *out_code_info, std::unique_ptr<fsa::IFileSystem> *out, const char *path, ncm::ProgramId program_id) {
|
Result OpenCodeFileSystemImpl(CodeVerificationData *out_verification_data, std::unique_ptr<fsa::IFileSystem> *out, const char *path, ncm::ProgramId program_id) {
|
||||||
/* Print a path suitable for the remote service. */
|
/* Print a path suitable for the remote service. */
|
||||||
fssrv::sf::Path sf_path;
|
fssrv::sf::Path sf_path;
|
||||||
R_TRY(FspPathPrintf(std::addressof(sf_path), "%s", path));
|
R_TRY(FspPathPrintf(std::addressof(sf_path), "%s", path));
|
||||||
|
|
||||||
/* Open the filesystem using libnx bindings. */
|
/* Open the filesystem using libnx bindings. */
|
||||||
static_assert(sizeof(CodeInfo) == sizeof(::FsCodeInfo));
|
static_assert(sizeof(CodeVerificationData) == sizeof(::FsCodeInfo));
|
||||||
::FsFileSystem fs;
|
::FsFileSystem fs;
|
||||||
R_TRY(fsldrOpenCodeFileSystem(reinterpret_cast<::FsCodeInfo *>(out_code_info), program_id.value, sf_path.str, std::addressof(fs)));
|
R_TRY(fsldrOpenCodeFileSystem(reinterpret_cast<::FsCodeInfo *>(out_verification_data), program_id.value, sf_path.str, std::addressof(fs)));
|
||||||
|
|
||||||
/* Allocate a new filesystem wrapper. */
|
/* Allocate a new filesystem wrapper. */
|
||||||
auto fsa = std::make_unique<RemoteFileSystem>(fs);
|
auto fsa = std::make_unique<RemoteFileSystem>(fs);
|
||||||
@@ -62,12 +62,12 @@ namespace ams::fs {
|
|||||||
return OpenPackageFileSystemImpl(out, sf_path.str);
|
return OpenPackageFileSystemImpl(out, sf_path.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpenSdCardCodeOrCodeFileSystemImpl(CodeInfo *out_code_info, std::unique_ptr<fsa::IFileSystem> *out, const char *path, ncm::ProgramId program_id) {
|
Result OpenSdCardCodeOrCodeFileSystemImpl(CodeVerificationData *out_verification_data, std::unique_ptr<fsa::IFileSystem> *out, const char *path, ncm::ProgramId program_id) {
|
||||||
/* If we can open an sd card code fs, use it. */
|
/* If we can open an sd card code fs, use it. */
|
||||||
R_SUCCEED_IF(R_SUCCEEDED(OpenSdCardCodeFileSystemImpl(out, program_id)));
|
R_SUCCEED_IF(R_SUCCEEDED(OpenSdCardCodeFileSystemImpl(out, program_id)));
|
||||||
|
|
||||||
/* Otherwise, fall back to a normal code fs. */
|
/* Otherwise, fall back to a normal code fs. */
|
||||||
return OpenCodeFileSystemImpl(out_code_info, out, path, program_id);
|
return OpenCodeFileSystemImpl(out_verification_data, out, path, program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpenHblCodeFileSystemImpl(std::unique_ptr<fsa::IFileSystem> *out) {
|
Result OpenHblCodeFileSystemImpl(std::unique_ptr<fsa::IFileSystem> *out) {
|
||||||
@@ -227,7 +227,7 @@ namespace ams::fs {
|
|||||||
public:
|
public:
|
||||||
AtmosphereCodeFileSystem() : initialized(false) { /* ... */ }
|
AtmosphereCodeFileSystem() : initialized(false) { /* ... */ }
|
||||||
|
|
||||||
Result Initialize(CodeInfo *out_code_info, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific) {
|
Result Initialize(CodeVerificationData *out_verification_data, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific) {
|
||||||
AMS_ABORT_UNLESS(!this->initialized);
|
AMS_ABORT_UNLESS(!this->initialized);
|
||||||
|
|
||||||
/* If we're hbl, we need to open a hbl fs. */
|
/* If we're hbl, we need to open a hbl fs. */
|
||||||
@@ -239,7 +239,7 @@ namespace ams::fs {
|
|||||||
|
|
||||||
/* Open the code filesystem. */
|
/* Open the code filesystem. */
|
||||||
std::unique_ptr<fsa::IFileSystem> fsa;
|
std::unique_ptr<fsa::IFileSystem> fsa;
|
||||||
R_TRY(OpenSdCardCodeOrCodeFileSystemImpl(out_code_info, std::addressof(fsa), path, program_id));
|
R_TRY(OpenSdCardCodeOrCodeFileSystemImpl(out_verification_data, std::addressof(fsa), path, program_id));
|
||||||
this->code_fs.emplace(std::move(fsa), program_id, is_specific);
|
this->code_fs.emplace(std::move(fsa), program_id, is_specific);
|
||||||
|
|
||||||
this->program_id = program_id;
|
this->program_id = program_id;
|
||||||
@@ -275,7 +275,7 @@ namespace ams::fs {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MountCode(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id) {
|
Result MountCode(CodeVerificationData *out, const char *name, const char *path, ncm::ProgramId program_id) {
|
||||||
/* Clear the output. */
|
/* Clear the output. */
|
||||||
std::memset(out, 0, sizeof(*out));
|
std::memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ namespace ams::fs {
|
|||||||
return fsa::Register(name, std::move(fsa));
|
return fsa::Register(name, std::move(fsa));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MountCodeForAtmosphereWithRedirection(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific) {
|
Result MountCodeForAtmosphereWithRedirection(CodeVerificationData *out, const char *name, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific) {
|
||||||
/* Clear the output. */
|
/* Clear the output. */
|
||||||
std::memset(out, 0, sizeof(*out));
|
std::memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ namespace ams::fs {
|
|||||||
return fsa::Register(name, std::move(ams_code_fs));
|
return fsa::Register(name, std::move(ams_code_fs));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MountCodeForAtmosphere(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id) {
|
Result MountCodeForAtmosphere(CodeVerificationData *out, const char *name, const char *path, ncm::ProgramId program_id) {
|
||||||
/* Clear the output. */
|
/* Clear the output. */
|
||||||
std::memset(out, 0, sizeof(*out));
|
std::memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
|
|||||||
197
libraries/libstratosphere/source/gpio/gpio_client_api.cpp
Normal file
197
libraries/libstratosphere/source/gpio/gpio_client_api.cpp
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* 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 <stratosphere.hpp>
|
||||||
|
#include "gpio_remote_manager_impl.hpp"
|
||||||
|
|
||||||
|
namespace ams::gpio {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/* TODO: Manager object. */
|
||||||
|
constinit os::SdkMutex g_init_mutex;
|
||||||
|
constinit int g_initialize_count = 0;
|
||||||
|
std::shared_ptr<sf::IManager> g_manager;
|
||||||
|
|
||||||
|
using InternalSession = std::shared_ptr<gpio::sf::IPadSession>;
|
||||||
|
|
||||||
|
InternalSession &GetInterface(GpioPadSession *session) {
|
||||||
|
AMS_ASSERT(session->_session != nullptr);
|
||||||
|
return *static_cast<InternalSession *>(session->_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize() {
|
||||||
|
std::scoped_lock lk(g_init_mutex);
|
||||||
|
|
||||||
|
if ((g_initialize_count++) == 0) {
|
||||||
|
R_ABORT_UNLESS(::gpioInitialize());
|
||||||
|
g_manager = ams::sf::MakeShared<sf::IManager, RemoteManagerImpl>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finalize() {
|
||||||
|
std::scoped_lock lk(g_init_mutex);
|
||||||
|
|
||||||
|
AMS_ASSERT(g_initialize_count > 0);
|
||||||
|
|
||||||
|
if ((--g_initialize_count) == 0) {
|
||||||
|
g_manager.reset();
|
||||||
|
::gpioExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result OpenSession(GpioPadSession *out_session, ams::DeviceCode device_code) {
|
||||||
|
/* Allocate the session. */
|
||||||
|
InternalSession *internal_session = new (std::nothrow) InternalSession;
|
||||||
|
AMS_ABORT_UNLESS(internal_session != nullptr);
|
||||||
|
auto session_guard = SCOPE_GUARD { delete internal_session; };
|
||||||
|
|
||||||
|
/* Get the session. */
|
||||||
|
{
|
||||||
|
ams::sf::cmif::ServiceObjectHolder object_holder;
|
||||||
|
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||||
|
R_TRY(g_manager->OpenSession2(std::addressof(object_holder), device_code, ddsf::AccessMode_ReadWrite));
|
||||||
|
} else {
|
||||||
|
R_TRY(g_manager->OpenSession(std::addressof(object_holder), ConvertToGpioPadName(device_code)));
|
||||||
|
}
|
||||||
|
*internal_session = object_holder.GetServiceObject<sf::IPadSession>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set output. */
|
||||||
|
out_session->_session = internal_session;
|
||||||
|
out_session->_event = nullptr;
|
||||||
|
|
||||||
|
/* We succeeded. */
|
||||||
|
session_guard.Cancel();
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseSession(GpioPadSession *session) {
|
||||||
|
AMS_ASSERT(session != nullptr);
|
||||||
|
|
||||||
|
/* Unbind the interrupt, if it's still bound. */
|
||||||
|
if (session->_event != nullptr) {
|
||||||
|
gpio::UnbindInterrupt(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the session. */
|
||||||
|
delete std::addressof(GetInterface(session));
|
||||||
|
session->_session = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IsWakeEventActive(bool *out_is_active, ams::DeviceCode device_code) {
|
||||||
|
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||||
|
R_TRY(g_manager->IsWakeEventActive2(out_is_active, device_code));
|
||||||
|
} else {
|
||||||
|
R_TRY(g_manager->IsWakeEventActive(out_is_active, ConvertToGpioPadName(device_code)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Direction GetDirection(GpioPadSession *session) {
|
||||||
|
Direction out;
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->GetDirection(std::addressof(out)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDirection(GpioPadSession *session, Direction direction) {
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->SetDirection(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
GpioValue GetValue(GpioPadSession *session) {
|
||||||
|
GpioValue out;
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->GetValue(std::addressof(out)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetValue(GpioPadSession *session, GpioValue value) {
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->SetValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
InterruptMode GetInterruptMode(GpioPadSession *session) {
|
||||||
|
InterruptMode out;
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->GetInterruptMode(std::addressof(out)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetInterruptMode(GpioPadSession *session, InterruptMode mode) {
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->SetInterruptMode(mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetInterruptEnable(GpioPadSession *session) {
|
||||||
|
bool out;
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->GetInterruptEnable(std::addressof(out)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetInterruptEnable(GpioPadSession *session, bool en) {
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->SetInterruptEnable(en));
|
||||||
|
}
|
||||||
|
|
||||||
|
InterruptStatus GetInterruptStatus(GpioPadSession *session) {
|
||||||
|
InterruptStatus out;
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->GetInterruptStatus(std::addressof(out)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearInterruptStatus(GpioPadSession *session) {
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->ClearInterruptStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetDebounceTime(GpioPadSession *session) {
|
||||||
|
int out;
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->GetDebounceTime(std::addressof(out)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDebounceTime(GpioPadSession *session, int ms) {
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->SetDebounceTime(ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetDebounceEnabled(GpioPadSession *session) {
|
||||||
|
bool out;
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->GetDebounceEnabled(std::addressof(out)));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDebounceEnabled(GpioPadSession *session, bool en) {
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->SetDebounceEnabled(en));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result BindInterrupt(os::SystemEventType *event, GpioPadSession *session) {
|
||||||
|
AMS_ASSERT(session->_event == nullptr);
|
||||||
|
|
||||||
|
ams::sf::CopyHandle handle;
|
||||||
|
R_TRY(GetInterface(session)->BindInterrupt(std::addressof(handle)));
|
||||||
|
|
||||||
|
os::AttachReadableHandleToSystemEvent(event, handle.GetValue(), true, os::EventClearMode_ManualClear);
|
||||||
|
|
||||||
|
session->_event = event;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnbindInterrupt(GpioPadSession *session) {
|
||||||
|
AMS_ASSERT(session->_event != nullptr);
|
||||||
|
|
||||||
|
R_ABORT_UNLESS(GetInterface(session)->UnbindInterrupt());
|
||||||
|
|
||||||
|
os::DestroySystemEvent(session->_event);
|
||||||
|
session->_event = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "gpio_remote_pad_session_impl.hpp"
|
||||||
|
|
||||||
|
namespace ams::gpio {
|
||||||
|
|
||||||
|
class RemoteManagerImpl {
|
||||||
|
public:
|
||||||
|
RemoteManagerImpl() { /* ... */ }
|
||||||
|
|
||||||
|
~RemoteManagerImpl() { /* ... */ }
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
Result OpenSessionForDev(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, s32 pad_descriptor) {
|
||||||
|
/* TODO: libnx bindings */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result OpenSession(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) {
|
||||||
|
::GpioPadSession p;
|
||||||
|
R_TRY(::gpioOpenSession(std::addressof(p), static_cast<::GpioPadName>(static_cast<u32>(pad_name))));
|
||||||
|
|
||||||
|
out.SetValue(ams::sf::MakeShared<gpio::sf::IPadSession, RemotePadSessionImpl>(p));
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result OpenSessionForTest(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name) {
|
||||||
|
/* TODO: libnx bindings */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IsWakeEventActive(ams::sf::Out<bool> out, gpio::GpioPadName pad_name) {
|
||||||
|
return ::gpioIsWakeEventActive2(out.GetPointer(), static_cast<::GpioPadName>(static_cast<u32>(pad_name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetWakeEventActiveFlagSet(ams::sf::Out<gpio::WakeBitFlag> out) {
|
||||||
|
/* TODO: libnx bindings */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetWakeEventActiveFlagSetForDebug(gpio::GpioPadName pad_name, bool is_enabled) {
|
||||||
|
/* TODO: libnx bindings */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetWakePinDebugMode(s32 mode) {
|
||||||
|
/* TODO: libnx bindings */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result OpenSession2(ams::sf::Out<std::shared_ptr<gpio::sf::IPadSession>> out, DeviceCode device_code, ddsf::AccessMode access_mode) {
|
||||||
|
::GpioPadSession p;
|
||||||
|
R_TRY(::gpioOpenSession2(std::addressof(p), device_code.GetInternalValue(), access_mode));
|
||||||
|
|
||||||
|
out.SetValue(ams::sf::MakeShared<gpio::sf::IPadSession, RemotePadSessionImpl>(p));
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IsWakeEventActive2(ams::sf::Out<bool> out, DeviceCode device_code) {
|
||||||
|
return ::gpioIsWakeEventActive2(out.GetPointer(), device_code.GetInternalValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetWakeEventActiveFlagSetForDebug2(DeviceCode device_code, bool is_enabled) {
|
||||||
|
/* TODO: libnx bindings */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetRetryValues(u32 arg0, u32 arg1) {
|
||||||
|
/* TODO: libnx bindings */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
static_assert(gpio::sf::IsIManager<RemoteManagerImpl>);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::gpio {
|
||||||
|
|
||||||
|
class RemotePadSessionImpl {
|
||||||
|
private:
|
||||||
|
::GpioPadSession srv;
|
||||||
|
public:
|
||||||
|
RemotePadSessionImpl(::GpioPadSession &p) : srv(p) { /* ... */ }
|
||||||
|
|
||||||
|
~RemotePadSessionImpl() { ::gpioPadClose(std::addressof(this->srv)); }
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
Result SetDirection(gpio::Direction direction) {
|
||||||
|
return ::gpioPadSetDirection(std::addressof(this->srv), static_cast<::GpioDirection>(static_cast<u32>(direction)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDirection(ams::sf::Out<gpio::Direction> out) {
|
||||||
|
static_assert(sizeof(gpio::Direction) == sizeof(::GpioDirection));
|
||||||
|
return ::gpioPadGetDirection(std::addressof(this->srv), reinterpret_cast<::GpioDirection *>(out.GetPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetInterruptMode(gpio::InterruptMode mode) {
|
||||||
|
return ::gpioPadSetInterruptMode(std::addressof(this->srv), static_cast<::GpioInterruptMode>(static_cast<u32>(mode)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetInterruptMode(ams::sf::Out<gpio::InterruptMode> out) {
|
||||||
|
static_assert(sizeof(gpio::InterruptMode) == sizeof(::GpioInterruptMode));
|
||||||
|
return ::gpioPadGetInterruptMode(std::addressof(this->srv), reinterpret_cast<::GpioInterruptMode *>(out.GetPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetInterruptEnable(bool enable) {
|
||||||
|
return ::gpioPadSetInterruptEnable(std::addressof(this->srv), enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetInterruptEnable(ams::sf::Out<bool> out) {
|
||||||
|
return ::gpioPadGetInterruptEnable(std::addressof(this->srv), out.GetPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetInterruptStatus(ams::sf::Out<gpio::InterruptStatus> out) {
|
||||||
|
static_assert(sizeof(gpio::InterruptStatus) == sizeof(::GpioInterruptStatus));
|
||||||
|
return ::gpioPadGetInterruptStatus(std::addressof(this->srv), reinterpret_cast<::GpioInterruptStatus *>(out.GetPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ClearInterruptStatus() {
|
||||||
|
return ::gpioPadClearInterruptStatus(std::addressof(this->srv));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetValue(gpio::GpioValue value) {
|
||||||
|
return ::gpioPadSetValue(std::addressof(this->srv), static_cast<::GpioValue>(static_cast<u32>(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetValue(ams::sf::Out<gpio::GpioValue> out) {
|
||||||
|
static_assert(sizeof(gpio::GpioValue) == sizeof(::GpioValue));
|
||||||
|
return ::gpioPadGetValue(std::addressof(this->srv), reinterpret_cast<::GpioValue *>(out.GetPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result BindInterrupt(ams::sf::OutCopyHandle out) {
|
||||||
|
::Event ev;
|
||||||
|
R_TRY(::gpioPadBindInterrupt(std::addressof(this->srv), std::addressof(ev)));
|
||||||
|
out.SetValue(ev.revent);
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result UnbindInterrupt() {
|
||||||
|
return ::gpioPadUnbindInterrupt(std::addressof(this->srv));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetDebounceEnabled(bool enable) {
|
||||||
|
return ::gpioPadSetDebounceEnabled(std::addressof(this->srv), enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDebounceEnabled(ams::sf::Out<bool> out) {
|
||||||
|
return ::gpioPadGetDebounceEnabled(std::addressof(this->srv), out.GetPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetDebounceTime(s32 ms) {
|
||||||
|
return ::gpioPadSetDebounceTime(std::addressof(this->srv), ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDebounceTime(ams::sf::Out<s32> out) {
|
||||||
|
return ::gpioPadGetDebounceTime(std::addressof(this->srv), out.GetPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetValueForSleepState(gpio::GpioValue value) {
|
||||||
|
/* TODO: libnx bindings. */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetValueForSleepState(ams::sf::Out<gpio::GpioValue> out) {
|
||||||
|
/* TODO: libnx bindings. */
|
||||||
|
AMS_ABORT();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(gpio::sf::IsIPadSession<RemotePadSessionImpl>);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,12 +17,12 @@
|
|||||||
|
|
||||||
namespace ams::spl::smc {
|
namespace ams::spl::smc {
|
||||||
|
|
||||||
Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords) {
|
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords) {
|
||||||
SecmonArgs args;
|
SecmonArgs args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::SetConfig);
|
args.X[0] = static_cast<u64>(FunctionId::SetConfig);
|
||||||
args.X[1] = static_cast<u64>(which);
|
args.X[1] = static_cast<u64>(which);
|
||||||
args.X[2] = 0;
|
args.X[2] = reinterpret_cast<u64>(address);
|
||||||
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
||||||
args.X[3 + i] = value[i];
|
args.X[3 + i] = value[i];
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user