Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6cfbae1ff | ||
|
|
c0fe4f7af7 | ||
|
|
5b219e6f58 | ||
|
|
d55a9d168e | ||
|
|
e1d884960d | ||
|
|
db97dd8d75 | ||
|
|
f96e1d5074 | ||
|
|
e61bb00d7a | ||
|
|
aa761753d7 | ||
|
|
85540d4ad2 |
6
Makefile
6
Makefile
@@ -1,4 +1,8 @@
|
|||||||
TOPTARGETS := all clean dist
|
TOPTARGETS := all clean dist
|
||||||
|
AMSREV := $(shell git rev-parse --short HEAD)
|
||||||
|
ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
|
||||||
|
AMSREV := $(AMSREV)-dirty
|
||||||
|
endif
|
||||||
|
|
||||||
all: fusee creport
|
all: fusee creport
|
||||||
fusee:
|
fusee:
|
||||||
@@ -21,7 +25,7 @@ dist: fusee creport
|
|||||||
$(eval MICROVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MICRO\b' common/include/atmosphere/version.h \
|
$(eval MICROVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MICRO\b' common/include/atmosphere/version.h \
|
||||||
| tr -s [:blank:] \
|
| tr -s [:blank:] \
|
||||||
| cut -d' ' -f3))
|
| cut -d' ' -f3))
|
||||||
$(eval AMSVER = $(MAJORVER).$(MINORVER).$(MICROVER))
|
$(eval AMSVER = $(MAJORVER).$(MINORVER).$(MICROVER)-$(AMSREV))
|
||||||
rm -rf atmosphere-$(AMSVER)
|
rm -rf atmosphere-$(AMSVER)
|
||||||
rm -rf out
|
rm -rf out
|
||||||
mkdir atmosphere-$(AMSVER)
|
mkdir atmosphere-$(AMSVER)
|
||||||
|
|||||||
@@ -19,6 +19,6 @@
|
|||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 7
|
#define ATMOSPHERE_RELEASE_VERSION_MINOR 7
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1
|
#define ATMOSPHERE_RELEASE_VERSION_MICRO 3
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
72
docs/changelog.md
Normal file
72
docs/changelog.md
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Changelog
|
||||||
|
## 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.
|
||||||
@@ -22,5 +22,8 @@ Stratosphère's modules include:
|
|||||||
### Building Atmosphère
|
### Building Atmosphère
|
||||||
A guide to building Atmosphère can be found [here](../docs/building.md).
|
A guide to building Atmosphère can be found [here](../docs/building.md).
|
||||||
|
|
||||||
### Release Roadmap
|
### Upcoming Features
|
||||||
A roadmap of the releases of Atmosphère can be found [here](../docs/roadmap.md).
|
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).
|
||||||
|
|||||||
@@ -53,11 +53,15 @@ When authoring patches, [hactool](https://github.com/SciresM/hactool) can be use
|
|||||||
|
|
||||||
### HBL Support
|
### HBL Support
|
||||||
|
|
||||||
TODO
|
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 (hbl_tid) (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
|
### Button Overrides
|
||||||
|
|
||||||
TODO
|
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
|
### SM MITM Integration
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
# Release Roadmap
|
# Planned Features
|
||||||
## Upcoming Releases
|
The following features are planned to be added in future versions of Atmosphère:
|
||||||
### 0.7
|
+ Thermosphère, a hypervisor-based emunand implementation.
|
||||||
0.7 will be Atmosphère's first official release.
|
+ A feature-rich debugging toolset (a component of Stratosphère).
|
||||||
This release will include:
|
+ 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.
|
||||||
+ Fusée
|
+ This should include a gdbstub implementation, possibly borrowing from Luma3DS's.
|
||||||
+ Supports loading/customizing of arbitrary KIPs from the SD card.
|
+ This API should be additionally usable for RAM Editing/"Cheat Engine" purposes.
|
||||||
+ Supports compile-time defined kernel patches on a per-firmware basis.
|
+ 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.
|
||||||
+ Configurable by editing BCT.ini on the SD card.
|
+ This should support client connections over both Wi-Fi and USB.
|
||||||
+ Atmosphère should also be launchable by the alternative hekate bootloader, for those who prefer it.
|
+ A custom logging system module, providing a means for other Atmosphère components (and possibly Nintendo's own system modules) to log debug output.
|
||||||
+ Exosphère
|
+ This should support logging to the SD card, over Wi-Fi, and over USB.
|
||||||
+ Exosphere is a re-implementation of Nintendo's TrustZone firmware, fully replicating all of its features.
|
+ An application-level plugin system.
|
||||||
+ In addition, it has been extended to provide information on current Atmosphere API version, for homebrew wishing to make use of it.
|
+ 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.
|
||||||
+ Stratosphère
|
+ An AR Code/Gameshark analog implementation, allowing for easy sharing/development of cheat codes to run on device.
|
||||||
+ loader system module
|
+ Further extensions to existing Atmosphère components.
|
||||||
+ Service Manager system module (sm)
|
+ General system stability improvements to enhance the user's experience.
|
||||||
+ Process Manager system module (pm)
|
|
||||||
+ fs.mitm system module
|
|
||||||
+ creport system module
|
|
||||||
|
|||||||
@@ -124,12 +124,14 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) {
|
|||||||
fatalSimple(0xF601);
|
fatalSimple(0xF601);
|
||||||
}
|
}
|
||||||
read_so_far += cur_read_size;
|
read_so_far += cur_read_size;
|
||||||
|
offset += cur_read_size;
|
||||||
} else {
|
} else {
|
||||||
/* Handle padding explicitly. */
|
/* Handle padding explicitly. */
|
||||||
cur_source_ind++;
|
cur_source_ind++;
|
||||||
/* Zero out the padding we skip, here. */
|
/* Zero out the padding we skip, here. */
|
||||||
memset((void *)((uintptr_t)buffer + read_so_far), 0, ((*this->p_source_infos)[cur_source_ind]).virtual_offset - (cur_source->virtual_offset + cur_source->size));
|
memset((void *)((uintptr_t)buffer + read_so_far), 0, ((*this->p_source_infos)[cur_source_ind]).virtual_offset - offset);
|
||||||
read_so_far += ((*this->p_source_infos)[cur_source_ind]).virtual_offset - (cur_source->virtual_offset + cur_source->size);
|
read_so_far += ((*this->p_source_infos)[cur_source_ind]).virtual_offset - offset;
|
||||||
|
offset = ((*this->p_source_infos)[cur_source_ind]).virtual_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
#include "fsmitm_utils.hpp"
|
#include "fsmitm_utils.hpp"
|
||||||
|
|
||||||
|
#include "setsys_mitm_service.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
extern u32 __start__;
|
extern u32 __start__;
|
||||||
|
|
||||||
@@ -86,15 +88,30 @@ void __appExit(void) {
|
|||||||
smExit();
|
smExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreateSettingsMitMServer(void *arg) {
|
||||||
|
MultiThreadedWaitableManager *server_manager = (MultiThreadedWaitableManager *)arg;
|
||||||
|
|
||||||
|
Result rc;
|
||||||
|
if (R_FAILED((rc = setsysInitialize()))) {
|
||||||
|
fatalSimple(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISession<MitMQueryService<SetSysMitMService>> *setsys_query_srv = NULL;
|
||||||
|
MitMServer<SetSysMitMService> *setsys_srv = new MitMServer<SetSysMitMService>(&setsys_query_srv, "set:sys", 60);
|
||||||
|
server_manager->add_waitable(setsys_srv);
|
||||||
|
server_manager->add_waitable(setsys_query_srv);
|
||||||
|
|
||||||
|
svcExitThread();
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Thread worker_thread = {0};
|
Thread worker_thread = {0};
|
||||||
Thread sd_initializer_thread = {0};
|
Thread sd_initializer_thread = {0};
|
||||||
Thread hid_initializer_thread = {0};
|
Thread hid_initializer_thread = {0};
|
||||||
|
Thread set_mitm_setup_thread = {0};
|
||||||
consoleDebugInit(debugDevice_SVC);
|
consoleDebugInit(debugDevice_SVC);
|
||||||
|
|
||||||
consoleDebugInit(debugDevice_SVC);
|
|
||||||
|
|
||||||
if (R_FAILED(threadCreate(&worker_thread, &FsMitMWorker::Main, NULL, 0x20000, 45, 0))) {
|
if (R_FAILED(threadCreate(&worker_thread, &FsMitMWorker::Main, NULL, 0x20000, 45, 0))) {
|
||||||
/* TODO: Panic. */
|
/* TODO: Panic. */
|
||||||
}
|
}
|
||||||
@@ -117,17 +134,26 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: What's a good timeout value to use here? */
|
/* TODO: What's a good timeout value to use here? */
|
||||||
auto server_manager = std::make_unique<MultiThreadedWaitableManager>(5, U64_MAX, 0x20000);
|
MultiThreadedWaitableManager *server_manager = new MultiThreadedWaitableManager(5, U64_MAX, 0x20000);
|
||||||
//auto server_manager = std::make_unique<WaitableManager>(U64_MAX);
|
|
||||||
|
|
||||||
/* Create fsp-srv mitm. */
|
/* Create fsp-srv mitm. */
|
||||||
ISession<MitMQueryService<FsMitMService>> *fs_query_srv = NULL;
|
ISession<MitMQueryService<FsMitMService>> *fs_query_srv = NULL;
|
||||||
MitMServer<FsMitMService> *fs_srv = new MitMServer<FsMitMService>(&fs_query_srv, "fsp-srv", 61);
|
MitMServer<FsMitMService> *fs_srv = new MitMServer<FsMitMService>(&fs_query_srv, "fsp-srv", 61);
|
||||||
server_manager->add_waitable(fs_srv);
|
server_manager->add_waitable(fs_srv);
|
||||||
server_manager->add_waitable(fs_query_srv);
|
server_manager->add_waitable(fs_query_srv);
|
||||||
|
|
||||||
|
/* Create set:sys mitm server, delayed until set:sys is available. */
|
||||||
|
if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) {
|
||||||
|
/* TODO: Panic. */
|
||||||
|
}
|
||||||
|
if (R_FAILED(threadStart(&set_mitm_setup_thread))) {
|
||||||
|
/* TODO: Panic. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Loop forever, servicing our services. */
|
/* Loop forever, servicing our services. */
|
||||||
server_manager->process();
|
server_manager->process();
|
||||||
|
|
||||||
|
delete server_manager;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ static std::atomic_bool g_has_hid_session = false;
|
|||||||
static u64 g_override_key_combination = KEY_R;
|
static u64 g_override_key_combination = KEY_R;
|
||||||
static bool g_override_by_default = true;
|
static bool g_override_by_default = true;
|
||||||
|
|
||||||
|
/* Static buffer for loader.ini contents at runtime. */
|
||||||
|
static char g_config_ini_data[0x800];
|
||||||
|
|
||||||
static bool IsHexadecimal(const char *str) {
|
static bool IsHexadecimal(const char *str) {
|
||||||
while (*str) {
|
while (*str) {
|
||||||
if (isxdigit(*str)) {
|
if (isxdigit(*str)) {
|
||||||
@@ -93,12 +96,7 @@ void Utils::InitializeSdThreadFunc(void *args) {
|
|||||||
fsDirClose(&titles_dir);
|
fsDirClose(&titles_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile config_file;
|
Utils::RefreshConfiguration();
|
||||||
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, "/atmosphere/loader.ini", FS_OPEN_READ, &config_file))) {
|
|
||||||
Utils::LoadConfiguration(&config_file);
|
|
||||||
fsFileClose(&config_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
g_has_initialized = true;
|
g_has_initialized = true;
|
||||||
|
|
||||||
@@ -246,11 +244,14 @@ Result Utils::GetKeysDown(u64 *keys) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::HasOverrideButton(u64 tid) {
|
bool Utils::HasOverrideButton(u64 tid) {
|
||||||
if (tid < 0x0100000000010000ULL) {
|
if (tid < 0x0100000000010000ULL || !IsSdInitialized()) {
|
||||||
/* Disable button override disable for non-applications. */
|
/* Disable button override disable for non-applications. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unconditionally refresh loader.ini contents. */
|
||||||
|
RefreshConfiguration();
|
||||||
|
|
||||||
u64 kDown = 0;
|
u64 kDown = 0;
|
||||||
bool keys_triggered = (R_SUCCEEDED(GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0));
|
bool keys_triggered = (R_SUCCEEDED(GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0));
|
||||||
return IsSdInitialized() && (g_override_by_default ^ keys_triggered);
|
return IsSdInitialized() && (g_override_by_default ^ keys_triggered);
|
||||||
@@ -314,27 +315,24 @@ static int FsMitMIniHandler(void *user, const char *section, const char *name, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Utils::LoadConfiguration(FsFile *f) {
|
void Utils::RefreshConfiguration() {
|
||||||
if (f == NULL) {
|
FsFile config_file;
|
||||||
|
if (R_FAILED(fsFsOpenFile(&g_sd_filesystem, "/atmosphere/loader.ini", FS_OPEN_READ, &config_file))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 size;
|
u64 size;
|
||||||
if (R_FAILED(fsFileGetSize(f, &size))) {
|
if (R_FAILED(fsFileGetSize(&config_file, &size))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = std::min(size, (decltype(size))0x7FF);
|
size = std::min(size, (decltype(size))0x7FF);
|
||||||
|
|
||||||
char *config_str = new char[0x800];
|
/* Read in string. */
|
||||||
if (config_str != NULL) {
|
std::fill(g_config_ini_data, g_config_ini_data + 0x800, 0);
|
||||||
/* Read in string. */
|
size_t r_s;
|
||||||
std::fill(config_str, config_str + 0x800, 0);
|
fsFileRead(&config_file, 0, g_config_ini_data, size, &r_s);
|
||||||
size_t r_s;
|
fsFileClose(&config_file);
|
||||||
fsFileRead(f, 0, config_str, size, &r_s);
|
|
||||||
|
ini_parse_string(g_config_ini_data, FsMitMIniHandler, NULL);
|
||||||
ini_parse_string(config_str, FsMitMIniHandler, NULL);
|
|
||||||
|
|
||||||
delete[] config_str;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -45,5 +45,5 @@ class Utils {
|
|||||||
static Result GetKeysDown(u64 *keys);
|
static Result GetKeysDown(u64 *keys);
|
||||||
static bool HasOverrideButton(u64 tid);
|
static bool HasOverrideButton(u64 tid);
|
||||||
private:
|
private:
|
||||||
static void LoadConfiguration(FsFile *f);
|
static void RefreshConfiguration();
|
||||||
};
|
};
|
||||||
104
stratosphere/fs_mitm/source/setsys_mitm_service.cpp
Normal file
104
stratosphere/fs_mitm/source/setsys_mitm_service.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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 <mutex>
|
||||||
|
#include <switch.h>
|
||||||
|
#include "setsys_mitm_service.hpp"
|
||||||
|
|
||||||
|
#include "mitm_query_service.hpp"
|
||||||
|
#include "debug.hpp"
|
||||||
|
|
||||||
|
static HosMutex g_version_mutex;
|
||||||
|
static bool g_got_version = false;
|
||||||
|
static SetSysFirmwareVersion g_fw_version = {0};
|
||||||
|
|
||||||
|
static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) {
|
||||||
|
std::lock_guard<HosMutex> lock(g_version_mutex);
|
||||||
|
if (!g_got_version) {
|
||||||
|
Result rc = setsysGetFirmwareVersion(&g_fw_version);
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify the output firmware version. */
|
||||||
|
{
|
||||||
|
u32 major, minor, micro;
|
||||||
|
char display_version[sizeof(g_fw_version.display_version)] = {0};
|
||||||
|
|
||||||
|
GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr);
|
||||||
|
snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro);
|
||||||
|
|
||||||
|
memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_got_version = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = g_fw_version;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetSysMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||||
|
Result rc = 0xF601;
|
||||||
|
|
||||||
|
switch (static_cast<SetSysCmd>(cmd_id)) {
|
||||||
|
case SetSysCmd::GetFirmwareVersion:
|
||||||
|
rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||||
|
break;
|
||||||
|
case SetSysCmd::GetFirmwareVersion2:
|
||||||
|
if (kernelAbove300()) {
|
||||||
|
rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version2>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSysMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||||
|
/* No commands need postprocessing. */
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetSysMitMService::handle_deferred() {
|
||||||
|
/* This service is never deferrable. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<Result> SetSysMitMService::get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) {
|
||||||
|
if (out.num_elements != 1) {
|
||||||
|
return {0xF601};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rc = _GetFirmwareVersion(out.pointer);
|
||||||
|
|
||||||
|
/* GetFirmwareVersion sanitizes these fields. */
|
||||||
|
out.pointer->revision_major = 0;
|
||||||
|
out.pointer->revision_minor = 0;
|
||||||
|
|
||||||
|
return {rc};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<Result> SetSysMitMService::get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) {
|
||||||
|
if (out.num_elements != 1) {
|
||||||
|
return {0xF601};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rc = _GetFirmwareVersion(out.pointer);
|
||||||
|
|
||||||
|
return {rc};
|
||||||
|
}
|
||||||
58
stratosphere/fs_mitm/source/setsys_mitm_service.hpp
Normal file
58
stratosphere/fs_mitm/source/setsys_mitm_service.hpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
#include <stratosphere/iserviceobject.hpp>
|
||||||
|
#include "imitmserviceobject.hpp"
|
||||||
|
#include "fsmitm_utils.hpp"
|
||||||
|
|
||||||
|
enum class SetSysCmd {
|
||||||
|
GetFirmwareVersion = 3,
|
||||||
|
GetFirmwareVersion2 = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
class SetSysMitMService : public IMitMServiceObject {
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
SetSysMitMService(Service *s) : IMitMServiceObject(s) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool should_mitm(u64 pid, u64 tid) {
|
||||||
|
/* Only MitM qlaunch, maintenance. */
|
||||||
|
return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetSysMitMService *clone() override {
|
||||||
|
auto new_srv = new SetSysMitMService((Service *)&this->forward_service);
|
||||||
|
this->clone_to(new_srv);
|
||||||
|
return new_srv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clone_to(void *o) override {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
|
||||||
|
virtual void postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
|
||||||
|
virtual Result handle_deferred();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Overridden commands. */
|
||||||
|
std::tuple<Result> get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out);
|
||||||
|
std::tuple<Result> get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out);
|
||||||
|
};
|
||||||
@@ -196,7 +196,7 @@ class ISession : public IWaitable {
|
|||||||
/* TODO: Panic? */
|
/* TODO: Panic? */
|
||||||
}
|
}
|
||||||
IpcParsedCommand r;
|
IpcParsedCommand r;
|
||||||
u64 cmd_id;
|
u64 cmd_id = 0;
|
||||||
|
|
||||||
|
|
||||||
Result retval = ipcParse(&r);
|
Result retval = ipcParse(&r);
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ static u64 g_override_key_combination = KEY_R;
|
|||||||
static bool g_override_by_default = true;
|
static bool g_override_by_default = true;
|
||||||
static u64 g_override_hbl_tid = 0x010000000000100D;
|
static u64 g_override_hbl_tid = 0x010000000000100D;
|
||||||
|
|
||||||
|
/* Static buffer for loader.ini contents at runtime. */
|
||||||
|
static char g_config_ini_data[0x800];
|
||||||
|
|
||||||
Result ContentManagement::MountCode(u64 tid, FsStorageId sid) {
|
Result ContentManagement::MountCode(u64 tid, FsStorageId sid) {
|
||||||
char path[FS_MAX_PATH] = {0};
|
char path[FS_MAX_PATH] = {0};
|
||||||
Result rc;
|
Result rc;
|
||||||
@@ -49,6 +52,10 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) {
|
|||||||
TryMountSdCard();
|
TryMountSdCard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_has_initialized_fs_dev) {
|
||||||
|
RefreshConfigurationData();
|
||||||
|
}
|
||||||
|
|
||||||
if (ShouldOverrideContents() && R_SUCCEEDED(MountCodeNspOnSd(tid))) {
|
if (ShouldOverrideContents() && R_SUCCEEDED(MountCodeNspOnSd(tid))) {
|
||||||
return 0x0;
|
return 0x0;
|
||||||
}
|
}
|
||||||
@@ -259,23 +266,17 @@ static int LoaderIniHandler(void *user, const char *section, const char *name, c
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentManagement::LoadConfiguration(FILE *config) {
|
void ContentManagement::RefreshConfigurationData() {
|
||||||
|
FILE *config = fopen("sdmc:/atmosphere/loader.ini", "r");
|
||||||
if (config == NULL) {
|
if (config == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *config_str = new char[0x800];
|
std::fill(g_config_ini_data, g_config_ini_data + 0x800, 0);
|
||||||
if (config_str != NULL) {
|
fread(g_config_ini_data, 1, 0x7FF, config);
|
||||||
/* Read in string. */
|
|
||||||
std::fill(config_str, config_str + 0x800, 0);
|
|
||||||
fread(config_str, 1, 0x7FF, config);
|
|
||||||
|
|
||||||
ini_parse_string(config_str, LoaderIniHandler, NULL);
|
|
||||||
|
|
||||||
delete[] config_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(config);
|
fclose(config);
|
||||||
|
|
||||||
|
ini_parse_string(g_config_ini_data, LoaderIniHandler, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentManagement::TryMountSdCard() {
|
void ContentManagement::TryMountSdCard() {
|
||||||
@@ -292,7 +293,6 @@ void ContentManagement::TryMountSdCard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (R_SUCCEEDED(fsdevMountSdmc())) {
|
if (R_SUCCEEDED(fsdevMountSdmc())) {
|
||||||
ContentManagement::LoadConfiguration(fopen("sdmc:/atmosphere/loader.ini", "r"));
|
|
||||||
g_has_initialized_fs_dev = true;
|
g_has_initialized_fs_dev = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class ContentManagement {
|
|||||||
|
|
||||||
static bool HasCreatedTitle(u64 tid);
|
static bool HasCreatedTitle(u64 tid);
|
||||||
static void SetCreatedTitle(u64 tid);
|
static void SetCreatedTitle(u64 tid);
|
||||||
static void LoadConfiguration(FILE *config);
|
static void RefreshConfigurationData();
|
||||||
static void TryMountSdCard();
|
static void TryMountSdCard();
|
||||||
|
|
||||||
static bool ShouldReplaceWithHBL(u64 tid);
|
static bool ShouldReplaceWithHBL(u64 tid);
|
||||||
|
|||||||
Reference in New Issue
Block a user