Merge pull request #1 from Atmosphere-NX/master

bump
This commit is contained in:
2g4y1 2019-03-05 13:44:49 +01:00 committed by GitHub
commit 85aacbb231
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
867 changed files with 128806 additions and 27997 deletions

56
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,56 @@
---
name: Bug Report
about: Something doesn't work correctly in Atmosphère.
#assignees:
---
## Bug Report
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ Lines between [ ] (square brackets) should be removed before posting. ]</br>
[ * ]</br>
[ Note: If the bug or crash you encountered is related to; ]</br>
[ - software used to make "backups", ]</br>
[ - software explicitly distributed for piracy, etc ]</br>
[ then contributors will not provide support for your issue and your issue will be closed. ]</br>
### What's the issue you encountered?
[ Describe the issue in detail and what you were doing beforehand. ]</br>
[ Did you make any changes related to Atmosphère itself? ]</br>
[ If so, make sure to include details relating to what exactly you changed. ]</br>
### How can the issue be reproduced?
[ * ]</br>
[ Include a detailed step by step process for recreating your issue. ]</br>
### Crash Report
[ Crash reports can be found under ``/atmosphere/crash_reports``. ]</br>
[ If your issue caused Atmosphère to crash, include the crash report(s) by creating a [gist](https://gist.github.com/) and pasting the link here. ]</br>
[ If you don't include a crash report in instances of crash related issues, we will ask you one to provide one. ]</br>
### System Firmware Version
X.X.X</br>
[ Replace X's with system firmware version at time of crash. ]</br>
[ You can find your firmware version in the Settings -> System, under "System Update". ]</br>
[ If it says "Update Pending", you can clear the pending update by rebooting to Maintenance Mode. ]</br>
### Environment?
- What bootloader (fusèe, hekate, etc) was Atmosphère launched by:
- Official release or unofficial build:
- [ Offical release version x.x.x (or) unofficial build ]
- [ If using an unofficial build, include details on where/how you acquired the build. ]
- [ Ex: Self-compilation ]
- [ Ex: Kosmos' distribution of Atmosphère ]
- Do you have additional kips or sysmodules you're loading:
- Homebrew software installed: [ * ]
### Additional context?
- Additional info about your environment:
- [ Any other information relevant to your issue. ]

View File

@ -0,0 +1,48 @@
---
name: Feature Request
about: Suggest a new feature for Atmosphère.
#assignees:
---
## Feature Request
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br>
[ Lines between [ ] (square brackets) are to be removed before posting. ]
[ Please search for existing [feature requests](https://github.com/Atmosphere-NX/Atmosphere/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22features%2Ffeature-request%22) before you make your own request. ]</br>
[ Duplicate requests will be marked as such and you will be referred to the original request. ]
### What feature are you suggesting?
#### Overview:
- [ Include the basic, high-level concepts for this feature here. ]</br>
#### Smaller Details:
- [ These may include specific methods of implementation etc. ]</br>
#### Nature of Request:
[ Remove all that do not apply to your request. ]
- Addition
- [ Ex: Addition of certain original features or features from other community projects. ]
- [ If you are suggesting porting features or including features from other projects, include what license they are distributed under and what, if any libraries those project use. ]
- Change
- Removal
- [Ex: Removal of certain features or implementation due to a specific issue/bug or because of low quality code, etc.]
### What component do you feel this would best fit within?
- [Fusée](https://github.com/Atmosphere-NX/Atmosphere#components)</br>
- Atmosphère's custom bootloader.</br>
- [Exosphère](https://github.com/Atmosphere-NX/Atmosphere#components)</br>
- Fully-featured custom secure monitor.</br>
- [Stratosphère](https://github.com/Atmosphere-NX/Atmosphere#components)</br>
- Custom system modules.</br>
- [**Thermosphère**](https://github.com/Atmosphere-NX/Atmosphere#components)</br>
- Atmosphère's emuNAND implementation.</br>
- [**Troposphère**](https://github.com/Atmosphere-NX/Atmosphere#components)</br>
- Application-level patches to the Horizon OS.</br>
[ Note: **Bolded components are not implemented** or are still at the prototyping phase. ]
### Why would this feature be useful?
[ If this is a feature for an end-user, how does it benefit the end-user? ]</br>
[ If this feature is for developers, what does it add to Atmosphère that did not already exist? ]</br>

7
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@ -0,0 +1,7 @@
---
name: Question
about: Please ask questions in the ReSwitched discord, instead of making issues.
---
We would like to use GitHub to keep track of problems/feature requests.
If you have a question, please join the ReSwitched discord for help.
- Discord link: https://discordapp.com/invite/DThbZ7z

19
.gitignore vendored
View File

@ -41,7 +41,9 @@
*.nso
*.nro
*.nacp
*.npdm
*.pfs0
*.nsp
*.kip
# Debug files
@ -59,10 +61,27 @@ Module.symvers
Mkfile.old
dkms.conf
# Distribution files
*.tgz
*.zip
# IDA binaries
*.id0
*.id1
*.id2
*.idb
*.nam
*.til
# KEYS file for sept-secondary.
*.pyc
sept/sept-secondary/KEYS.py
.**/
# NOTE: make sure to make exceptions to this pattern when needed!
*.bin
*.enc
**/out
**/build

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "common/include/boost"]
path = common/include/boost
url = https://github.com/Atmosphere-NX/ext-boost.git
[submodule "stratosphere/libstratosphere"]
path = stratosphere/libstratosphere
url = https://github.com/Atmosphere-NX/libstratosphere.git

View File

@ -1,10 +1,81 @@
TOPTARGETS := all clean
TOPTARGETS := all clean dist
AMSBRANCH := $(shell git symbolic-ref --short HEAD)
AMSHASH := $(shell git rev-parse --short HEAD)
AMSREV := $(AMSBRANCH)-$(AMSHASH)
all: fusee
fusee:
ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
AMSREV := $(AMSREV)-dirty
endif
COMPONENTS := fusee stratosphere exosphere thermosphere troposphere
all: $(COMPONENTS)
thermosphere:
$(MAKE) -C thermosphere all
exosphere: thermosphere
$(MAKE) -C exosphere all
stratosphere: exosphere
$(MAKE) -C stratosphere all
troposphere: stratosphere
$(MAKE) -C troposphere all
sept: exosphere
$(MAKE) -C sept all
fusee: exosphere stratosphere sept
$(MAKE) -C $@ all
clean:
$(MAKE) -C fusee clean
rm -rf out
.PHONY: $(TOPTARGETS) fusee
dist: all
$(eval MAJORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MAJOR\b' common/include/atmosphere/version.h \
| tr -s [:blank:] \
| cut -d' ' -f3))
$(eval MINORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MINOR\b' common/include/atmosphere/version.h \
| tr -s [:blank:] \
| cut -d' ' -f3))
$(eval MICROVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MICRO\b' common/include/atmosphere/version.h \
| tr -s [:blank:] \
| cut -d' ' -f3))
$(eval AMSVER = $(MAJORVER).$(MINORVER).$(MICROVER)-$(AMSREV))
rm -rf atmosphere-$(AMSVER)
rm -rf out
mkdir atmosphere-$(AMSVER)
mkdir atmosphere-$(AMSVER)/atmosphere
mkdir atmosphere-$(AMSVER)/sept
mkdir atmosphere-$(AMSVER)/switch
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/010000000000000D
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
cp 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.enc atmosphere-$(AMSVER)/sept/sept-secondary.enc
cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini
cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini
cp common/defaults/system_settings.ini atmosphere-$(AMSVER)/atmosphere/system_settings.ini
cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches
cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp
cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034/exefs.nsp
cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags
touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags/boot2.flag
cp stratosphere/dmnt/dmnt.nsp atmosphere-$(AMSVER)/atmosphere/titles/010000000000000D/exefs.nsp
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
rm -r atmosphere-$(AMSVER)
mkdir out
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
.PHONY: $(TOPTARGETS) $(COMPONENTS)

View File

@ -3,6 +3,7 @@
=====
![License](https://img.shields.io/badge/License-GPLv2-blue.svg)
[![Chat on Discord](https://camo.githubusercontent.com/b4175720ede4f2621aa066ffbabb70ae30044679/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636861742d446973636f72642d627269676874677265656e2e737667)](https://discordapp.com/invite/ZdqEhed)
Atmosphère is a work-in-progress customized firmware for the Nintendo Switch.
@ -12,6 +13,7 @@ Components
Atmosphère consists of multiple components, each of which replaces/modifies a different component of the system:
* Fusée: First-stage Loader, responsible for loading and validating stage 2 (custom TrustZone) plus package2 (Kernel/FIRM sysmodules), and patching them as needed. This replaces all functionality normally in Package1loader/NX Bootloader.
* Sept: Payload used to enable support for runtime key derivation on 7.0.0.
* Exosphère: Customized TrustZone, to run a customized Secure Monitor
* Thermosphère: EL2 EmuNAND support, i.e. backing up and using virtualized/redirected NAND images
* Stratosphère: Custom Sysmodule(s), both Rosalina style to extend the kernel/provide new features, and of the loader reimplementation style to hook important system actions
@ -20,15 +22,17 @@ Atmosphère consists of multiple components, each of which replaces/modifies a d
Credits
=====
Atmosphère is currently being developed and maintained by __SciresM__, __TuxSH__ and __hexkyz__.<br>
Atmosphère is currently being developed and maintained by __SciresM__, __TuxSH__, __hexkyz__, and __fincs__.<br>
In no particular order, we credit the following for their invaluable contributions:
* __switchbrew__ for the [libnx](https://github.com/switchbrew/libnx) project and the extensive [documentation, research and tool development](http://switchbrew.org) pertaining to the Nintendo Switch.
* __devkitPro__ for the [devkitA64](https://devkitpro.org/) toolchain and libnx support.
* __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.tech/) pertaining to the Nintendo Switch.
* __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.team/) pertaining to the Nintendo Switch.
* __ChaN__ for the [FatFs](http://elm-chan.org/fsw/ff/00index_e.html) module.
* __Marcus Geelnard__ for the [bcl-1.2.0](https://sourceforge.net/projects/bcl/files/bcl/bcl-1.2.0) library.
* __naehrwert__ and __st4rk__ for the original [hekate](https://github.com/nwert/hekate) project and its hwinit code base.
* __CTCaer__ for the continued [hekate](https://github.com/CTCaer/hekate) project's fork and the [minerva_tc](https://github.com/CTCaer/minerva_tc) project.
* __Riley__ for suggesting "Atmosphere" as a Horizon OS reimplementation+customization project name.
* __naehrwert__ for the [hekate](https://github.com/nwert/hekate) project and its hwinit code base.
* __hedgeberg__ for research and hardware testing.
* __lioncash__ for code cleanup and general improvements.
* __jaames__ for designing and providing Atmosphère's graphical resources.

14
common/defaults/BCT.ini Normal file
View File

@ -0,0 +1,14 @@
BCT0
[stage1]
stage2_path = atmosphere/fusee-secondary.bin
stage2_addr = 0xF0000000
stage2_entrypoint = 0xF0000000
[exosphere]
; Note: Disabling debugmode will cause parts of ams.tma to not work, in the future.
debugmode = 1
debugmode_user = 0
[stratosphere]
; To force-enable nogc, add nogc = 1
; To force-disable nogc, add nogc = 0

View File

@ -0,0 +1,8 @@
[hbl_config]
title_id=010000000000100D
path=atmosphere/hbl.nsp
override_key=!R
[default_config]
override_key=!L
cheat_enable_key=!L

View File

@ -0,0 +1,11 @@
; Disable uploading error reports to Nintendo
[eupld]
upload_enabled = u8!0x0
; Enable USB 3.0 superspeed for homebrew
[usb]
usb30_force_enabled = u8!0x0
; Atmosphere custom settings
[atmosphere]
; Make the power menu's "reboot" button reboot to payload.
; Set to "normal" for normal reboot, "rcm" for rcm reboot.
power_menu_reboot_function = str!payload

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef ATMOSPHERE_H
#define ATMOSPHERE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "atmosphere/version.h"
#include "atmosphere/target_fw.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef ATMOSPHERE_TARGET_FIRMWARE_H
#define ATMOSPHERE_TARGET_FIRMWARE_H
#define ATMOSPHERE_TARGET_FIRMWARE_100 1
#define ATMOSPHERE_TARGET_FIRMWARE_200 2
#define ATMOSPHERE_TARGET_FIRMWARE_300 3
#define ATMOSPHERE_TARGET_FIRMWARE_400 4
#define ATMOSPHERE_TARGET_FIRMWARE_500 5
#define ATMOSPHERE_TARGET_FIRMWARE_600 6
#define ATMOSPHERE_TARGET_FIRMWARE_620 7
#define ATMOSPHERE_TARGET_FIRMWARE_700 8
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_700
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_700
/* TODO: What should this be, for release? */
#define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT
#endif

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef ATMOSPHERE_VERSION_H
#define ATMOSPHERE_VERSION_H
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
#define ATMOSPHERE_RELEASE_VERSION_MINOR 8
#define ATMOSPHERE_RELEASE_VERSION_MICRO 4
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 7
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 1
#endif

1
common/include/boost Submodule

@ -0,0 +1 @@
Subproject commit fc6429e46398e16178b828a3a20e1bee9c56443d

6
docs/building.md Normal file
View File

@ -0,0 +1,6 @@
# Building Atmosphère
The process for building Atmosphère is similar to building Fusée Gelée payloads and other Switch apps.
In order to build Atmosphère you must have devkitARM and devkitA64 installed on your computer. You can find instructions on how to install and setup devkitARM and devkitA64 on various OSes [here](https://devkitpro.org/wiki/Getting_Started).
Once you have finished installing devkitARM and devkitA64, simply clone the Atmosphère repo, change to it and run `make`.

205
docs/changelog.md Normal file
View File

@ -0,0 +1,205 @@
# Changelog
## 0.8.4
+ Support for 7.0.0/7.0.1 was added.
+ This is facilitated through a new payload, `sept`, which can be signed, encrypted, and then loaded by Nintendo's TSEC firmware.
+ `sept` will derive the keys needed to boot new firmware, and then load `sept/payload.bin` off the SD card and jump to it.
+ Recognition of applications for override/mitm has been improved.
+ Nintendo's official Title ID range (`0x0100000000000000`-`0x01FFFFFFFFFFFFFF`) is now enforced.
+ A deadlock condition was fixed involving libstratosphere mitm sysmodules.
+ Kernel patches for JIT support were added (Thanks, @m4xw!).
+ These loosen restrictions on caller process in svcControlCodeMemory.
+ `set.mitm` and `fs.mitm` were merged into a single `ams_mitm` sysmodule.
+ This saves a process ID, allowing users to run one additional process up to the 0x40 process limit.
+ A `bpc.mitm` component was added, performing custom behavior on shutdown/reboot requests from `am` or applications.
+ Performing a reboot from the reboot menu now reboots to atmosphere. This can be configured via `system_settings.ini`.
+ Performing a shutdown from the reboot menu now works properly with AutoRCM, and does a real shutdown.
+ General system stability improvements to enhance the user's experience.
## 0.8.3
+ A custom warmboot firmware was implemented, which does not perform anti-downgrade fuse checks.
+ This fixes sleep mode when using a downgraded NAND.
+ This also removes Atmosphère's final dependency on Nintendo's encrypted PK11 binary; all components are now re-implemented.
+ The ExternalContentSource API was changed to not clear on failure.
+ Content override now supports an "app" setting, that causes all applications to be overridden with HBL instead of a specific title.
+ Note: because override keys are system-wide, using this setting will prevent using mods in games (as every game will be HBL).
+ A bug was fixed causing incorrect fatal-error output when svcBreak was called on 5.0.0+.
+ An extension was added to set.mitm to support customization of system settings.
+ These are controlled by `atmosphere/system_settings.ini`, see [here](https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/modules/set_mitm.md) for documentation.
+ An extension was added to sm, adding a new `sm:dmnt` service.
+ This can be used by a debug monitor in order to debug the registration state of various other services.
+ A bug was fixed in the MitM API that could sometimes cause a system hang during boot.
+ A change was made to the MitM API: in cases where sm would have returned 0xE15 when installing a mitm service, it now defers the result (following GetService semantics).
+ Support for booting into maintenance mode by holding +/- was added to PM.
+ An extension was added to exosphere, adding a custom SMC that allows for DMA to IRAM.
+ In addition, smcGetConfig was extended to reboot to a payload in IRAM at 0x40010000 when ConfigItem 65001 is set to 2.
+ Fatal will now use this to reboot to sdmc:/atmosphere/reboot_payload.bin if present, when a vol button is pressed.
+ An example homebrew ("reboot_to_payload") was also written and is now included with Atmosphère.
+ General system stability improvements to enhance the user's experience.
## 0.8.2
+ A number of bugs were fixed causing users to sometimes see `Key Derivation Failed!`.
+ KFUSE clock enable timings have been adjusted to allow time to stabilize before TSEC is granted access.
+ A race condition was fixed that could cause wrong key data to be used on 6.2.0
+ The TSEC firmware is now retried on failure, fixing a failure affecting ~1/50 boots on 6.2.0.
+ A bug was fixed causing some modules to not work on firmware 1.0.0.
+ A bug was fixed causing sleep mode to not work with debugmode enabled.
+ As a result, debugmode is now enabled in the default BCT.ini.
+ General system stability improvements to enhance the user's experience.
## 0.8.1
+ A bug was fixed causing users to see `Failed to enable SMMU!` if fusee had previously rebooted.
+ This message will still occur sporadically if fusee is not launched from coldboot, but it can never happen twice in a row.
+ A race condition was fixed in Atmosphere `bis_protect` functionality that could cause NS to be able to overwrite BCT public keys.
+ This sometimes broke AutoRCM protection, the current fix has been tested on hardware and verified to work.
+ Support was added for enabling `debugmode` based on the `exosphere` section of `BCT.ini`:
+ Setting `debugmode = 1` will cause exosphere to tell the kernel that debugmode is active.
+ Setting `debugmode_user = 1` will cause exosphere to tell userland that debugmode is active.
+ These are completely independent of one another, allowing fine control of system behavior.
+ Support was added for `nogc` functionality; thanks to @rajkosto for the patches.
+ By default, `nogc` patches will automatically apply if the user is booting into 4.0.0+ with fuses from <= 3.0.2.
+ Users can override this functionality via the `nogc` entry in the `stratosphere` section of `BCT.ini`:
+ Setting `nogc = 1` will force enable `nogc` patches.
+ Setting `nogc = 0` will force disable `nogc` patches.
+ If patches are enabled but not found for the booting system, a fatal error will be thrown.
+ This should prevent running FS without `nogc` patches after updating to an unsupported system version.
+ An extension was added to `exosphere` allowing userland applications to cause the system to reboot into RCM:
+ This is done by calling smcSetConfig(id=65001, value=<nonzero>); user homebrew can use splSetConfig for this.
+ On fatal error, the user can now choose to perform a standard reboot via the power button, or a reboot into RCM via either volume button.
+ A custom message was added to `fatal` for when an Atmosphère API version mismatch is detected (2495-1623).
+ General system stability improvements to enhance the user's experience.
## 0.8.0
+ A custom `fatal` system module was added.
+ This re-implements and extends Nintendo's fatal module, with the following features:
+ Atmosphère's `fatal` does not create error reports.
+ Atmosphère's `fatal` draws a custom error screen, showing registers and a backtrace.
+ Atmosphère's `fatal` attempts to gather debugging info for all crashes, and not just ones that include info.
+ Atmosphère's `fatal` will attempt saving reports to the SD, if a crash report was not generated by `creport`.
+ Title flag handling was changed to prevent folder clutter.
+ Instead of living in `atmosphere/titles/<tid>/%s.flag`, flags are now located in `atmosphere/titles/<tid>/flags/%s.flag`
+ The old format will continue to be supported for some time, but is deprecated.
+ Flags can now be applied to HBL by placing them at `atmosphere/flags/hbl_%s.flag`.
+ Changes were made to the mitm API, greatly improving caller semantics.
+ `sm` now informs mitm services of a new session's process id, enabling custom handling based on title id/process id.
+ smhax is no longer enabled, because it is no longer needed and breaks significant functionality.
+ Users with updated HBL/homebrew should see no observable differences due to this change.
+ Functionality was added implementing basic protections for NAND from userland homebrew:
+ BOOT0 now has write protection for the BCT public key and keyblob regions.
+ The `ns` sysmodule is no longer allowed to write the BCT public keys; all other processes can.
+ This should prevent system updates from removing AutoRCM.
+ No processes should be allowed to write to the keyblob region.
+ By default, BIS partitions other than BOOT0 are now read-only, and CAL0 is neither readable nor writable.
+ Adding a `bis_write` flag for a title will allow it to write to BIS.
+ Adding a `cal_read` flag for a title will allow it to read CAL0.
+ An automatic backup is now made of CAL0 on boot.
+ `fs.mitm` maintains a file handle to this backup, so userland software cannot read it.
+ To facilitate this, `fs.mitm` now mitms all sessions for non-system modules; content overriding has been made separate from service interception.
+ Please note: these protections are basic, and sufficiently malicious homebrew ++can defeat them++.
+ Please be careful to only run homebrew software from sources that you trust.
+ A bug involving HDCP titles crashing on newer firmwares was fixed.
+ Support was added for system version 6.2.0; our thanks to @motezazer for his invaluable help.
+ By default, new keys will automatically be derived without user input.
+ Support is also present for loading new keys from `atmosphere/prod.keys` or `atmosphere/dev.keys`
+ General system stability improvements to enhance the user's experience.
## 0.7.5
+ DRAM training was added to fusee-secondary, courtesy @hexkyz.
+ This greatly improves the speed of memory accesses during boot, resulting in a boot time that is ~200-400% faster.
+ creport has had its code region detection improved.
+ Instead of only checking one of the crashing thread's PC/LR for code region presence, creport now checks both + every address in the stacktrace. This is also now done for every thread.
+ This matches the improvement Nintendo added to official creport in 6.1.0.
+ The code region detection heuristic was further improved by checking whether an address points to .rodata or .rwdata, instead of just .text.
+ This means that a crash appears in a loaded NRO (or otherwise discontiguous) code region, creport will be able to detect all active code regions, and not just that one.
## 0.7.4
+ [libstratosphere](https://github.com/Atmosphere-NX/libstratosphere) has been completely refactored/rewritten, and split into its own, separate submodule.
+ While this is mostly "under the hood" for end-users, the refactor is faster (improving both boot-time and runtime performance), more accurate (many of the internal IPC structures are now bug-for-bug compatible with Nintendo's implementations), and significantly more stable (it fixes a large number of bugs present in the old library).
+ The refactored API is significantly cleaner and easier to write system module code for, which should improve/speed up development of stratosphere.
+ Developers looking to write their own custom system modules for the Switch can now easily include libstratosphere as a submodule in their projects.
+ Loader was extended to add a new generic way to redirect content (ExternalContentSources), courtesy @misson20000:
+ A new command was added to ldr:shel, taking in a tid to redirect and returning a session handle.
+ When the requested TID is loading, Loader will query the handle as though it were an IFileSystem.
+ This allows clients to generically define their own filesystems, and override content with them in loader.
+ fs.mitm has gotten several optimizations that should improve its performance and stability:
+ RomFS redirection now only occurs when there is content to redirect, even if the title is being mitm'd elsewhere.
+ A cache is now maintained of the active data storage, if any, for all opened title IDs. This means if two processes both try to open the same archive, fs.mitm won't duplicate any of its work.
+ RomFS metadata is now cached to the SD card on build instead of being persisted in memory -- this greatly reduces memory footprint and allows fs.mitm to redirect more titles simultaneously than before.
+ A number of bugs were fixed, including:
+ A resource leak was fixed in process creation. This fixes crashes that occur when a large number (>32) games have been launched since the last reboot.
+ fs.mitm no longer errors when receiving a zero-sized buffer. This fixes crashes in some games, including The Messenger.
+ Multi-threaded server semantics should no longer cause deadlocks in certain circumstances. This fixes crashes in some games, including NES Classics.
+ PM now only gives full FS permissions to the active KIPs. This fixes a potential crash where new processes might be unable to be registered with FS.
+ The `make dist` target now includes the branch in the generated zip name.
+ General system stability improvements to enhance the user's experience.
## 0.7.3
+ Loader and fs.mitm now try to reload loader.ini before reading it. This allows for changing the override button combination/HBL title id at runtime.
+ Added a MitM between set:sys and qlaunch, used to override the system version string displayed in system settings.
+ The displayed system version will now display `<Actual version> (AMS <x>.<y>.<z>)`.
+ General system stability improvements to enhance the user's experience.
## 0.7.2
+ Fixed a bug in fs.mitm's LayeredFS read implementation that caused some games to crash when trying to read files.
+ Fixed a bug affecting 1.0.0 that caused games to crash with fatal error 2001-0106 on boot.
+ Improved filenames output by the make dist target.
+ General system stability improvements to enhance the user's experience.
## 0.7.1
+ Fixed a bug preventing consoles on 4.0.0-4.1.0 from going to sleep and waking back up.
+ Fixed a bug preventing consoles on < 4.0.0 from booting without specific KIPs on the SD card.
+ An API was added to Atmosphère's Service Manager for deferring acquisition of all handles for specific services until after early initialization is completed.
+ General system stability improvements to enhance the user's experience.
## 0.7.0
+ First official release of Atmosphère.
+ Supports the following featureset:
+ Fusée, a custom bootloader.
+ Supports loading/customizing of arbitrary KIPs from the SD card.
+ Supports loading a custom kernel from the SD card ("/atmosphere/kernel.bin").
+ Supports compile-time defined kernel patches on a per-firmware basis.
+ All patches at paths like /atmosphere/kip_patches/<user-defined patch name>/<SHA256 of KIP>.ips will be applied to the relevant KIPs, allowing for easy distribution of patches supporting multiple versions.
+ Both the IPS and IPS32 formats are supported.
+ All patches at paths like /atmosphere/kernel_patches/<user-defined patch name>/<SHA256 of Kernel>.ips will be applied to the kernel, allowing for easy distribution of patches supporting multiple versions.
+ Both the IPS and IPS32 formats are supported.
+ Configurable by editing BCT.ini on the SD card.
+ Atmosphère should also be launchable by the alternative hekate bootloader, for those who prefer it.
+ Exosphère, a fully-featured custom secure monitor.
+ Exosphere is a re-implementation of Nintendo's TrustZone firmware, fully replicating all of its features.
+ In addition, it has been extended to provide information on current Atmosphere API version, for homebrew wishing to make use of it.
+ Stratosphère, a set of custom system modules. This includes:
+ A loader system module.
+ Reimplementation of Nintendo's loader, fully replicating all original functionality.
+ Configurable by editing /atmosphere/loader.ini
+ First class support for the Homebrew Loader.
+ An exefs NSP (default "/atmosphere/hbl.nsp") will be used in place of the victim title's exefs.
+ By default, HBL will replace the album applet, but any application should also be supported.
+ Extended to support arbitrary redirection of executable content to the SD card.
+ Files will be preferentially loaded from /atmosphere/titles/<titleid>/exefs/, if present.
+ Files present in the original exefs a user wants to mark as not present may be "stubbed" by creating a .stub file on the SD.
+ If present, a PFS0 at /atmosphere/titles/<titleid>/exefs.nsp will fully replace the original exefs.
+ Redirection is optionally toggleable by holding down certain buttons (by default, holding R disables redirection).
+ Full support for patching NSO content is implemented.
+ All patches at paths like /atmosphere/exefs_patches/<user-defined patch name>/<Hex Build-ID for NSO to patch>.ips will be applied, allowing for easy distribution of patches supporting multiple firmware versions and/or titles.
+ Both the IPS and IPS32 formats are supported.
+ Extended to support launching content from loose executable files on the SD card, without requiring any official installation.
+ This is done by specifying FsStorageId_None on launch.
+ A service manager system module.
+ Reimplementation of Nintendo's service manager, fully replicating all original functionality.
+ Compile-time support for reintroduction of "smhax", allowing clients to optionally skip service access verification by skipping initialization.
+ Extended to allow homebrew to acquire more handles to privileged services than Nintendo natively allows.
+ Extended to add a new API for installing Man-In-The-Middle listeners for arbitrary services.
+ API can additionally be used to safely detect whether a service has been registered in a non-blocking way with no side-effects.
+ Full API documentation to come.
+ A process manager system module.
+ Reimplementation of Nintendo's process manager, fully replicating all original functionality.
+ Extended to allow homebrew to acquire handles to arbitrary processes, and thus read/modify system memory without blocking execution.
+ Extended to allow homebrew to retrieve information about system resource limits.
+ Extended by embedding a full, extended implementation of Nintendo's boot2 system module.
+ Title launch order has been optimized in order to grant access to the SD card faster.
+ The error-collection system module is intentionally not launched, preventing many system telemetry error reports from being generated at all.
+ Users may place their own custom sysmodules on the SD card and flag them for automatic boot2 launch by creating a /atmosphere/titles/<title ID>/boot2.flag file on their SD card.
+ A custom fs.mitm system module.
+ Uses Atmosphère's MitM API in order to provide an easy means for users to modify game content.
+ Intercepts all FS commands sent by games, with special handling for commands used to mount RomFS/DLC content to enable easy creation and distribution of game/DLC mods.
+ fs.mitm will parse the base RomFS image for a game, a RomFS image located at /atmosphere/titles/<title ID>/romfs.bin, and all loose files in /atmosphere/titles/<title ID>/romfs/, and merge them together into a single RomFS image.
+ When merging, loose files are preferred to content in the SD card romfs.bin image, and files from the SD card image are preferred to those in the base image.
+ Can additionally be used to intercept commands sent by arbitrary system titles (excepting those launched before SD card is active), by creating a /atmosphere/titles/<title ID>/fsmitm.flag file on the SD card.
+ Can be forcibly disabled for any title, by creating a /atmosphere/titles/<title ID>/fsmitm_disable.flag file on the SD card.
+ Redirection is optionally toggleable by holding down certain buttons (by default, holding R disables redirection).
+ A custom crash report system module.
+ Serves as a drop-in replacement for Nintendo's own creport system module.
+ Generates detailed, human-readable reports on system crashes, saving to /atmosphere/crash_reports/<timestamp>_<title ID>.log.
+ Because reports are not sent to the erpt sysmodule, this disables all crash report related telemetry.
+ General system stability improvements to enhance the user's experience.

View File

@ -0,0 +1,10 @@
# Exosphère
Exosphère is a reimplementation of Arm's TrustZone (TZ), also known as Secure Monitor (Secure_Monitor.bin). It has the highest privilege mode available on the Switchs processor, and has access to everything on the console.
Exosphère will potentially play a big role in Jamais Vu and Déja Vu, which are upcoming software exploits for the Switch, allowing one to launch Atmosphère on a Fusée-Gélee patched (ipatched) Switch console, and will also enable one to launch into CFW directly from the Switch itself without the use of any sort of external device, such as a computer or RCM jig, provided they are on a low enough system firmware.
## TrustZone/Secure Monitor
TrustZone is responsible for all the cryptographic operations on the Switch. The idea behind the way it operates is that all the keys stay in the TrustZone, and userspace only gets "handles" to them. This would make sure that keydata never leaks and is kept secure. It also has a few more responsibilities, such as power management, providing a source of random numbers, and providing access to various pieces of information that are stored in the fuses.
## Extensions
Exosphère currently only contains one extension, an SMC allowing homebrew to find which version of Atmosphère is currently running, in order to find out what extensions are allowed to be used.

View File

@ -0,0 +1,26 @@
# BCT.ini
BCT.ini is the configuration file used by fusée-primary and fusée-secondary. It is read by fusee-primary.bin to setup and boot fusee-secondary.bin and is also read by fusee-secondary.bin to configure Exosphère or to specify the environment it should boot.
## Configuration
This file is located at the root of your SD.
```
BCT0
[stage1]
stage2_path = fusee-secondary.bin
stage2_addr = 0xF0000000
stage2_entrypoint = 0xF0000000
```
Add the following lines and replace the `X` according to the following list if you have trouble booting past the firmware version detection.
`target_firmware` is the OFW major version.
```
[exosphere]
target_firmware = X
```
```
1.0.0 = 1
2.X.X = 2
3.X.X = 3
4.X.X = 4
5.X.X = 5
6.0.0 = 6
```

View File

@ -0,0 +1,20 @@
# Fusée
Fusée (not to be confused with Fusée Gelée) is a custom bootloader needed to start Atmosphère and replaces Nintendo's Package1loader/bootloader. It currently utilizes the [Tegra X1 RCM Vulnerability](https://nvidia.custhelp.com/app/answers/detail/a_id/4660/~/security-notice%3A-nvidia-tegra-rcm-vulnerability) in order to function.
Fusée is split into two separate parts: fusée-primary and fusée-secondary. This is due to the RCM Vulnerability only allowing payloads of a limited filesize to be sent to the device.
As of June 2018, there are new Switch systems being sold that prevent Fusée (or any payload that requires the Fusée Gelée exploit) from working due to having an ipatched bootrom. All ipatched systems share the HAC-S-JXE-C3 product code. While Fusée cannot work on these ipatched units, they still come on firmware 4.1.0, which is vulnerable to the upcoming Déja Vu software exploit. Note that if you update past 4.1.0 on one of these ipatched units, your odds of being able to install Atmosphère or run any homebrew become practically non-existent.
Additionally, a hardware revision of the Switch known as “Mariko” is believed to be in development. No such units have been seen in stores yet, but it is expected Nintendo will roll them out silently. The Mariko units will most likely patch the bootrom vulnerability Fusée Gelée, which is currently used to access CFW, and will likely have their own proprietary bootloader.
## Fusée-Primary
Fusée-primary is the payload file (fusee-primary.bin) sent to the Switch from an external device. Once sent, fusée-primary makes initial preparations before loading fusée-secondary from the Switchs SD Card.
Fusée-primary can be configured via the [BCT.ini](../fusee/BCT.md) file located on the Switchs SD card.
## Fusée-Secondary
Fusée-secondary is a payload file that stays on the root of the Switchs SD Card (fusee-secondary.bin). It is automatically launched once fusée-primary has finished, and is responsible for preparing the Switchs hardware for future running environments, such as the homebrew menu. Fusée-secondary is also responsible for validating and launching Exosphère.
Fusée-secondary contains various [.kip modules](/docs/main.md#modules). These modules modify existing features in the OS, and can also add new ones.
Fusée is also capable of chainloading other payloads such as Linux.

View File

@ -0,0 +1,15 @@
# sept
Sept is a payload that facilitates booting Atmosphère when targeting firmware version 7.0.0+.
It consists of a primary and a secondary payload.
## Sept-Primary
Sept-primary is essentially a stand-in for Nintendo's package1ldr, on 7.0.0+. To use it, the caller (normally Fusée-secondary) loads the sept-primary binary to `0x4003F000`,
loads the 7.0.0+ TSEC firmware to `0x40010F00`, and loads a signed, encrypted payload to `0x40016FE0`.
This signed, encrypted payload is normally Sept-secondary.
## Sept-Secondary
Sept-secondary is a payload that performs 7.0.0+ key derivation, and then chainloads to `sept/payload.bin`.
It is normally stored encrypted/signed; if one wishes to build sept-secondary instead of using release builds, one must bring his/her own keys.

View File

@ -0,0 +1,10 @@
# Stratosphère
Stratosphère allows customization of the Horizon OS and Switch kernel. It includes custom sysmodules that extend the kernel and provide new features. It also includes a reimplementation of the loader sysmodules to hook important system actions.
The sysmodules that Stratosphère includes are:
+ [boot](../modules/boot.md): This module boots the system and initalizes hardware.
+ [creport](../modules/creport.md): Reimplementation of Nintendos crash report system. Dumps all error logs to the SD card instead of saving them to the NAND and sending them to Nintendo.
+ [fs_mitm](../modules/fs_mitm.md): This module can log, deny, delay, replace, and redirect any request made to the File System.
+ [loader](../modules/loader.md): Enables modifying the code of binaries that are not stored inside the kernel.
+ [pm](../modules/pm.md): Reimplementation of Nintendos Process Manager.
+ [sm](../modules/sm.md): Reimplementation of Nintendos Service Manager.

View File

@ -0,0 +1,6 @@
# Thermosphère
Thermosphère is a hypervisor based implementation of emuNAND. An emuNAND is a copy of the firmware on the Switchs internal memory (sysNAND), and is typically installed on an external SD Card.
An emuNAND operates completely independently of the sysNAND. This allows one to make or test various modifications and homebrew safely without needing to restore their NAND backup afterwards by testing things on the emuNAND, and switching back to the sysNAND when finished. In the case of past Nintendo systems such as the 3DS, an emuNAND could also be used to update your system to the latest firmware while keeping your sysNAND on a lower version, however this may be more difficult to do on the Switch due to Nintendo using efuse technology for major system updates.
Thermosphère is currently planned to be included in the 1.0 release of Atmosphère.

View File

@ -0,0 +1,2 @@
# Troposphère
Troposphère contains various application-level modifications to the OS, such as launching homebrew directly from the homemenu or executing cheat/gameshark codes, similar to Luma3DS. Troposphère is not yet implemented in Atmosphère.

12
docs/flags.md Normal file
View File

@ -0,0 +1,12 @@
# Flags
Atmosphère supports customizing CFW behavior based on the presence of `flags` on the SD card.
The following flags are supported on a per-title basis, by placing `<flag_name>.flag` inside `/atmosphere/titles/<title_id>/flags/`:
+ `boot2`, which indicates to PM that the title should be launched during the `boot2` process.
+ `fsmitm`, which indicates that `fs.mitm` should override contents for the title even if it otherwise wouldn't.
+ `fsmitm_disable`, which indicates that `fs.mitm` should not override contents for the title, even it it otherwise would.
+ `bis_write`, which indicates that `fs.mitm` should allow the title to write to BIS partitions.
+ `cal_read`, which indicates that `fs.mitm` should allow the title to read the CAL0/PRODINFO partition.
The following global flags are supported, by placing `<flag name>.flag` inside `/atmosphere/flags/`:
+ `hbl_bis_write` and `hbl_cal_read` enable the BIS write and CAL0 read functionality for HBL, without needing to specify its title id.

29
docs/main.md Normal file
View File

@ -0,0 +1,29 @@
# Atmosphère
Atmosphère is a work-in-progress customized firmware for the Nintendo Switch. Atmosphère consists of several different components, each in charge of performing different system functions of the Nintendo Switch.
The components of Atmosphère are:
+ [Fusée](../docs/components/fusee/fusee.md), a custom bootloader.
+ [Exosphère](../docs/components/exosphere.md), a fully-featured custom secure monitor.
+ [Stratosphère](../docs/components/stratosphere.md), a set of custom system modules.
+ [Thermosphère](../docs/components/thermosphere.md), a hypervisor-based emuNAND implementation. This component has not been implemented yet.
+ [Troposphère](../docs/components/troposphere.md), Application-level patches to the Horizon OS. This component has also not been implemented yet.
### Modules
The Stratosphère component of Atmosphère contains various modules. These have a `.kip` extension. They provide custom features, extend existing features, or replace Nintendo sysmodules.
Stratosphère's modules include:
+ [boot](../docs/modules/boot.md)
+ [creport](../docs/modules/creport.md)
+ [fs_mitm](../docs/modules/fs_mitm.md)
+ [loader](../docs/modules/loader.md)
+ [pm](../docs/modules/pm.md)
+ [sm](../docs/modules/sm.md)
### Building Atmosphère
A guide to building Atmosphère can be found [here](../docs/building.md).
### Upcoming Features
A list of planned features for Atmosphère can be found [here](../docs/roadmap.md).
### Release History
A changelog of previous versions of Atmosphère can be found [here](../docs/changelog.md).

2
docs/modules/boot.md Normal file
View File

@ -0,0 +1,2 @@
# boot
The boot module is responsible for booting the system and initalizing hardware. A second boot module known as boot2 is integrated with the [pm (process manager)](../modules/pm.md) sysmodule in Atmosphère, and launches other processes.

2
docs/modules/creport.md Normal file
View File

@ -0,0 +1,2 @@
# creport
creport is a reimplementation of Nintendo's crash reporter. Atmosphère's creport catches all error logs that would have been saved to the NAND and instead saves them to the SD card for debugging purposes. This is helpful because the errors no longer go to Nintendo and developers of homebrew can still see the errors to help with the debugging process. creport catches system errors, game crashes, and homebrew crashes.

2
docs/modules/fs_mitm.md Normal file
View File

@ -0,0 +1,2 @@
# fs_mitm
fs_mitm is a sysmodule that enables intercepting file system operations. This module can log, deny, delay, replace, or redirect any request made to the filesystem. It enables LayeredFS to function, which allows for game mods.

101
docs/modules/loader.md Normal file
View File

@ -0,0 +1,101 @@
# loader
loader is a reimplementation of the loader sysmodule. This module is responsible for creating processes from executable NSO images and registering their access control with the kernel, sm, and fs.
## Atmosphère Extensions
Atmosphère extends this module to allow executables to be replaced or patched by files stored on the SD card. Note that a few services are required for SD card access and therefore cannot be replaced or patched in this manner. This includes psc, bus, and pcv.
### Exefs Replacement
TODO: details on buttons affecting this.
When a process is created, loader will search for several NSO filenames in the title's exefs directory.
These filenames are, in this order:
- rtld
- main
- subsdk0
- subsdk1
- ...
- subsdk9
- sdk
Each NSO that is found will be loaded into the process contiguously. The process's entrypoint is at the first NSO to be loaded, usually `rtld` or `main`.
Additionally, when a process is loaded, loader will search for a `main.npdm` file in the exefs directory specifying the title's permissions.
Atmosphère extends this functionality by also searching for these files on the SD card. When searching for a file, loader will first check if it exists on the SD card. If it does, that file will be used instead. Otherwise, it will use the copy located in the exefs, if that is present. The following directory will be searched.
```
sdmc:/atmosphere/titles/<title id>/exefs/
```
This allows the replacement of applets, sysmodules, or even games with homebrew versions.
In order to prevent an NSO from being loaded even if it exists in the exefs, loader will also check if a stub file exists. If such a file exists, the NSO will not be loaded. The files should be named like `rtld.stub`, `main.stub`, etc. and may be empty.
### NSO Patching
TODO: details on buttons affecting this.
When an NSO is loaded, the stratosphere implementatin of loader will search for IPS patch files on the SD card in the following locations.
```
sdmc:/atmosphere/exefs_patches/<patchset name>/<nso build id>.ips
```
This organization allows patchsets affecting multiple NSOs to be distributed as a single directory. Patches will be searched for in each patchset directory. The name of each patch file should match the hexadecimal build ID of the NSO to affect, except that trailing zero bytes may be left off. Because the NSO build ID is unique for every NSO, this means patches will only apply to the files they are meant to apply to.
Patch files are accepted in either IPS format or IPS32 format.
Because NSO files are compressed, patch files are not made between the original version of a compressed NSO and the modified version of such an NSO. Instead, they are made between the uncompressed version of an NSO and the modified (and still uncompressed) version of that NSO. This also means that a patch file cannot be manually applied to the compressed version of an NSO; it must be applied to the uncompressed version. The Stratosphere implementation of loader will correctly apply these patches while loading the process regardless of whether the NSO it finds is compressed or not.
When authoring patches, [hactool](https://github.com/SciresM/hactool) can be used to find an NSO's build ID and to uncompress NSOs. Recent versions of the [ReSwitched IDA loaders](https://github.com/reswitched/loaders) can be used to load uncompressed NSOs into IDA in such a way that you can [apply patches to the input file](https://www.hex-rays.com/products/ida/support/idadoc/1618.shtml). From there, any IPS tool can be used to create the patch between the original NSO and the patched NSO. Note that if the NSO you are patching is larger than 16 MiB, you will have to use a tool that supports IPS32.
### HBL Support
Atmosphère can use the loader module in order to turn any game on your Switch's home menu into a launchpoint for the Homebrew Menu, rather than launching it through the album applet. This allows one to launch the Homebrew Menu with access to the ~3.2GB of RAM that the Switch reserves for games and applications, as opposed to the 442MB of RAM we are limited to when launching the Homebrew Menu from the album. This also means that it is no longer necessary to install homebrew as `.nsp` files on your Switch so long as you are using this method, as the only reason to do so is to allow the homebrew to access all of the Switch's available memory.
In order to setup this method you will need the latest release of [hbmenu](https://github.com/switchbrew/nx-hbmenu/releases), and the latest release of [hbloader](https://github.com/switchbrew/nx-hbloader/releases). Place `hbmenu.nro` on the root of your Switch's SD Card, and place `hbl.nsp` in the atmosphere folder. From there, simply configure `loader.ini` in the atmosphere folder by replacing the Title ID in the ini (title_id in the [hbl_config] section) (it is the Title ID for the album by default) with the Title ID of whatever game you wish to use to launch the Homebrew Menu. A list of Title IDs for Switch Games can be found [here](https://switchbrew.org/wiki/Title_list/Games). Afterwards you may reinsert your SD Card into your Switch and boot into Atmosphère as you normally would. You should now be able to boot into the Homebrew Menu by launching your designated game of choice.
### Button Overrides
By default `loader.ini` is configured to launch the Homebrew Menu when launching the game normally, and launching the game when selecting the game while holding down R. If you wish to change this, you can modify the override_key section of `loader.ini`. Placing an exclamation point in front of whatever button you wish to use will make it so that you will only launch the actual game while holding down that button, otherwise you will go into the Homebrew Menu. Removing the exclamation point will reverse this, meaning that you will boot into the Homebrew Menu only while holding down the assigned button when launching the game.
For example, `override_key=!R` will run the game only while holding down R when launching it, otherwise it will boot into the Homebrew Menu. `override_key=R` will only boot into the Homebrew Menu while holding down R when launching the game, otherwise it will launch the game as normal.
### SM MITM Integration
When the Stratosphere implementation of loader creates a new process, it notifies [sm](sm.md) through the `AtmosphereAssociatePidTidForMitm` command to notify any MITM services of new processes' identities.
### IPC: AtmosphereSetExternalContentSource and AtmosphereClearExternalContentSource
Two additional commands are added to the [`ldr:shel`](https://reswitched.github.io/SwIPC/ifaces.html#nn::ro::detail::ILdrShellInterface) interface, called `AtmosphereSetExternalContentSource` and `AtmosphereClearExternalContentSource`.
Their command IDs are `65000` and `65001` on all system firmware versions.
`AtmosphereSetExternalContentSource` takes a `u64 tid` and returns a server-side session handle.
The client is expected to implement the `IFileSystem` interface on the returned handle. The next
time the title specified by the given title ID is launched, its ExeFS contents will be loaded from
the custom `IFileSystem` instead of from SD card or original ExeFS. NSOs loaded from external
content source may still be subject to exefs IPS patches. After the title is launched successfuly,
the `IFileSystem` is closed and the external content source override is removed. If
`AtmosphereSetExternalContentSource` is called on a title that already has an external content
source set for it, the existing one will be removed and replaced with the new one. It is illegal to
call `AtmosphereSetExternalContentSource` while the title is being launched.
If title launching fails, the external content source remains registered. The
`AtmosphereClearExternalContentSource` command can be used to clear an external content source if
title launch fails.
The `IFileSystem` only needs to implement `OpenFile` and `GetFileTimeStampRaw`. The paths received
by the `IFileSystem`'s `OpenFile` command begin with slashes, as in `/main`, `/rtld`, and `/main.npdm`.
A result code of 0x202 should be returned if the file does not exist. `GetFileTimeStampRaw` can just
be a stub. The `IFile`s returned from `OpenFile` only need to implement `Read` and `GetSize`.
The SwIPC definitions for the extension commands follow.
```
interface nn::ldr::detail::IShellInterface is ldr:shel {
...
[65000] AtmosphereSetExternalContentSource(u64 tid) -> handle<copy, session_server> ifilesystem_handle;
[65001] AtmosphereClearExternalContentSource(u64 tid);
}
```

23
docs/modules/pm.md Normal file
View File

@ -0,0 +1,23 @@
# pm
pm is a reimplementation of Nintendo's process manager. This module is responsible for tracking running processes on the system, and managing resource limits. pm is also required to create and manage processes for homebrew applications.
## Atmosphère Extensions
There are a few ways in which the Stratosphere implementation of pm differs intentionally from the stock pm.
### IPC: AtmosphereGetProcessHandle
The Stratosphere implementation of pm adds an additional command to the [`pm:dmnt`](https://reswitched.github.io/SwIPC/ifaces.html#nn::pm::detail::IDebugMonitorInterface) interface, called `AtmosphereGetProcessHandle`. Its command ID is `65000` on all system firmware versions. It takes a `u64 process_id` and returns a process handle for the specified process, if that process is known. Notable exceptions include KIPs, which are not known to pm. If the specified process cannot be found, error code 0x20F is returned.
The SwIPC definition for this command follows.
```
interface nn::pm::detail::IDebugMonitorInterface is pm:dmnt {
...
[65000] AtmosphereGetProcessInfo(u64 pid) -> handle<copy, process> process_handle, u64 title_id, u64 storage_id;
}
```
### Extra System Memory for Sysmodules
The Stratosphere implementation of pm shrinks the APPLET memory pool by 24 MiB by default, giving this memory to the SYSTEM pool. This allows custom sysmodules to use more memory without hitting the SYSTEM memory limit.

54
docs/modules/set_mitm.md Normal file
View File

@ -0,0 +1,54 @@
# set_mitm
set_mitm is a sysmodule that enables intercepting requests to the system settings service.
## Atmosphère Extensions
set_mitm intercepts the `GetFirmwareVersion` command, if the requester is `qlaunch` or `maintenance`.\
It modifies the `display_version` field of the returned system version, causing the version to display\
in settings as `#.#.# (AMS #.#.#)`. This allows users to easily verify what version of Atmosphère they are running.
set_mitm also intercepts the `GetSettingsItemValueSize` and `GetSettingsItemValue` commands for all requesters.\
It does so in order to enable user configuration of system settings, which are parsed from `atmosphere/system_settings.ini` on boot.\
The format for settings is described below.
### Atmosphère Settings Format
Settings are parsed from the `atmosphere/system_settings.ini` file during the boot process. This file is a normal ini file,\
with some specific interpretations.
The standard representation of a system setting's identifier takes the form `name!key`. This is represented within\
`system_settings.ini` as a section `name`, with an entry `key`. For example:
```
[name]
key = ...
```
System settings can have variable types (strings, integral values, byte arrays, etc). To accommodate this, `system_settings.ini`\
must store values as a `type_identifier!value_store` pair. A number of different types are supported, with identifiers detailed below.\
Please note that a malformed value string will cause a fatal error to occur on boot. A full example of a custom setting is given below\
(setting `eupld!upload_enabled = 0`), for posterity:
```
[eupld]
upload_enabled = u8!0x0
```
### Supported Types
* Strings
* Type identifiers: `str`, `string`
* The value string is used directly as the setting, with null terminator appended.
* Integral types
* Type identifiers: `u8`, `u16`, `u32`, `u64`
* The value string is parsed via a call to `strtoul(value, NULL, 0)`.
* Setting bitwidth is determined by the identifier (8 for 1 byte, 16 for 2 bytes, and so on).
* Raw bytes
* Type identifiers: `hex`, `bytes`
* The value string is parsed as a hexadecimal string.
* The value string must be of even length, or a fatal error will be thrown on parse.
### Atmosphère Custom Settings
At present, Atmosphère implements no custom settings. However, this is subject to change in the future, and any\
custom settings will be documented here as they are added.

125
docs/modules/sm.md Normal file
View File

@ -0,0 +1,125 @@
# sm
sm is a reimplementation of Nintendo's service manager. It allows Atmosphère to add or remove process handle limits, add new services, or intercept service calls. This allows high-level intercepting of Horizon OS functionality.
## Atmosphère Extensions
There are a few ways in which the Stratosphere implementation of sm differs intentionally from the stock sm.
### IPC: MITM Commands
The Stratosphere implementation of sm adds a few additional commands to the [`sm:`](https://reswitched.github.io/SwIPC/ifaces.html#nn::sm::detail::IUserInterface) port session.
Their SwIPC definitions follow.
```
interface nn::sm::detail::IUserInterface is sm: {
...
[65000] AtmosphereInstallMitm(ServiceName service) -> handle<port, move> service, handle<server_session, move> query;
[65001] AtmosphereUninstallMitm(ServiceName service);
[65002] AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid);
}
```
Additionally, an interface `sm:dmnt` has been created to allow a debug monitor to query sm's state.
Its SwIPC definition follows.
```
interface nn::sm::detail::IDebugMonitorInterface is sm:dmnt {
[65000] AtmosphereGetServiceRecord(ServiceName name) -> SmServiceRecord;
[65001] AtmosphereListServiceRecords(u64 offset) -> buffer<SmServiceRecord, 6>, u64 count;
[65002] AtmosphereGetServiceRecordSize() -> u64 record_size;
}
```
#### AtmosphereInstallMitm
This command alters the registration for the named service, in order to allow services to intercept communication between client processes and their intended services. It is used by [fs_mitm](fs_mitm.md).
It takes the name of the service to install an MITM for, and returns two handles. The first is a port handle, similar to those returned from the [RegisterService](https://reswitched.github.io/SwIPC/ifaces.html#nn::sm::detail::IUserInterface(2)) command. The second is the server side of a session, called the query session. This session will used by sm to determine whether or not a new session should be intercepted, and to inform the MITM service of the identity of new processes.
The query session is expected to implement the following interface.
```
interface MitmQueryService {
[65000] ShouldMitm(u64 pid) -> u64 should_mitm;
[65001] AssociatePidTid(u64 pid, u64 tid);
}
```
The `ShouldMitm` command is invoked whenever a process attempts to make a new connection to the MITM'd service. It should return `0` if the process's connection should not be intercepted. Any other value will cause the process's connection to be intercepted. If the command returns an error code, the process's connection will not be intercepted.
The `AssociatePidTid` command is invoked on all MITM query sessions whenever a new process is created, in order to inform those services of the identity of a newly created process before it attempts to connect to any services.
If the process that installed the MITM attempts to connect to the service, it will always connect to the original service.
This command requires that the session be initialized, returning error code 0x415 if it is not.\
If the given service name is invalid, error code 0xC15 is returned.\
If the user does not have service registration permission for the named service, error code 0x1015 is returned.\
If the service already has an MITM installed, error code 0x815 is returned.\
If the service has not yet been registered, the request will be deferred until the service is registered in the same manner as IUserInterface::GetService.
#### AtmosphereUninstallMitm
Removes any installed MITM for the named service.
This command requires that the session be initialized, returning error code 0x415 if it is not.
#### AtmosphereAssociatePidTidForMitm
This command is used internally by the Stratosphere implementation of the [loader](loader.md) sysmodule, when a new process is created. It will call the `AssociatePidTid` command on every registered MITM query session.
If the given process ID refers to a kernel internal process, error code 0x1015 is returned. This command requires that the session be initialized, returning error code 0x415 if it is not.
#### AtmosphereGetServiceRecordSize
Retrieves `sizeof(SmServiceRecord)` for a service. The current format of `SmServiceRecord` structure follows.
```
struct SmServiceRecord {
uint64_t service_name;
uint64_t owner_pid;
uint64_t max_sessions;
uint64_t mitm_pid;
uint64_t mitm_waiting_ack_pid;
bool is_light;
bool mitm_waiting_ack;
};
```
#### AtmosphereGetServiceRecord
Retrieves a service registration record for a service.
#### AtmosphereListServiceRecords
Provides a list of service registrations records.
The command will return an array of `SmServiceRecord`s, skipping `offset` records. The number of records returned is indicated by `count`.
If `count` is less than the size of the buffer divided by `sizeof(SmServiceRecord)` (the buffer was not completely filled), the end of the service registration list has been reached. Otherwise, client code
should increment `offset` by `count` and call again. Client code should retrieve a record size using `AtmosphereGetServiceRecordSize`, and either make sure that the size of a record matches what it expects,
or should make sure to use the correct size as the stride while iterating over the array of returned records. Example pseudocode is shown below.
```
offset = 0;
record_size = AtmosphereGetServiceRecordSize();
do {
SmServiceRecord records[16];
count = AtmosphereListServiceRecords(offset, buffer(records));
for (i = 0; i < count; i++) {
SmServiceRecord record = {0};
memcpy(&record, &records[i], min(record_size, sizeof(SmServiceRecord));
/* process record */
offset++;
}
} while(count == sizeof(records) / record_size);
```
### Minimum Session Limit
When a service is registered, the sysmodule registering it must specify a limit on the number of sessions that are allowed to be active for that service at a time. This is used to ensure that services like `fs-pr`, `fs-ldr`, and `ldr:pm` can only be connected to once, adding an additional layer of safety over the regular service verification to ensure that those services are only connected to by the highly priveleged process they are intended to be used by.
By default, the Stratosphere implementation of PM will raise any session limits to at least 8, meaning that for services like `fs-pr` and those mentioned above, up to 8 processes will be able to connect to those sessions, leaving 7 sessions for homebrew to use.
### Weak Service Verification
In system firmware versions before 3.0.1, if a process did not call the [Initialize](https://reswitched.github.io/SwIPC/ifaces.html#nn::sm::detail::IUserInterface(0)) command on its `sm:` session, normally used to inform sm of the process's identity, sm would assume that the process was a kernel internal process and skip any service registration or access checks. The Stratosphere implementation of sm reimplements this vulnerability, allowing homebrew processes to skip service registration and access checks.

16
docs/roadmap.md Normal file
View File

@ -0,0 +1,16 @@
# Planned Features
The following features are planned to be added in future versions of Atmosphère:
+ Thermosphère, a hypervisor-based emunand implementation.
+ A feature-rich debugging toolset (a component of Stratosphère).
+ A custom debug monitor system module, providing an API for debugging Switch's processes. This may not be a reimplementation of Nintendo's own debug monitor.
+ This should include a gdbstub implementation, possibly borrowing from Luma3DS's.
+ This API should be additionally usable for RAM Editing/"Cheat Engine" purposes.
+ A custom shell system module, providing an means for users to perform various RPC (with support for common/interesting functionality) on their Switch remotely. This may not be a reimplementation of Nintendo's own shell.
+ This should support client connections over both Wi-Fi and USB.
+ A custom logging system module, providing a means for other Atmosphère components (and possibly Nintendo's own system modules) to log debug output.
+ This should support logging to the SD card, over Wi-Fi, and over USB.
+ An application-level plugin system.
+ This will, ideally, work somewhat like NTR-CFW's plugin system on the 3DS, allowing users to run their own code in a game's process in their own thread.
+ An AR Code/Gameshark analog implementation, allowing for easy sharing/development of cheat codes to run on device.
+ Further extensions to existing Atmosphère components.
+ General system stability improvements to enhance the user's experience.

View File

@ -9,6 +9,13 @@ endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/devkitA64/base_rules
AMSBRANCH := $(shell git symbolic-ref --short HEAD)
AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD)
ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
AMSREV := $(AMSREV)-dirty
endif
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
@ -20,30 +27,32 @@ TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := src src/dbg
DATA := data
INCLUDES := include
INCLUDES := include ../common/include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a -mtune=cortex-a57
DEFINES := -D__CCPLEX__
ARCH := -march=armv8-a -mtune=cortex-a57 -mgeneral-regs-only #<- important
DEFINES := -D__CCPLEX__ -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"
CFLAGS := \
-g \
-O2 \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
-fno-asynchronous-unwind-tables \
-fno-unwind-tables \
-std=gnu11 \
-Werror \
-Wall \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE)
CFLAGS += $(INCLUDE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -nostartfiles -nostdlib -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS :=
@ -66,14 +75,16 @@ export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(TOPDIR)/bpmpfw
$(TOPDIR)/lp0fw \
$(TOPDIR)/sc7fw \
$(TOPDIR)/rebootstub
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) bpmpfw.bin
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin lp0fw.bin rebootstub.bin
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@ -100,22 +111,30 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) build_bpmpfw clean all
.PHONY: $(BUILD) build_sc7fw build_lp0fw build_rebootstub clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
check_bpmpfw:
@$(MAKE) -C bpmpfw all
check_sc7fw:
@$(MAKE) -C sc7fw all
$(BUILD): check_bpmpfw
check_lp0fw:
@$(MAKE) -C lp0fw all
check_rebootstub:
@$(MAKE) -C rebootstub all
$(BUILD): check_sc7fw check_lp0fw check_rebootstub
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@$(MAKE) -C $(TOPDIR)/bpmpfw clean
@$(MAKE) -C $(TOPDIR)/sc7fw clean
@$(MAKE) -C $(TOPDIR)/lp0fw clean
@$(MAKE) -C $(TOPDIR)/rebootstub clean
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf

View File

@ -1,10 +0,0 @@
#ifndef EXOSPHERE_BPMPFW_LP0_H
#define EXOSPHERE_BPMPFW_LP0_H
#include "utils.h"
void lp0_entry_main(void);
void reboot(void);
#endif

View File

@ -1,24 +0,0 @@
.section .text.start
.align 4
.global _start
_start:
b crt0
.global _reboot
b reboot
.global crt0
.type crt0, %function
crt0:
@ setup to call lp0_entry_main
msr cpsr_cxsf, #0xD3
ldr sp, =__stack_top__
ldr lr, =reboot
b lp0_entry_main
.global spinlock_wait
.type spinlock_wait, %function
spinlock_wait:
subs r0, r0, #1
bgt spinlock_wait
bx lr

View File

@ -1,17 +0,0 @@
#ifndef EXOSPHERE_BPMPFW_TIMER_H
#define EXOSPHERE_BPMPFW_TIMER_H
#include "utils.h"
#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010)
static inline void timer_wait(uint32_t microseconds) {
uint32_t old_time = TIMERUS_CNTR_1US_0;
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
/* Spin-lock. */
}
}
void spinlock_wait(uint32_t count);
#endif

View File

@ -1,22 +0,0 @@
#ifndef EXOSPHERE_BPMPFW_UTILS_H
#define EXOSPHERE_BPMPFW_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define BIT(n) (1u << (n))
#define BITL(n) (1ull << (n))
#define MASK(n) (BIT(n) - 1)
#define MASKL(n) (BITL(n) - 1)
#define MASK2(a,b) (MASK(a) & ~MASK(b))
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
#define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed))
#define ALINLINE __attribute__((always_inline))
#endif

View File

@ -2,6 +2,3 @@
*link:
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
*startfile:
crti%O%s crtbegin%O%s

154
exosphere/lp0fw/Makefile Normal file
View File

@ -0,0 +1,154 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/base_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := src
DATA := data
INCLUDES := include ../../common/include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS := \
-g \
-O2 \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
-fno-inline \
-std=gnu11 \
-Werror \
-Wall \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__BPMP__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# 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 VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# 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 .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin
$(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
%.elf: $(OFILES)
@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
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

24
exosphere/lp0fw/linker.ld Normal file
View File

@ -0,0 +1,24 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x40010000;
__start__ = ABSOLUTE(.);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; }
. = ALIGN(4);
__end__ = ABSOLUTE(.);
__total_size__ = (__end__ - __start__);
__executable_size__ = (__end__ - _start);
__stack_top__ = 0x40013000;
__stack_bottom__ = 0x40012000;
}

134
exosphere/lp0fw/src/car.c Normal file
View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2018 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 <stdint.h>
#include "utils.h"
#include "car.h"
#include "timer.h"
#include "pmc.h"
#include "emc.h"
#include "lp0.h"
static inline uint32_t get_special_clk_reg(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0x178;
case CARDEVICE_UARTB: return 0x17C;
case CARDEVICE_I2C1: return 0x124;
case CARDEVICE_I2C5: return 0x128;
case CARDEVICE_ACTMON: return 0x3E8;
case CARDEVICE_BPMP: return 0;
default: reboot();
}
}
static inline uint32_t get_special_clk_val(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0;
case CARDEVICE_I2C1: return (6 << 29);
case CARDEVICE_I2C5: return (6 << 29);
case CARDEVICE_ACTMON: return (6 << 29);
case CARDEVICE_BPMP: return 0;
default: reboot();
}
}
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298};
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
static uint32_t g_clk_clr_reg_offsets[NUM_CAR_BANKS] = {0x324, 0x32C, 0x334, 0x444, 0x44C, 0x228, 0x2A0};
void car_configure_oscillators(void) {
/* Enable the crystal oscillator, setting drive strength to the saved value in PMC. */
CLK_RST_CONTROLLER_OSC_CTRL_0 = (CLK_RST_CONTROLLER_OSC_CTRL_0 & 0xFFFFFC0E) | 1 | (((APBDEV_PMC_OSC_EDPD_OVER_0 >> 1) & 0x3F) << 4);
/* Set CLK_M_DIVISOR to 1 (causes actual division by 2.) */
CLK_RST_CONTROLLER_SPARE_REG0_0 = (1 << 2);
/* Reading the register after writing it is required to ensure value takes. */
(void)(CLK_RST_CONTROLLER_SPARE_REG0_0);
/* Set TIMERUS_USEC_CFG to cycle at 0x60 / 0x5 = 19.2 MHz. */
/* Value is (dividend << 8) | (divisor). */
TIMERUS_USEC_CFG_0 = 0x45F;
}
void car_mbist_workaround(void) {
/* This code works around MBIST bug. */
/* Clear LVL2_CLK_GATE_OVR* registers. */
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 = 0;
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 = 0;
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 = 0;
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 = 0;
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 = 0;
/* Clear bit patterns in CAR. */
/* L: Reset all but RTC, TMR, GPIO, BPMP Cache (CACHE2). */
MAKE_CAR_REG(g_clk_clr_reg_offsets[0]) = MAKE_CAR_REG(g_clk_reg_offsets[0]) & 0x7FFFFECF;
/* H: Reset all but MC, PMC, FUSE, EMC. */
MAKE_CAR_REG(g_clk_clr_reg_offsets[1]) = MAKE_CAR_REG(g_clk_reg_offsets[1]) & 0xFDFFFF3E;
/* U: Reset all but CSITE, IRAM[A-D], BPMP Cache RAM (CRAM2). */
MAKE_CAR_REG(g_clk_clr_reg_offsets[2]) = MAKE_CAR_REG(g_clk_reg_offsets[2]) & 0xFE0FFDFF;
/* V: Reset all but MSELECT, S/PDIF audio doubler, TZRAM, SE. */
MAKE_CAR_REG(g_clk_clr_reg_offsets[3]) = MAKE_CAR_REG(g_clk_reg_offsets[3]) & 0x3FBFFFF7;
/* W: Reset all but PCIERX[0-5], ENTROPY. */
MAKE_CAR_REG(g_clk_clr_reg_offsets[4]) = MAKE_CAR_REG(g_clk_reg_offsets[4]) & 0xFFDFFF03;
/* X: Reset all but ETC, MCLK, MCLK2, I2C6, EMC_DLL, GPU, DBGAPB, PLLG_REF, . */
MAKE_CAR_REG(g_clk_clr_reg_offsets[5]) = MAKE_CAR_REG(g_clk_reg_offsets[5]) & 0xDCFFB87F;
/* Y: Reset all but MC_CDPA, MC_CCPA. */
MAKE_CAR_REG(g_clk_clr_reg_offsets[6]) = MAKE_CAR_REG(g_clk_reg_offsets[6]) & 0xFFFFFCFF;
/* Enable clock to MC1, if CH1 is enabled in EMC. */
if (EMC_FBIO_CFG7_0 & 4) { /* CH1_ENABLE */
CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 |= 0x40000000; /* SET_CLK_ENB_MC1 */
}
}
void clk_enable(CarDevice dev) {
uint32_t special_reg;
if ((special_reg = get_special_clk_reg(dev))) {
MAKE_CAR_REG(special_reg) = get_special_clk_val(dev);
}
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
}
void clk_disable(CarDevice dev) {
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
}
void rst_enable(CarDevice dev) {
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
}
void rst_disable(CarDevice dev) {
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
}
void clkrst_enable(CarDevice dev) {
clk_enable(dev);
rst_disable(dev);
}
void clkrst_disable(CarDevice dev) {
rst_enable(dev);
clk_disable(dev);
}
void clkrst_reboot(CarDevice dev) {
clkrst_disable(dev);
clkrst_enable(dev);
}

109
exosphere/lp0fw/src/car.h Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_CLOCK_AND_RESET_H
#define EXOSPHERE_WARMBOOT_BIN_CLOCK_AND_RESET_H
#include <stdint.h>
#define CAR_BASE 0x60006000
#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n)
#define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048)
#define CLK_RST_CONTROLLER_OSC_CTRL_0 MAKE_CAR_REG(0x050)
#define CLK_RST_CONTROLLER_PLLX_BASE_0 MAKE_CAR_REG(0x0E0)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4)
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450)
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454)
#define CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 MAKE_CAR_REG(0x36C)
#define CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 MAKE_CAR_REG(0x374)
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5_0 MAKE_CAR_REG(0x128)
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 MAKE_CAR_REG(0x62C)
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 MAKE_CAR_REG(0x630)
#define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0 MAKE_CAR_REG(0x388)
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT_0 MAKE_CAR_REG(0x3B4)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 MAKE_CAR_REG(0x0F8)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 MAKE_CAR_REG(0x0FC)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 MAKE_CAR_REG(0x3A0)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 MAKE_CAR_REG(0x554)
#define CLK_RST_CONTROLLER_CCLKG_BURST_POLICY_0 MAKE_CAR_REG(0x368)
#define CLK_RST_CONTROLLER_CCLKP_BURST_POLICY_0 MAKE_CAR_REG(0x370)
#define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008)
#define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C)
#define CLK_RST_CONTROLLER_RST_DEV_H_SET_0 MAKE_CAR_REG(0x308)
#define CLK_RST_CONTROLLER_RST_DEV_U_SET_0 MAKE_CAR_REG(0x310)
#define CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 MAKE_CAR_REG(0x30C)
#define CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 MAKE_CAR_REG(0x314)
#define CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 MAKE_CAR_REG(0x434)
#define CLK_RST_CONTROLLER_CLK_ENB_L_SET_0 MAKE_CAR_REG(0x320)
#define CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 MAKE_CAR_REG(0x328)
#define CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 MAKE_CAR_REG(0x330)
#define CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 MAKE_CAR_REG(0x440)
#define CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 MAKE_CAR_REG(0x448)
#define CLK_RST_CONTROLLER_CLK_ENB_Y_SET_0 MAKE_CAR_REG(0x29C)
#define CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 MAKE_CAR_REG(0x32C)
#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 MAKE_CAR_REG(0x44C)
#define NUM_CAR_BANKS 7
typedef enum {
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_UNK = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_BPMP = ((0 << 5) | 0x1)
} CarDevice;
void car_configure_oscillators(void);
void car_mbist_workaround(void);
void clk_enable(CarDevice dev);
void clk_disable(CarDevice dev);
void rst_enable(CarDevice dev);
void rst_disable(CarDevice dev);
void clkrst_enable(CarDevice dev);
void clkrst_disable(CarDevice dev);
void clkrst_reboot(CarDevice dev);
#endif

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2018 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 <stdint.h>
#include "utils.h"
#include "cluster.h"
#include "car.h"
#include "timer.h"
#include "pmc.h"
#include "misc.h"
#include "i2c.h"
#include "flow.h"
#include "sysreg.h"
static void cluster_pmc_enable_partition(uint32_t mask, uint32_t toggle) {
/* Set toggle if unset. */
if (!(APBDEV_PMC_PWRGATE_STATUS_0 & mask)) {
APBDEV_PMC_PWRGATE_TOGGLE_0 = toggle;
}
/* Wait until toggle set. */
while (!(APBDEV_PMC_PWRGATE_STATUS_0 & mask)) { }
/* Remove clamping. */
APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = mask;
while (APBDEV_PMC_CLAMP_STATUS_0 & mask) { }
}
void cluster_initialize_cpu(void) {
/* Hold CoreSight in reset. */
CLK_RST_CONTROLLER_RST_DEV_U_SET_0 = 0x200;
/* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */
CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0 &= 0xFFFFF000;
/* Restore SB_AA64_RESET values from PMC scratch. */
SB_AA64_RESET_LOW_0 = APBDEV_PMC_SECURE_SCRATCH34_0 | 1;
SB_AA64_RESET_HIGH_0 = APBDEV_PMC_SECURE_SCRATCH35_0;
/* Set CDIV_ENB for CCLKG/CCLKP. */
CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 = 0x80000000;
CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 = 0x80000000;
/* Enable CoreSight clock, take CoreSight out of reset. */
CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 = 0x200;
CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 = 0x200;
/* Configure MSELECT to divide by 4, enable MSELECT clock. */
CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT_0 = 6; /* (6/2) + 1 = 4. */
CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 = 0x8;
/* Wait 2 us, then take MSELECT out of reset. */
timer_wait(2);
CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 = 0x8;
/* Set MSELECT WRAP_TO_SLAVE_INCR[0-2], clear ERR_RESP_EN_SLAVE[1-2]. */
MSELECT_CONFIG_0 = (MSELECT_CONFIG_0 & 0xFCFFFFFF) | 0x38000000;
/* Clear PLLX_ENABLE. */
CLK_RST_CONTROLLER_PLLX_BASE_0 &= 0xBFFFFFFF;
/* Clear PMC scratch 190, disable PMC DPD then wait 10 us. */
APBDEV_PMC_SCRATCH190_0 &= 0xFFFFFFFE;
APBDEV_PMC_DPD_SAMPLE_0 = 0;
timer_wait(10);
/* Configure UART2 via GPIO controller 2 G. */
MAKE_REG32(0x6000D108) |= 4; /* GPIO_CNF */
MAKE_REG32(0x6000D118) |= 4; /* GPIO_OE */
MAKE_REG32(0x6000D128) &= ~4; /* GPIO_OUT */
/* Set CL_DVFS RSVD0 + TRISTATE, read register to make it stick. */
PINMUX_AUX_DVFS_PWM_0 = 0x11;
(void)PINMUX_AUX_DVFS_PWM_0;
/* Configure I2C. */
PINMUX_AUX_PWR_I2C_SCL_0 = 0x40;
PINMUX_AUX_PWR_I2C_SDA_0 = 0x40;
/* Enable clock to CL_DVFS, and set its source/divider. */
CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 = 0x08000000;
CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 = 0xE;
CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 = 0xE;
/* Power on I2C5, wait 5 us, set source + take out of reset. */
CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 = 0x8000;
CLK_RST_CONTROLLER_RST_DEV_H_SET_0 = 0x8000;
timer_wait(5);
CLK_RST_CONTROLLER_CLK_SOURCE_I2C5_0 = 0x4;
CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 = 0x8000;
/* Enable the PMIC, wait 2ms. */
i2c_enable_pmic();
timer_wait(2000);
/* Enable power to the CRAIL partition. */
cluster_pmc_enable_partition(1, 0x100);
/* Remove SW clamp to CRAIL. */
APBDEV_PMC_SET_SW_CLAMP_0 = 0;
APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = 1;
while (APBDEV_PMC_CLAMP_STATUS_0 & 1) { }
/* Nintendo manually counts down from 8. I am not sure why this happens. */
{
volatile int32_t counter = 8;
while (counter >= 0) {
counter--;
}
}
/* Power off I2C5. */
CLK_RST_CONTROLLER_RST_DEV_H_SET_0 = 0x8000;
CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 = 0x8000;
/* Disable clock to CL_DVFS */
CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 = 0x08000000;
/* Perform RAM repair if necessary. */
flow_perform_ram_repair();
/* Enable power to the non-CPU partition. */
cluster_pmc_enable_partition(0x8000, 0x10F);
/* Enable clock to PLLP_OUT_CPU, wait 2 us. */
CLK_RST_CONTROLLER_CLK_ENB_Y_SET_0 = 0x80000000;
timer_wait(2);
/* Enable clock to CPU, CPUG, wait 10 us. */
CLK_RST_CONTROLLER_CLK_ENB_L_SET_0 = 1;
CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 = 1;
timer_wait(10);
/* Set CPU clock sources to PLLP_OUT_0 + state to RUN, wait 10 us. */
CLK_RST_CONTROLLER_CCLKG_BURST_POLICY_0 = 0x20004444;
CLK_RST_CONTROLLER_CCLKP_BURST_POLICY_0 = 0x20004444;
timer_wait(10);
/* Take non-CPU out of reset (write CLR_NONCPURESET). */
CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = 0x20000000;
}
void cluster_power_on_cpu(void) {
/* Enable power to CE0 partition. */
cluster_pmc_enable_partition(0x4000, 0x10E);
/* Clear CPU reset. */
CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = 0x10001;
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_CLUSTER_H
#define EXOSPHERE_WARMBOOT_BIN_CLUSTER_H
#include <stdint.h>
#include "utils.h"
#define MSELECT_CONFIG_0 MAKE_REG32(0x50060000)
void cluster_initialize_cpu(void);
void cluster_power_on_cpu(void);
#endif

33
exosphere/lp0fw/src/emc.c Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2018 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 "utils.h"
#include "lp0.h"
#include "emc.h"
#include "pmc.h"
#include "timer.h"
void emc_configure_pmacro_training(void) {
/* Set DISABLE_CFG_BYTEN for all N. */
EMC_PMACRO_CFG_PM_GLOBAL_0_0 = 0xFF0000;
/* Set CHN_TRAINING_E_WRPTR for channel 0 + channel 1. */
EMC_PMACRO_TRAINING_CTRL_0_0 = 8;
EMC_PMACRO_TRAINING_CTRL_1_0 = 8;
/* Clear DISABLE_CFG_BYTEN for all N. */
EMC_PMACRO_CFG_PM_GLOBAL_0_0 = 0x0;
}

71
exosphere/lp0fw/src/emc.h Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_EMC_H
#define EXOSPHERE_WARMBOOT_BIN_EMC_H
#include "utils.h"
#define EMC_BASE (0x7001B000)
#define EMC0_BASE (0x7001E000)
#define EMC1_BASE (0x7001F000)
#define MAKE_EMC_REG(ofs) (MAKE_REG32(EMC_BASE + ofs))
#define MAKE_EMC0_REG(ofs) (MAKE_REG32(EMC0_BASE + ofs))
#define MAKE_EMC1_REG(ofs) (MAKE_REG32(EMC1_BASE + ofs))
#define EMC_CFG_0 MAKE_EMC_REG(0x00C)
#define EMC_ADR_CFG_0 MAKE_EMC_REG(0x10)
#define EMC_TIMING_CONTROL_0 MAKE_EMC_REG(0x028)
#define EMC_SELF_REF_0 MAKE_EMC_REG(0x0E0)
#define EMC_MRW_0 MAKE_EMC_REG(0x0E8)
#define EMC_FBIO_CFG5_0 MAKE_EMC_REG(0x104)
#define EMC_MRW3_0 MAKE_EMC_REG(0x138)
#define EMC_AUTO_CAL_CONFIG_0 MAKE_EMC_REG(0x2A4)
#define EMC_REQ_CTRL_0 MAKE_EMC_REG(0x2B0)
#define EMC_EMC_STATUS_0 MAKE_EMC_REG(0x2B4)
#define EMC0_EMC_STATUS_0 MAKE_EMC0_REG(0x2B4)
#define EMC1_EMC_STATUS_0 MAKE_EMC1_REG(0x2B4)
#define EMC_CFG_DIG_DLL_0 MAKE_EMC_REG(0x2BC)
#define EMC0_CFG_DIG_DLL_0 MAKE_EMC0_REG(0x2BC)
#define EMC1_CFG_DIG_DLL_0 MAKE_EMC1_REG(0x2BC)
#define EMC_ZCAL_INTERVAL_0 MAKE_EMC_REG(0x2E0)
#define EMC_PMC_SCRATCH3_0 MAKE_EMC_REG(0x448)
#define EMC_FBIO_CFG7_0 MAKE_EMC_REG(0x584)
#define EMC_PMACRO_CFG_PM_GLOBAL_0_0 MAKE_EMC_REG(0xC30)
#define EMC_PMACRO_TRAINING_CTRL_0_0 MAKE_EMC_REG(0xCF8)
#define EMC_PMACRO_TRAINING_CTRL_1_0 MAKE_EMC_REG(0xCFC)
void emc_configure_pmacro_training(void);
#endif

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018 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 <stdint.h>
#include "utils.h"
#include "flow.h"
void flow_perform_ram_repair(void) {
/* Perform repair only if not active cluster. */
if (!(FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 & 1)) {
/* Set REQ, to begin RAM repair. */
FLOW_CTLR_RAM_REPAIR_0 = 1;
/* Wait for STS to say RAM repair has completed. */
while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)) { }
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_FLOW_CTLR_H
#define EXOSPHERE_WARMBOOT_BIN_FLOW_CTLR_H
#include <stdint.h>
#include <stdbool.h>
#include "utils.h"
#define FLOW_BASE (0x60007000)
#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_BASE + ofs)
#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004)
#define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040)
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098)
void flow_perform_ram_repair(void);
#endif

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2018 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 <stdint.h>
#include "utils.h"
#include "fuse.h"
#include "car.h"
#include "pmc.h"
#define NUM_FUSE_BYPASS_ENTRIES 0
bool fuse_check_downgrade_status(void) {
/* We aren't going to implement anti-downgrade. */
return false;
}
void fuse_disable_programming(void) {
FUSE_REGS->FUSE_DIS_PGM = 1;
}
static fuse_bypass_data_t g_fuse_bypass_entries[NUM_FUSE_BYPASS_ENTRIES] = {
/* No entries here. */
};
void fuse_configure_fuse_bypass(void) {
/* Enable fuses in CAR? This seems to affect fuse data visibility. */
CLK_RST_CONTROLLER_MISC_CLK_ENB_0 |= 0x10000000;
/* Configure bypass/override, only if programming is allowed. */
if (!(FUSE_REGS->FUSE_DIS_PGM & 1)) {
/* Enable write access. */
FUSE_REGS->FUSE_WRITE_ACCESS = (FUSE_REGS->FUSE_WRITE_ACCESS & ~0x1) | 0x10000;
/* Enable fuse bypass config. */
FUSE_REGS->FUSE_FUSEBYPASS = 1;
/* Override fuses. */
for (size_t i = 0; i < NUM_FUSE_BYPASS_ENTRIES; i++) {
MAKE_FUSE_REG(g_fuse_bypass_entries[i].offset) = g_fuse_bypass_entries[i].value;
}
/* Disable fuse write access. */
FUSE_REGS->FUSE_WRITE_ACCESS |= 1;
/* Enable fuse bypass config. */
/* I think this is a bug, and Nintendo meant to write 0 here? */
FUSE_REGS->FUSE_FUSEBYPASS = 1;
/* This...clears the disable programming bit(?). */
/* I have no idea why this happens. What? */
/* This is probably also either a bug or does nothing. */
/* Is this bit even clearable? */
FUSE_REGS->FUSE_DIS_PGM &= 0xFFFFFFFE;
/* Restore saved private key disable bit. */
FUSE_REGS->FUSE_PRIVATEKEYDISABLE |= (APBDEV_PMC_SECURE_SCRATCH21_0 & 0x10);
/* Lock private key disable secure scratch. */
APBDEV_PMC_SEC_DISABLE2_0 |= 0x4000000;
}
}

202
exosphere/lp0fw/src/fuse.h Normal file
View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_FUSE_H
#define EXOSPHERE_WARMBOOT_BIN_FUSE_H
#include <stdbool.h>
#include <stdint.h>
#include "utils.h"
typedef struct {
uint32_t FUSE_CTRL;
uint32_t FUSE_REG_ADDR;
uint32_t FUSE_REG_READ;
uint32_t FUSE_REG_WRITE;
uint32_t FUSE_TIME_RD1;
uint32_t FUSE_TIME_RD2;
uint32_t FUSE_TIME_PGM1;
uint32_t FUSE_TIME_PGM2;
uint32_t FUSE_PRIV2INTFC;
uint32_t FUSE_FUSEBYPASS;
uint32_t FUSE_PRIVATEKEYDISABLE;
uint32_t FUSE_DIS_PGM;
uint32_t FUSE_WRITE_ACCESS;
uint32_t FUSE_PWR_GOOD_SW;
uint32_t _0x38[0x32];
} fuse_registers_t;
typedef struct {
uint32_t FUSE_PRODUCTION_MODE;
uint32_t _0x4;
uint32_t _0x8;
uint32_t _0xC;
uint32_t FUSE_SKU_INFO;
uint32_t FUSE_CPU_SPEEDO_0;
uint32_t FUSE_CPU_IDDQ;
uint32_t _0x1C;
uint32_t _0x20;
uint32_t _0x24;
uint32_t FUSE_FT_REV;
uint32_t FUSE_CPU_SPEEDO_1;
uint32_t FUSE_CPU_SPEEDO_2;
uint32_t FUSE_SOC_SPEEDO_0;
uint32_t FUSE_SOC_SPEEDO_1;
uint32_t FUSE_SOC_SPEEDO_2;
uint32_t FUSE_SOC_IDDQ;
uint32_t _0x44;
uint32_t FUSE_FA;
uint32_t _0x4C;
uint32_t _0x50;
uint32_t _0x54;
uint32_t _0x58;
uint32_t _0x5C;
uint32_t _0x60;
uint32_t FUSE_PUBLIC_KEY[0x8];
uint32_t FUSE_TSENSOR_1;
uint32_t FUSE_TSENSOR_2;
uint32_t _0x8C;
uint32_t FUSE_CP_REV;
uint32_t _0x94;
uint32_t FUSE_TSENSOR_0;
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG;
uint32_t FUSE_SECURITY_MODE;
uint32_t FUSE_PRIVATE_KEY[0x4];
uint32_t FUSE_DEVICE_KEY;
uint32_t _0xB8;
uint32_t _0xBC;
uint32_t FUSE_RESERVED_SW;
uint32_t FUSE_VP8_ENABLE;
uint32_t FUSE_RESERVED_ODM[0x8];
uint32_t _0xE8;
uint32_t _0xEC;
uint32_t FUSE_SKU_USB_CALIB;
uint32_t FUSE_SKU_DIRECT_CONFIG;
uint32_t _0xF8;
uint32_t _0xFC;
uint32_t FUSE_VENDOR_CODE;
uint32_t FUSE_FAB_CODE;
uint32_t FUSE_LOT_CODE_0;
uint32_t FUSE_LOT_CODE_1;
uint32_t FUSE_WAFER_ID;
uint32_t FUSE_X_COORDINATE;
uint32_t FUSE_Y_COORDINATE;
uint32_t _0x11C;
uint32_t _0x120;
uint32_t FUSE_SATA_CALIB;
uint32_t FUSE_GPU_IDDQ;
uint32_t FUSE_TSENSOR_3;
uint32_t _0x130;
uint32_t _0x134;
uint32_t _0x138;
uint32_t _0x13C;
uint32_t _0x140;
uint32_t _0x144;
uint32_t FUSE_OPT_SUBREVISION;
uint32_t _0x14C;
uint32_t _0x150;
uint32_t FUSE_TSENSOR_4;
uint32_t FUSE_TSENSOR_5;
uint32_t FUSE_TSENSOR_6;
uint32_t FUSE_TSENSOR_7;
uint32_t FUSE_OPT_PRIV_SEC_DIS;
uint32_t FUSE_PKC_DISABLE;
uint32_t _0x16C;
uint32_t _0x170;
uint32_t _0x174;
uint32_t _0x178;
uint32_t _0x17C;
uint32_t FUSE_TSENSOR_COMMON;
uint32_t _0x184;
uint32_t _0x188;
uint32_t _0x18C;
uint32_t _0x190;
uint32_t _0x194;
uint32_t _0x198;
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
uint32_t _0x1A0;
uint32_t _0x1A4;
uint32_t _0x1A8;
uint32_t _0x1AC;
uint32_t _0x1B0;
uint32_t _0x1B4;
uint32_t _0x1B8;
uint32_t _0x1BC;
uint32_t _0x1D0;
uint32_t FUSE_TSENSOR_8;
uint32_t _0x1D8;
uint32_t _0x1DC;
uint32_t _0x1E0;
uint32_t _0x1E4;
uint32_t _0x1E8;
uint32_t _0x1EC;
uint32_t _0x1F0;
uint32_t _0x1F4;
uint32_t _0x1F8;
uint32_t _0x1FC;
uint32_t _0x200;
uint32_t FUSE_RESERVED_CALIB;
uint32_t _0x208;
uint32_t _0x20C;
uint32_t _0x210;
uint32_t _0x214;
uint32_t _0x218;
uint32_t FUSE_TSENSOR_9;
uint32_t _0x220;
uint32_t _0x224;
uint32_t _0x228;
uint32_t _0x22C;
uint32_t _0x230;
uint32_t _0x234;
uint32_t _0x238;
uint32_t _0x23C;
uint32_t _0x240;
uint32_t _0x244;
uint32_t _0x248;
uint32_t _0x24C;
uint32_t FUSE_USB_CALIB_EXT;
uint32_t _0x254;
uint32_t _0x258;
uint32_t _0x25C;
uint32_t _0x260;
uint32_t _0x264;
uint32_t _0x268;
uint32_t _0x26C;
uint32_t _0x270;
uint32_t _0x274;
uint32_t _0x278;
uint32_t _0x27C;
uint32_t FUSE_SPARE_BIT[0x20];
} fuse_chip_registers_t;
#define FUSE_REGS ((volatile fuse_registers_t *)(0x7000F800))
#define FUSE_CHIP_REGS ((volatile fuse_chip_registers_t *)(0x7000F900))
#define MAKE_FUSE_REG(n) MAKE_REG32(0x7000F800 + n)
typedef struct {
uint32_t offset;
uint32_t value;
} fuse_bypass_data_t;
bool fuse_check_downgrade_status(void);
void fuse_configure_fuse_bypass(void);
void fuse_disable_programming(void);
#endif

76
exosphere/lp0fw/src/i2c.c Normal file
View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2018 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 "i2c.h"
#include "timer.h"
/* Prototypes for internal commands. */
void i2c_set_test_master_config_load(void);
void i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes);
void i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b);
/* Load hardware config for I2C5. */
void i2c_set_test_master_config_load(void) {
/* Set MSTR_CONFIG_LOAD. */
I2C_I2C_CONFIG_LOAD_0 = 0x1;
while (I2C_I2C_CONFIG_LOAD_0 & 1) {
/* Wait forever until it's unset. */
}
}
/* Writes a value to an i2c device. */
void i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) {
if (num_bytes > 4) {
return;
}
/* Set device for 7-bit mode. */
I2C_I2C_CMD_ADDR0_0 = device << 1;
/* Load in data to write. */
I2C_I2C_CMD_DATA1_0 = val;
/* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800;
i2c_set_test_master_config_load();
/* Config |= SEND; */
I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800 | 0x200;
while (I2C_I2C_STATUS_0 & 0x100) {
/* Wait until not busy. */
}
while (I2C_I2C_STATUS_0 & 0xF) {
/* Wait until write successful. */
}
}
/* Writes a byte val to reg for given device. */
void i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) {
uint32_t val = (reg) | (b << 8);
/* Write 1 byte (reg) + 1 byte (value) */
i2c_write(device, val, 2);
}
/* Enable the PMIC. */
void i2c_enable_pmic(void) {
/* Write 00 to Device 27 Reg 00. */
i2c_send_byte_command(27, 0, 0x80);
}

48
exosphere/lp0fw/src/i2c.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_I2C_H
#define EXOSPHERE_WARMBOOT_BIN_I2C_H
#include "utils.h"
/* I2C_BASE = I2C5. */
#define I2C_BASE (0x7000D000)
#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs))
#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000)
#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004)
#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C)
#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C)
#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068)
#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C)
#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084)
#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088)
#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C)
void i2c_enable_pmic(void);
#endif

98
exosphere/lp0fw/src/lp0.c Normal file
View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2018 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 "utils.h"
#include "lp0.h"
#include "mc.h"
#include "pmc.h"
#include "misc.h"
#include "fuse.h"
#include "car.h"
#include "emc.h"
#include "cluster.h"
#include "flow.h"
#include "timer.h"
#include "secmon.h"
void reboot(void) {
/* Write MAIN_RST */
APBDEV_PMC_CNTRL_0 = 0x10;
while (true) {
/* Wait for reboot. */
}
}
void lp0_entry_main(warmboot_metadata_t *meta) {
const uint32_t target_firmware = meta->target_firmware;
/* Before doing anything else, ensure some sanity. */
if (meta->magic != WARMBOOT_MAGIC || target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX) {
reboot();
}
/* [4.0.0+] First thing warmboot does is disable BPMP access to memory. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) {
disable_bpmp_access_to_dram();
}
/* Configure debugging depending on FUSE_PRODUCTION_MODE */
misc_configure_device_dbg_settings();
/* Check for downgrade. */
/* NOTE: We implemented this as "return false" */
if (fuse_check_downgrade_status()) {
reboot();
}
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_300) {
/* Nintendo's firmware checks APBDEV_PMC_SECURE_SCRATCH32_0 against a per-warmboot binary value here. */
/* We won't bother with that. */
if (false /* APBDEV_PMC_SECURE_SCRATCH32_0 == WARMBOOT_MAGIC_NUMBER */) {
reboot();
}
}
/* TODO: Check that we're running at the correct physical address. */
/* Setup fuses, disable bypass. */
fuse_configure_fuse_bypass();
/* Configure oscillators/timing in CAR. */
car_configure_oscillators();
/* Restore RAM configuration. */
misc_restore_ram_svop();
emc_configure_pmacro_training();
/* Setup clock output for all devices, working around mbist bug. */
car_mbist_workaround();
/* Initialize the CPU cluster. */
cluster_initialize_cpu();
secmon_restore_to_tzram(target_firmware);
/* Power on the CPU cluster. */
cluster_power_on_cpu();
/* Nintendo clears most of warmboot.bin out of IRAM here. We're not gonna bother. */
/* memset( ... ); */
const uint32_t halt_val = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x40000000 : 0x50000000;
while (true) {
/* Halt the BPMP. */
FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val;
}
}

35
exosphere/lp0fw/src/lp0.h Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_LP0_H
#define EXOSPHERE_WARMBOOT_BIN_LP0_H
#include "utils.h"
/* WBT0 */
#define WARMBOOT_MAGIC 0x30544257
typedef struct {
uint32_t magic;
uint32_t target_firmware;
uint32_t padding[2];
} warmboot_metadata_t;
void lp0_entry_main(warmboot_metadata_t *meta);
void __attribute__((noreturn)) reboot(void);
#endif

40
exosphere/lp0fw/src/mc.c Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2018 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 <stdint.h>
#include "mc.h"
#include "utils.h"
void disable_bpmp_access_to_dram(void) {
/* Modify carveout 4 to prevent BPMP access to dram (TZ will fix it). */
volatile security_carveout_t *carveout = (volatile security_carveout_t *)(MC_BASE + 0xC08 + 0x50 * (4 - CARVEOUT_ID_MIN));
carveout->paddr_low = 0;
carveout->paddr_high = 0;
carveout->size_big_pages = 1; /* 128 KiB */
carveout->client_access_0 = 0;
carveout->client_access_1 = 0;
carveout->client_access_2 = 0;
carveout->client_access_3 = 0;
carveout->client_access_4 = 0;
carveout->client_force_internal_access_0 = BIT(CSR_AVPCARM7R);
carveout->client_force_internal_access_1 = BIT(CSW_AVPCARM7W);
carveout->client_force_internal_access_2 = 0;
carveout->client_force_internal_access_3 = 0;
carveout->client_force_internal_access_4 = 0;
/* Set config to LOCKED, TZ-SECURE, untranslated addresses only. */
carveout->config = 0x8F;
}

614
exosphere/lp0fw/src/mc.h Normal file
View File

@ -0,0 +1,614 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_MC_H
#define EXOSPHERE_WARMBOOT_BIN_MC_H
#include <stdint.h>
#define MC_BASE_PHYS 0x70019000
#define MC_BASE (MC_BASE_PHYS)
#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n)
#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 0x34
#define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_PPCS1_ASID 0x298
#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
/* Virtual aliases */
#define VIRT_MC_SECURITY_CFG3 MAKE_MC_REG(MC_SECURITY_CFG3)
/* Memory Controller clients */
#define CLIENT_ACCESS_NUM_CLIENTS 32
typedef enum {
/* _ACCESS0 */
CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
/* _ACCESS1 */
CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
/* _ACCESS2 */
CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
/* _ACCESS3 */
CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
/* _ACCESS4 */
CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4))
} McClient;
/* Memory Controller carveouts */
#define CARVEOUT_ID_MIN 1
#define CARVEOUT_ID_MAX 5
typedef struct {
uint32_t config;
uint32_t paddr_low;
uint32_t paddr_high;
uint32_t size_big_pages;
uint32_t client_access_0;
uint32_t client_access_1;
uint32_t client_access_2;
uint32_t client_access_3;
uint32_t client_access_4;
uint32_t client_force_internal_access_0;
uint32_t client_force_internal_access_1;
uint32_t client_force_internal_access_2;
uint32_t client_force_internal_access_3;
uint32_t client_force_internal_access_4;
uint8_t padding[0x18];
} security_carveout_t;
void disable_bpmp_access_to_dram(void);
#endif

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2018 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 <stdint.h>
#include "utils.h"
#include "misc.h"
#include "fuse.h"
#include "sysreg.h"
#include "pmc.h"
void misc_configure_device_dbg_settings(void) {
/* Enable RTCK daisychaining by setting TBE bit. */
APB_MISC_PP_CONFIG_CTL_0 = 0x80;
/* Literally none of this is documented in the TRM, lol. */
if (FUSE_CHIP_REGS->FUSE_SECURITY_MODE == 1) {
uint32_t secure_boot_val = 0b0100; /* Sets NIDEN for aarch64. */
uint32_t misc_val = 0x40;
if (APBDEV_PMC_STICKY_BITS_0 & 0x40) {
misc_val = 0x0;
} else {
secure_boot_val = 0b1101; /* Sets SPNIDEN, NIDEN, DBGEN for aarch64. */
}
SB_PFCFG_0 = (SB_PFCFG_0 & ~0b1111) | secure_boot_val; /* Configures debug bits. */
APB_MISC_PP_CONFIG_CTL_0 |= misc_val; /* Undocumented, seems to control invasive debugging/JTAG. */
}
/* Set sticky bits based SECURITY_MODE. */
APBDEV_PMC_STICKY_BITS_0 |= FUSE_CHIP_REGS->FUSE_SECURITY_MODE;
/* Set E_INPUT in PINMUX_AUX_GPIO_PA6_0 */
PINMUX_AUX_GPIO_PA6_0 |= 0x40;
}
void misc_restore_ram_svop(void) {
/* This sets CFG2TMC_RAM_SVOP_PDP to 0x2. */
APB_MISC_GP_ASDBGREG_0 = (APB_MISC_GP_ASDBGREG_0 & 0xFCFFFFFF) | 0x02000000;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_MISC_H
#define EXOSPHERE_WARMBOOT_BIN_MISC_H
#include <stdint.h>
#include "utils.h"
#define MISC_BASE (0x70000000)
#define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n)
#define APB_MISC_PP_CONFIG_CTL_0 MAKE_MISC_REG(0x024)
#define APB_MISC_GP_ASDBGREG_0 MAKE_MISC_REG(0x810)
#define PINMUX_AUX_PWR_I2C_SCL_0 MAKE_MISC_REG(0x30DC)
#define PINMUX_AUX_PWR_I2C_SDA_0 MAKE_MISC_REG(0x30E0)
#define PINMUX_AUX_DVFS_PWM_0 MAKE_MISC_REG(0x3184)
#define PINMUX_AUX_GPIO_PA6_0 MAKE_MISC_REG(0x3244)
void misc_configure_device_dbg_settings(void);
void misc_restore_ram_svop(void);
#endif

69
exosphere/lp0fw/src/pmc.h Normal file
View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_PMC_H
#define EXOSPHERE_WARMBOOT_BIN_PMC_H
#include "utils.h"
#define PMC_BASE (0x7000E400)
#define MAKE_PMC_REG(ofs) (MAKE_REG32(PMC_BASE + ofs))
#define APBDEV_PMC_CNTRL_0 MAKE_PMC_REG(0x000)
#define APBDEV_PMC_DPD_SAMPLE_0 MAKE_PMC_REG(0x020)
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x024)
#define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C)
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x030)
#define APBDEV_PMC_REMOVE_CLAMPING_CMD_0 MAKE_PMC_REG(0x034)
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038)
#define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080)
#define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084)
#define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098)
#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818)
#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4)
#define APBDEV_PMC_STICKY_BITS_0 MAKE_PMC_REG(0x2C0)
#define APBDEV_PMC_SEC_DISABLE2_0 MAKE_PMC_REG(0x2C4)
#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8)
#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334)
#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360)
#define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_PMC_REG(0x368)
#define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_PMC_REG(0x36C)
#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_PMC_REG(0xB18)
#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_PMC_REG(0xB1C)
#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_PMC_REG(0xB20)
#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_PMC_REG(0xB24)
#define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C)
#define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460)
#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464)
#define APBDEV_PMC_IO_DPD4_STATUS_0 MAKE_PMC_REG(0x468)
#define APBDEV_PMC_SET_SW_CLAMP_0 MAKE_PMC_REG(0x47C)
#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4)
#endif

252
exosphere/lp0fw/src/se.c Normal file
View File

@ -0,0 +1,252 @@
/*
* Copyright (c) 2018 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 <string.h>
#include "utils.h"
#include "lp0.h"
#include "se.h"
static void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size);
/* Initialize a SE linked list. */
static void __attribute__((__noinline__)) ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
ll->num_entries = 0; /* 1 Entry. */
if (buffer != NULL) {
ll->addr_info.address = (uint32_t) buffer;
ll->addr_info.size = (uint32_t) size;
} else {
ll->addr_info.address = 0;
ll->addr_info.size = 0;
}
}
void se_check_error_status_reg(void) {
if (se_get_regs()->ERR_STATUS_REG) {
reboot();
}
}
void se_check_for_error(void) {
volatile tegra_se_t *se = se_get_regs();
if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) {
reboot();
}
}
void se_verify_flags_cleared(void) {
if (se_get_regs()->FLAGS_REG & 3) {
reboot();
}
}
void clear_aes_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
reboot();
}
/* Zero out the whole keyslot and IV. */
for (unsigned int i = 0; i < 0x10; i++) {
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
se->AES_KEYTABLE_DATA = 0;
}
}
void clear_rsa_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX) {
reboot();
}
/* Zero out the whole keyslot. */
for (unsigned int i = 0; i < 0x40; i++) {
/* Select Keyslot Modulus[i] */
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
se->RSA_KEYTABLE_DATA = 0;
}
for (unsigned int i = 0; i < 0x40; i++) {
/* Select Keyslot Expontent[i] */
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
se->RSA_KEYTABLE_DATA = 0;
}
}
void clear_aes_keyslot_iv(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
reboot();
}
for (size_t i = 0; i < (0x10 >> 2); i++) {
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
se->AES_KEYTABLE_DATA = 0;
}
}
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
se_ll_t in_ll;
se_ll_t out_ll;
ll_init(&in_ll, (void *)src, src_size);
ll_init(&out_ll, dst, dst_size);
/* Set the LLs. */
se->IN_LL_ADDR_REG = (uint32_t)(&in_ll);
se->OUT_LL_ADDR_REG = (uint32_t) (&out_ll);
/* Set registers for operation. */
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
se->INT_STATUS_REG = se->INT_STATUS_REG;
se->OPERATION_REG = op;
while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
se_check_for_error();
}
/* Secure AES Functionality. */
void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) {
uint8_t block[0x10] = {0};
if (src_size > sizeof(block) || dst_size > sizeof(block)) {
reboot();
}
/* Load src data into block. */
if (src_size != 0) {
memcpy(block, src, src_size);
}
/* Trigger AES operation. */
se_get_regs()->BLOCK_COUNT_REG = 0;
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
/* Copy output data into dst. */
if (dst_size != 0) {
memcpy(dst, block, dst_size);
}
}
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
reboot();
}
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
se->CRYPTO_REG = keyslot << 24 | 0x100;
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
}
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
reboot();
}
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
se->CRYPTO_REG = keyslot << 24;
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
}
void shift_left_xor_rb(uint8_t *key) {
uint8_t prev_high_bit = 0;
for (unsigned int i = 0; i < 0x10; i++) {
uint8_t cur_byte = key[0xF - i];
key[0xF - i] = (cur_byte << 1) | (prev_high_bit);
prev_high_bit = cur_byte >> 7;
}
if (prev_high_bit) {
key[0xF] ^= 0x87;
}
}
void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
reboot();
}
/* Generate the derived key, to be XOR'd with final output block. */
uint8_t ALIGN(16) derived_key[0x10] = {0};
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
shift_left_xor_rb(derived_key);
if (data_size & 0xF) {
shift_left_xor_rb(derived_key);
}
se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
se->CRYPTO_REG = (keyslot << 24) | (0x145);
clear_aes_keyslot_iv(keyslot);
unsigned int num_blocks = (data_size + 0xF) >> 4;
/* Handle aligned blocks. */
if (num_blocks > 1) {
se->BLOCK_COUNT_REG = num_blocks - 2;
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
se->CRYPTO_REG |= 0x80;
}
/* Create final block. */
uint8_t ALIGN(16) last_block[0x10] = {0};
if (data_size & 0xF) {
memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF);
last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */
} else if (data_size >= 0x10) {
memcpy(last_block, data + data_size - 0x10, 0x10);
}
for (unsigned int i = 0; i < 0x10; i++) {
last_block[i] ^= derived_key[i];
}
/* Perform last operation. */
se->BLOCK_COUNT_REG = 0;
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
/* Copy output CMAC. */
for (unsigned int i = 0; i < (cmac_size >> 2); i++) {
((uint32_t *)cmac)[i] = ((volatile uint32_t *)se->HASH_RESULT_REG)[i];
}
}
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202);
}
void se_aes_256_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
reboot();
}
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY) | (0x202 << 16);
se->CRYPTO_REG = (keyslot << 24) | 0x66;
clear_aes_keyslot_iv(keyslot);
se->BLOCK_COUNT_REG = (src_size >> 4) - 1;
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
}

188
exosphere/lp0fw/src/se.h Normal file
View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_SE_H
#define EXOSPHERE_WARMBOOT_BIN_SE_H
#define SE_BASE 0x70012000
#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n)
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
#define KEYSLOT_SWITCH_SRKGENKEY 0x8
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
#define KEYSLOT_SWITCH_TEMPKEY 0x9
#define KEYSLOT_SWITCH_SESSIONKEY 0xA
#define KEYSLOT_SWITCH_RNGKEY 0xB
#define KEYSLOT_SWITCH_MASTERKEY 0xC
#define KEYSLOT_SWITCH_DEVICEKEY 0xD
/* This keyslot was added in 4.0.0. */
#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD
#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE
#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF
/* This keyslot was added in 5.0.0. */
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
#define KEYSLOT_AES_MAX 0x10
#define KEYSLOT_RSA_MAX 0x2
#define KEYSIZE_AES_MAX 0x20
#define KEYSIZE_RSA_MAX 0x100
#define ALG_SHIFT (12)
#define ALG_DEC_SHIFT (8)
#define ALG_NOP (0 << ALG_SHIFT)
#define ALG_AES_ENC (1 << ALG_SHIFT)
#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP)
#define ALG_RNG (2 << ALG_SHIFT)
#define ALG_SHA (3 << ALG_SHIFT)
#define ALG_RSA (4 << ALG_SHIFT)
#define DST_SHIFT (2)
#define DST_MEMORY (0 << DST_SHIFT)
#define DST_HASHREG (1 << DST_SHIFT)
#define DST_KEYTAB (2 << DST_SHIFT)
#define DST_SRK (3 << DST_SHIFT)
#define DST_RSAREG (4 << DST_SHIFT)
#define ENCMODE_SHIFT (24)
#define DECMODE_SHIFT (16)
#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT)
#define HASH_DISABLE (0x0)
#define HASH_ENABLE (0x1)
#define OP_ABORT 0
#define OP_START 1
#define OP_RESTART 2
#define OP_CTX_SAVE 3
#define OP_RESTART_IN 4
#define CTX_SAVE_SRC_SHIFT 29
#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_KEY_LOW_BITS 0
#define CTX_SAVE_KEY_HIGH_BITS 1
#define CTX_SAVE_KEY_ORIGINAL_IV 2
#define CTX_SAVE_KEY_UPDATED_IV 3
#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24
#define CTX_SAVE_KEY_INDEX_SHIFT 8
#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16
#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12
#define RSA_2048_BYTES 0x100
typedef struct {
uint32_t _0x0;
uint32_t _0x4;
uint32_t OPERATION_REG;
uint32_t INT_ENABLE_REG;
uint32_t INT_STATUS_REG;
uint32_t CONFIG_REG;
uint32_t IN_LL_ADDR_REG;
uint32_t _0x1C;
uint32_t _0x20;
uint32_t OUT_LL_ADDR_REG;
uint32_t _0x28;
uint32_t _0x2C;
uint8_t HASH_RESULT_REG[0x20];
uint8_t _0x50[0x20];
uint32_t CONTEXT_SAVE_CONFIG_REG;
uint8_t _0x74[0x18C];
uint32_t SHA_CONFIG_REG;
uint32_t SHA_MSG_LENGTH_REG;
uint32_t _0x208;
uint32_t _0x20C;
uint32_t _0x210;
uint32_t SHA_MSG_LEFT_REG;
uint32_t _0x218;
uint32_t _0x21C;
uint32_t _0x220;
uint32_t _0x224;
uint8_t _0x228[0x58];
uint32_t AES_KEY_READ_DISABLE_REG;
uint32_t AES_KEYSLOT_FLAGS[0x10];
uint8_t _0x2C4[0x3C];
uint32_t _0x300;
uint32_t CRYPTO_REG;
uint32_t CRYPTO_CTR_REG[4];
uint32_t BLOCK_COUNT_REG;
uint32_t AES_KEYTABLE_ADDR;
uint32_t AES_KEYTABLE_DATA;
uint32_t _0x324;
uint32_t _0x328;
uint32_t _0x32C;
uint32_t CRYPTO_KEYTABLE_DST_REG;
uint8_t _0x334[0xC];
uint32_t RNG_CONFIG_REG;
uint32_t RNG_SRC_CONFIG_REG;
uint32_t RNG_RESEED_INTERVAL_REG;
uint8_t _0x34C[0xB4];
uint32_t RSA_CONFIG;
uint32_t RSA_KEY_SIZE_REG;
uint32_t RSA_EXP_SIZE_REG;
uint32_t RSA_KEY_READ_DISABLE_REG;
uint32_t RSA_KEYSLOT_FLAGS[2];
uint32_t _0x418;
uint32_t _0x41C;
uint32_t RSA_KEYTABLE_ADDR;
uint32_t RSA_KEYTABLE_DATA;
uint8_t RSA_OUTPUT[0x100];
uint8_t _0x528[0x2D8];
uint32_t FLAGS_REG;
uint32_t ERR_STATUS_REG;
uint32_t _0x808;
uint32_t SPARE_0;
uint32_t _0x810;
uint32_t _0x814;
uint32_t _0x818;
uint32_t _0x81C;
uint8_t _0x820[0x17E0];
} tegra_se_t;
typedef struct {
uint32_t address;
uint32_t size;
} se_addr_info_t;
typedef struct {
uint32_t num_entries; /* Set to total entries - 1 */
se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */
} se_ll_t;
static inline volatile tegra_se_t *se_get_regs(void) {
return (volatile tegra_se_t *)SE_BASE;
}
void se_check_error_status_reg(void);
void se_check_for_error(void);
void se_verify_flags_cleared(void);
void clear_aes_keyslot(unsigned int keyslot);
void clear_rsa_keyslot(unsigned int keyslot);
void clear_aes_keyslot_iv(unsigned int keyslot);
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_aes_256_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
#endif

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2018 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 <stdint.h>
#include "utils.h"
#include "lp0.h"
#include "secmon.h"
#include "se.h"
#include "fuse.h"
#include "pmc.h"
/* "private" functions. */
static bool secmon_should_clear_aes_keyslot(unsigned int keyslot);
static void secmon_clear_unused_keyslots(void);
static void secmon_decrypt_saved_image(void *dst, const void *src, size_t size);
void secmon_restore_to_tzram(const uint32_t target_firmware) {
/* Newer warmboot binaries clear the untouched keyslots for safety. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500) {
secmon_clear_unused_keyslots();
}
/* Decrypt Secure Monitor from DRAM into TZRAM. */
void *tzram_src = (void *)(0x80010000);
void *tzram_dst = (void *)(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500 ? 0x7C012000 : 0x7C010000);
const size_t tzram_size = 0xE000;
secmon_decrypt_saved_image(tzram_dst, tzram_src, tzram_size);
/* Nintendo clears DRAM, but I'm not sure why, given they lock out BPMP access to DRAM. */
for (size_t i = 0; i < tzram_size/sizeof(uint32_t); i++) {
((volatile uint32_t *)tzram_src)[i] = 0;
}
/* Make security engine require secure busmaster. */
se_get_regs()->_0x4 = 0;
/* TODO: se_verify_keys_unreadable(); */
/* TODO: pmc_lockout_wb_scratch_registers(); */
/* Disable fuse programming. */
fuse_disable_programming();
}
void secmon_decrypt_saved_image(void *dst, const void *src, size_t size) {
/* First, AES-256-CBC decrypt the image into TZRAM. */
se_aes_256_cbc_decrypt(KEYSLOT_SWITCH_LP0TZRAMKEY, dst, size, src, size);
/* Next, calculate CMAC. */
uint32_t tzram_cmac[4] = {0, 0, 0, 0};
se_compute_aes_256_cmac(KEYSLOT_SWITCH_LP0TZRAMKEY, tzram_cmac, sizeof(tzram_cmac), dst, size);
/* Validate the MAC against saved one in PMC scratch. */
if (tzram_cmac[0] != APBDEV_PMC_SECURE_SCRATCH112_0 ||
tzram_cmac[1] != APBDEV_PMC_SECURE_SCRATCH113_0 ||
tzram_cmac[2] != APBDEV_PMC_SECURE_SCRATCH114_0 ||
tzram_cmac[3] != APBDEV_PMC_SECURE_SCRATCH115_0) {
reboot();
}
/* Clear the PMC scratch registers that hold the CMAC. */
APBDEV_PMC_SECURE_SCRATCH112_0 = 0;
APBDEV_PMC_SECURE_SCRATCH113_0 = 0;
APBDEV_PMC_SECURE_SCRATCH114_0 = 0;
APBDEV_PMC_SECURE_SCRATCH115_0 = 0;
/* Clear keyslot now that we're done with it. */
clear_aes_keyslot(KEYSLOT_SWITCH_LP0TZRAMKEY);
}
bool secmon_should_clear_aes_keyslot(unsigned int keyslot) {
/* We'll just compare keyslot against a hardcoded list of keys. */
static const uint8_t saved_keyslots[6] = {
KEYSLOT_SWITCH_LP0TZRAMKEY,
KEYSLOT_SWITCH_SESSIONKEY,
KEYSLOT_SWITCH_RNGKEY,
KEYSLOT_SWITCH_MASTERKEY,
KEYSLOT_SWITCH_DEVICEKEY,
KEYSLOT_SWITCH_4XOLDDEVICEKEY
};
for (unsigned int i = 0; i < sizeof(saved_keyslots)/sizeof(saved_keyslots[0]); i++) {
if (keyslot == saved_keyslots[i]) {
return false;
}
}
return true;
}
void secmon_clear_unused_keyslots(void) {
/* Clear unused keyslots. */
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
if (secmon_should_clear_aes_keyslot(i)) {
clear_aes_keyslot(i);
}
clear_aes_keyslot_iv(i);
}
for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) {
clear_rsa_keyslot(i);
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_SECMON_H
#define EXOSPHERE_WARMBOOT_BIN_SECMON_H
#include <stdint.h>
#include "utils.h"
void secmon_restore_to_tzram(const uint32_t target_firmware);
#endif

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2018 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 .text.start
/* Warmboot header. */
/* Binary size */
.word __total_size__
.rept 3
.word 0x00000000
.endr
/* RSA modulus */
.rept 0x40
.word 0xFFFFFFFF
.endr
/* Padding */
.rept 4
.word 0x00000000
.endr
/* RSA signature */
.rept 0x40
.word 0xFFFFFFFF
.endr
/* Padding */
.rept 4
.word 0x00000000
.endr
/* Relocation meta */
.word __total_size__
.word _start
.word _start
.word __executable_size__
.global _start
_start:
b crt0
.global _metadata
_metadata:
.ascii "WBT0" /* Magic number */
.word 0x00000000 /* Target firmware. */
.word 0x00000000 /* Reserved */
.word 0x00000000 /* Reserved */
.global crt0
.type crt0, %function
crt0:
@ setup to call lp0_entry_main
ldr sp, =__stack_top__
ldr lr, =reboot
ldr r0, =_metadata
b lp0_entry_main

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_SYSREG_H
#define EXOSPHERE_WARMBOOT_BIN_SYSREG_H
#include <stdint.h>
#define SYSREG_BASE (0x6000C000)
#define SB_BASE (SYSREG_BASE + 0x200)
#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n)
#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n)
#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004)
#define SB_CSR_0 MAKE_SB_REG(0x00)
#define SB_PIROM_START_0 MAKE_SB_REG(0x04)
#define SB_PFCFG_0 MAKE_SB_REG(0x08)
#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C)
#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10)
#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14)
#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18)
#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C)
#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20)
#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24)
#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28)
#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30)
#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34)
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_TIMER_H
#define EXOSPHERE_WARMBOOT_BIN_TIMER_H
#include "utils.h"
#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010)
#define TIMERUS_USEC_CFG_0 MAKE_REG32(0x60005014)
static inline void timer_wait(uint32_t microseconds) {
const uint32_t old_time = TIMERUS_CNTR_1US_0;
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
/* Spin-lock. */
}
}
void spinlock_wait(uint32_t count);
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_WARMBOOT_BIN_UTILS_H
#define EXOSPHERE_WARMBOOT_BIN_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <atmosphere.h>
#define BIT(n) (1u << (n))
#define BITL(n) (1ull << (n))
#define MASK(n) (BIT(n) - 1)
#define MASKL(n) (BITL(n) - 1)
#define MASK2(a,b) (MASK(a) & ~MASK(b))
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
#define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed))
#define ALINLINE __attribute__((always_inline))
#endif

View File

@ -0,0 +1,18 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x4003F000;
__start__ = ABSOLUTE(.);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; }
. = ALIGN(4);
__end__ = ABSOLUTE(.);
}

View File

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

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2018 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 "max77620.h"
#include "i2c.h"
#include "timer.h"
/* Prototypes for internal commands. */
void i2c_load_config(void);
int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes);
int i2c_read(unsigned int device, void *dst, unsigned num_bytes);
int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes);
int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b);
/* Load hardware config for I2C4. */
void i2c_load_config(void) {
/* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */
I2C_I2C_CONFIG_LOAD_0 = 0x25;
/* Wait a bit for master config to be loaded. */
for (unsigned int i = 0; i < 20; i++) {
timer_wait(1);
if (!(I2C_I2C_CONFIG_LOAD_0 & 1)) {
break;
}
}
}
/* Initialize I2C4. */
void i2c_init(void) {
/* Setup divisor, and clear the bus. */
I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001;
I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003;
/* Load hardware configuration. */
i2c_load_config();
/* Wait a while until BUS_CLEAR_DONE is set. */
for (unsigned int i = 0; i < 10; i++) {
timer_wait(20000);
if (I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) {
break;
}
}
/* Read the BUS_CLEAR_STATUS. Result doesn't matter. */
I2C_I2C_BUS_CLEAR_STATUS_0;
/* Read and set the Interrupt Status. */
uint32_t int_status = I2C_INTERRUPT_STATUS_REGISTER_0;
I2C_INTERRUPT_STATUS_REGISTER_0 = int_status;
}
/* Writes a value to an i2c device. */
int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) {
if (num_bytes > 4) {
return 0;
}
/* Set device for 7-bit mode. */
I2C_I2C_CMD_ADDR0_0 = device << 1;
/* Load in data to write. */
I2C_I2C_CMD_DATA1_0 = val;
/* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800;
i2c_load_config();
/* Config |= SEND; */
I2C_I2C_CNFG_0 |= 0x200;
while (I2C_I2C_STATUS_0 & 0x100) {
/* Wait until not busy. */
}
/* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */
return (I2C_I2C_STATUS_0 & 0xF) == 0;
}
/* Reads a value from an i2c device. */
int i2c_read(unsigned device, void *dst, unsigned num_bytes) {
if (num_bytes > 4) {
return 0;
}
/* Set device for 7-bit read mode. */
I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1;
/* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2840;
i2c_load_config();
/* Config |= SEND; */
I2C_I2C_CNFG_0 |= 0x200;
while (I2C_I2C_STATUS_0 & 0x100) {
/* Wait until not busy. */
}
/* Ensure success. */
if ((I2C_I2C_STATUS_0 & 0xF) != 0) {
return 0;
}
uint32_t val = I2C_I2C_CMD_DATA1_0;
for (size_t i = 0; i < num_bytes; i++) {
((uint8_t *)dst)[i] = ((uint8_t *)&val)[i];
}
return 1;
}
/* Queries the value of a register. */
int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes) {
/* Limit output size to 32-bits. */
if (num_bytes > 4) {
return 0;
}
/* Write single byte register ID to device. */
if (!i2c_write(device, r, 1)) {
return 0;
}
return i2c_read(device, dst, num_bytes);
}
/* Writes a byte val to reg for given device. */
int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) {
uint32_t val = (reg) | (b << 8);
/* Write 1 byte (reg) + 1 byte (value) */
return i2c_write(device, val, 2);
}
void i2c_stop_rtc_alarm(void) {
i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x10);
uint8_t val = 0;
for (int i = 0; i < 14; i++) {
if (i2c_query(MAX77620_RTC_I2C_ADDR, 0x0E + i, &val, 1)) {
val &= 0x7F;
i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, 0x0E + i, val);
}
}
i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x01);
}
void i2c_send_shutdown_cmd(void) {
i2c_send_byte_command(MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_REBOOTSTUB_I2C_H
#define EXOSPHERE_REBOOTSTUB_I2C_H
#include "utils.h"
/* I2C_BASE = I2C4. */
#define I2C_BASE (0x7000D000)
#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs))
#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000)
#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004)
#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C)
#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C)
#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068)
#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C)
#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084)
#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088)
#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C)
void i2c_init(void);
void i2c_stop_rtc_alarm(void);
void i2c_send_shutdown_cmd(void);
#endif

View File

@ -0,0 +1,360 @@
/*
* Defining registers address and its bit definitions of MAX77620 and MAX20024
*
* Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2018 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.
*/
#ifndef _MFD_MAX77620_H_
#define _MFD_MAX77620_H_
#define MAX77620_I2C_ADDR 0x3C
#define MAX77620_RTC_I2C_ADDR 0x68
/* RTC Registers */
#define MAX77620_REG_RTCINT 0x00
#define MAX77620_REG_RTCINTM 0x01
#define MAX77620_REG_RTCCNTLM 0x02
#define MAX77620_REG_RTCCNTL 0x03
#define MAX77620_REG_RTCUPDATE0 0x04
#define MAX77620_REG_RTCUPDATE1 0x05
#define MAX77620_REG_RTCSMPL 0x06
#define MAX77620_REG_RTCSEC 0x07
#define MAX77620_REG_RTCMIN 0x08
#define MAX77620_REG_RTCHOUR 0x09
#define MAX77620_REG_RTCDOW 0x0A
#define MAX77620_REG_RTCMONTH 0x0B
#define MAX77620_REG_RTCYEAR 0x0C
#define MAX77620_REG_RTCDOM 0x0D
#define MAX77620_REG_RTCSECA1 0x0E
#define MAX77620_REG_RTCMINA1 0x0F
#define MAX77620_REG_RTCHOURA1 0x10
#define MAX77620_REG_RTCDOWA1 0x11
#define MAX77620_REG_RTCMONTHA1 0x12
#define MAX77620_REG_RTCYEARA1 0x13
#define MAX77620_REG_RTCDOMA1 0x14
#define MAX77620_REG_RTCSECA2 0x15
#define MAX77620_REG_RTCMINA2 0x16
#define MAX77620_REG_RTCHOURA2 0x17
#define MAX77620_REG_RTCDOWA2 0x18
#define MAX77620_REG_RTCMONTHA2 0x19
#define MAX77620_REG_RTCYEARA2 0x1A
#define MAX77620_REG_RTCDOMA2 0x1B
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
#define MAX77620_REG_CNFGGLBL1 0x00
#define MAX77620_REG_CNFGGLBL2 0x01
#define MAX77620_REG_CNFGGLBL3 0x02
#define MAX77620_REG_CNFG1_32K 0x03
#define MAX77620_REG_CNFGBBC 0x04
#define MAX77620_REG_IRQTOP 0x05
#define MAX77620_REG_INTLBT 0x06
#define MAX77620_REG_IRQSD 0x07
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08
#define MAX77620_REG_IRQ_LVL2_L8 0x09
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A
#define MAX77620_REG_ONOFFIRQ 0x0B
#define MAX77620_REG_NVERC 0x0C
#define MAX77620_REG_IRQTOPM 0x0D
#define MAX77620_REG_INTENLBT 0x0E
#define MAX77620_REG_IRQMASKSD 0x0F
#define MAX77620_REG_IRQ_MSK_L0_7 0x10
#define MAX77620_REG_IRQ_MSK_L8 0x11
#define MAX77620_REG_ONOFFIRQM 0x12
#define MAX77620_REG_STATLBT 0x13
#define MAX77620_REG_STATSD 0x14
#define MAX77620_REG_ONOFFSTAT 0x15
/* SD and LDO Registers */
#define MAX77620_REG_SD0 0x16
#define MAX77620_REG_SD1 0x17
#define MAX77620_REG_SD2 0x18
#define MAX77620_REG_SD3 0x19
#define MAX77620_REG_SD4 0x1A
#define MAX77620_REG_DVSSD0 0x1B
#define MAX77620_REG_DVSSD1 0x1C
#define MAX77620_REG_SD0_CFG 0x1D
#define MAX77620_REG_SD1_CFG 0x1E
#define MAX77620_REG_SD2_CFG 0x1F
#define MAX77620_REG_SD3_CFG 0x20
#define MAX77620_REG_SD4_CFG 0x21
#define MAX77620_REG_SD_CFG2 0x22
#define MAX77620_REG_LDO0_CFG 0x23
#define MAX77620_REG_LDO0_CFG2 0x24
#define MAX77620_REG_LDO1_CFG 0x25
#define MAX77620_REG_LDO1_CFG2 0x26
#define MAX77620_REG_LDO2_CFG 0x27
#define MAX77620_REG_LDO2_CFG2 0x28
#define MAX77620_REG_LDO3_CFG 0x29
#define MAX77620_REG_LDO3_CFG2 0x2A
#define MAX77620_REG_LDO4_CFG 0x2B
#define MAX77620_REG_LDO4_CFG2 0x2C
#define MAX77620_REG_LDO5_CFG 0x2D
#define MAX77620_REG_LDO5_CFG2 0x2E
#define MAX77620_REG_LDO6_CFG 0x2F
#define MAX77620_REG_LDO6_CFG2 0x30
#define MAX77620_REG_LDO7_CFG 0x31
#define MAX77620_REG_LDO7_CFG2 0x32
#define MAX77620_REG_LDO8_CFG 0x33
#define MAX77620_REG_LDO8_CFG2 0x34
#define MAX77620_REG_LDO_CFG3 0x35
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
/* LDO Configuration 3 */
#define MAX77620_TRACK4_MASK (1 << 5)
#define MAX77620_TRACK4_SHIFT 5
/* Voltage */
#define MAX77620_SDX_VOLT_MASK 0xFF
#define MAX77620_SD0_VOLT_MASK 0x3F
#define MAX77620_SD1_VOLT_MASK 0x7F
#define MAX77620_LDO_VOLT_MASK 0x3F
#define MAX77620_REG_GPIO0 0x36
#define MAX77620_REG_GPIO1 0x37
#define MAX77620_REG_GPIO2 0x38
#define MAX77620_REG_GPIO3 0x39
#define MAX77620_REG_GPIO4 0x3A
#define MAX77620_REG_GPIO5 0x3B
#define MAX77620_REG_GPIO6 0x3C
#define MAX77620_REG_GPIO7 0x3D
#define MAX77620_REG_PUE_GPIO 0x3E
#define MAX77620_REG_PDE_GPIO 0x3F
#define MAX77620_REG_AME_GPIO 0x40
#define MAX77620_REG_ONOFFCNFG1 0x41
#define MAX77620_REG_ONOFFCNFG2 0x42
/* FPS Registers */
#define MAX77620_REG_FPS_CFG0 0x43
#define MAX77620_REG_FPS_CFG1 0x44
#define MAX77620_REG_FPS_CFG2 0x45
#define MAX77620_REG_FPS_LDO0 0x46
#define MAX77620_REG_FPS_LDO1 0x47
#define MAX77620_REG_FPS_LDO2 0x48
#define MAX77620_REG_FPS_LDO3 0x49
#define MAX77620_REG_FPS_LDO4 0x4A
#define MAX77620_REG_FPS_LDO5 0x4B
#define MAX77620_REG_FPS_LDO6 0x4C
#define MAX77620_REG_FPS_LDO7 0x4D
#define MAX77620_REG_FPS_LDO8 0x4E
#define MAX77620_REG_FPS_SD0 0x4F
#define MAX77620_REG_FPS_SD1 0x50
#define MAX77620_REG_FPS_SD2 0x51
#define MAX77620_REG_FPS_SD3 0x52
#define MAX77620_REG_FPS_SD4 0x53
#define MAX77620_REG_FPS_NONE 0
#define MAX77620_FPS_SRC_MASK 0xC0
#define MAX77620_FPS_SRC_SHIFT 6
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
#define MAX77620_FPS_EN_SRC_MASK 0x06
#define MAX77620_FPS_EN_SRC_SHIFT 1
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
#define MAX77620_FPS_ENFPS_SW 0x01
/* Minimum and maximum FPS period time (in microseconds) are
* different for MAX77620 and Max20024.
*/
#define MAX77620_FPS_PERIOD_MIN_US 40
#define MAX20024_FPS_PERIOD_MIN_US 20
#define MAX77620_FPS_PERIOD_MAX_US 2560
#define MAX20024_FPS_PERIOD_MAX_US 5120
#define MAX77620_REG_FPS_GPIO1 0x54
#define MAX77620_REG_FPS_GPIO2 0x55
#define MAX77620_REG_FPS_GPIO3 0x56
#define MAX77620_REG_FPS_RSO 0x57
#define MAX77620_REG_CID0 0x58
#define MAX77620_REG_CID1 0x59
#define MAX77620_REG_CID2 0x5A
#define MAX77620_REG_CID3 0x5B
#define MAX77620_REG_CID4 0x5C
#define MAX77620_REG_CID5 0x5D
#define MAX77620_REG_DVSSD4 0x5E
#define MAX20024_REG_MAX_ADD 0x70
#define MAX77620_CID_DIDM_MASK 0xF0
#define MAX77620_CID_DIDM_SHIFT 4
/* CNCG2SD */
#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1)
#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2)
/* Device Identification Metal */
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
/* Device Indentification OTP */
#define MAX77620_CID5_DIDO(n) ((n) & 0xF)
/* SD CNFG1 */
#define MAX77620_SD_SR_MASK 0xC0
#define MAX77620_SD_SR_SHIFT 6
#define MAX77620_SD_POWER_MODE_MASK 0x30
#define MAX77620_SD_POWER_MODE_SHIFT 4
#define MAX77620_SD_CFG1_ADE_MASK (1 << 3)
#define MAX77620_SD_CFG1_ADE_DISABLE 0
#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3)
#define MAX77620_SD_FPWM_MASK 0x04
#define MAX77620_SD_FPWM_SHIFT 2
#define MAX77620_SD_FSRADE_MASK 0x01
#define MAX77620_SD_FSRADE_SHIFT 0
#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2)
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2)
#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1)
#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0)
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0)
/* LDO_CNFG2 */
#define MAX77620_LDO_POWER_MODE_MASK 0xC0
#define MAX77620_LDO_POWER_MODE_SHIFT 6
#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2)
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
#define MAX77620_LDO_CFG2_ADE_DISABLE 0
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
#define MAX77620_LDO_CFG2_SS_SLOW 0
#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7)
#define MAX77620_IRQ_TOP_SD_MASK (1 << 6)
#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5)
#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4)
#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3)
#define MAX77620_IRQ_TOP_32K_MASK (1 << 2)
#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1)
#define MAX77620_IRQ_LBM_MASK (1 << 3)
#define MAX77620_IRQ_TJALRM1_MASK (1 << 2)
#define MAX77620_IRQ_TJALRM2_MASK (1 << 1)
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0
#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0
#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0
#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4)
#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4)
#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5)
#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6)
#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6)
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0)
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1)
#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2)
#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3)
#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4)
#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5)
#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6)
#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7)
#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2)
#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7)
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2)
#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1)
#define MAX20024_ONOFFCNFG1_CLRSE 0x18
#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7)
#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6)
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5)
#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2)
#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0)
#define MAX77620_GLBLM_MASK (1 << 0)
#define MAX77620_WDTC_MASK 0x3
#define MAX77620_WDTOFFC (1 << 4)
#define MAX77620_WDTSLPC (1 << 3)
#define MAX77620_WDTEN (1 << 2)
#define MAX77620_TWD_MASK 0x3
#define MAX77620_TWD_2s 0x0
#define MAX77620_TWD_16s 0x1
#define MAX77620_TWD_64s 0x2
#define MAX77620_TWD_128s 0x3
#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7)
#define MAX77620_CNFGGLBL1_MPPLD (1 << 6)
#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4))
#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4)
#define MAX77620_CNFGGLBL1_LBDAC 0x0E
#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1)
#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0)
/* CNFG BBC registers */
#define MAX77620_CNFGBBC_ENABLE (1 << 0)
#define MAX77620_CNFGBBC_CURRENT_MASK 0x06
#define MAX77620_CNFGBBC_CURRENT_SHIFT 1
#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18
#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3
#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5)
#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0
#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6
#define MAX77620_FPS_COUNT 3
/* Interrupts */
enum {
MAX77620_IRQ_TOP_GLBL, /* Low-Battery */
MAX77620_IRQ_TOP_SD, /* SD power fail */
MAX77620_IRQ_TOP_LDO, /* LDO power fail */
MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */
MAX77620_IRQ_TOP_RTC, /* RTC */
MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */
MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */
MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */
MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */
MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */
};
/* GPIOs */
enum {
MAX77620_GPIO0,
MAX77620_GPIO1,
MAX77620_GPIO2,
MAX77620_GPIO3,
MAX77620_GPIO4,
MAX77620_GPIO5,
MAX77620_GPIO6,
MAX77620_GPIO7,
MAX77620_GPIO_NR,
};
/* FPS Source */
enum max77620_fps_src {
MAX77620_FPS_SRC_0,
MAX77620_FPS_SRC_1,
MAX77620_FPS_SRC_2,
MAX77620_FPS_SRC_NONE,
MAX77620_FPS_SRC_DEF,
};
enum max77620_chip_id {
MAX77620,
MAX20024,
};
#endif /* _MFD_MAX77620_H_ */

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018 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 "utils.h"
#include "i2c.h"
#include "timer.h"
void do_shutdown(void) {
/* Initialize i2c. */
i2c_init();
/* Stop alarm, shutdown. */
i2c_stop_rtc_alarm();
i2c_send_shutdown_cmd();
while (true) { }
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2018 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 .text.start
.align 4
.global _start
_start:
ldr r0, reboot_type
cmp r0, #0x0
beq do_shutdown
b jump_to_reboot_payload
reboot_type:
.word 0x00000001
.global jump_to_reboot_payload
.type jump_to_reboot_payload, %function
jump_to_reboot_payload:
@ clear all registers
ldr r0, =0x52425430 @ RBT0
mov r1, #0x0
mov r2, #0x0
mov r3, #0x0
mov r4, #0x0
mov r5, #0x0
mov r6, #0x0
mov r7, #0x0
mov r8, #0x0
mov r9, #0x0
mov r10, #0x0
mov r11, #0x0
mov r12, #0x0
mov lr, #0x0
ldr sp, =0x40010000
ldr pc, =0x40010000

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_REBOOTSTUB_TIMER_H
#define EXOSPHERE_REBOOTSTUB_TIMER_H
#include "utils.h"
#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010)
static inline void timer_wait(uint32_t microseconds) {
uint32_t old_time = TIMERUS_CNTR_1US_0;
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
/* Spin-lock. */
}
}
void spinlock_wait(uint32_t count);
#endif

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_REBOOTSTUB_UTILS_H
#define EXOSPHERE_REBOOTSTUB_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define BIT(n) (1u << (n))
#define BITL(n) (1ull << (n))
#define MASK(n) (BIT(n) - 1)
#define MASKL(n) (BITL(n) - 1)
#define MASK2(a,b) (MASK(a) & ~MASK(b))
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
#define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed))
#define ALINLINE __attribute__((always_inline))
#endif

View File

@ -2,46 +2,58 @@
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/libnx/switch_rules
include $(DEVKITARM)/base_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
SOURCES := source
BUILD := build
SOURCES := src
DATA := data
INCLUDES := include
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS := \
-g \
-O2 \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
-fno-inline \
-std=gnu11 \
-Werror \
-Wall \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__
CFLAGS += $(INCLUDE) -D__BPMP__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lnx
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
@ -50,9 +62,14 @@ LIBDIRS := $(PORTLIBS) $(LIBNX)
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
@ -74,77 +91,64 @@ 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 := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I. \
-iquote $(CURDIR)/include/switch/
-I$(CURDIR)/$(BUILD)
.PHONY: clean all
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: lib/$(TARGET).a lib/$(TARGET)d.a
all: $(BUILD)
lib:
$(BUILD):
@[ -d $@ ] || mkdir -p $@
release:
@[ -d $@ ] || mkdir -p $@
debug:
@[ -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
lib/$(TARGET)d.a : lib debug $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=debug OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DDEBUG=1 -Og" \
DEPSDIR=$(CURDIR)/debug \
--no-print-directory -C debug \
-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
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr release debug lib *.bz2
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
all : $(OUTPUT).bin
$(OFILES_SRC) : $(HFILES)
$(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

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

View File

@ -1,5 +1,21 @@
/*
* Copyright (c) 2018 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 "utils.h"
#include "lp0.h"
#include "sc7.h"
#include "emc.h"
#include "pmc.h"
#include "timer.h"

View File

@ -1,3 +1,19 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_BPMPFW_EMC_H
#define EXOSPHERE_BPMPFW_EMC_H

View File

@ -1,3 +1,19 @@
/*
* Copyright (c) 2018 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 "i2c.h"
#include "timer.h"

View File

@ -1,3 +1,19 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_BPMPFW_I2C_H
#define EXOSPHERE_BPMPFW_I2C_H

View File

@ -1,3 +1,19 @@
/*
* Copyright (c) 2018 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/>.
*/
#ifndef EXOSPHERE_BPMPFW_PMC_H
#define EXOSPHERE_BPMPFW_PMC_H

View File

@ -1,5 +1,21 @@
/*
* Copyright (c) 2018 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 "utils.h"
#include "lp0.h"
#include "sc7.h"
#include "i2c.h"
#include "pmc.h"
#include "emc.h"
@ -39,7 +55,7 @@ static void set_pmc_dpd_io_pads(void) {
spinlock_wait(32);
}
void lp0_entry_main(void) {
void sc7_entry_main(void) {
/* Disable the BPMP Cache. */
CACHE_CTRL |= 0xC00;

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