Compare commits
34 Commits
mesosphere
...
meso_build
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d4523041f | ||
|
|
e26e1df07f | ||
|
|
f92de24164 | ||
|
|
a8a90e6324 | ||
|
|
1c71d12d9d | ||
|
|
37738699f2 | ||
|
|
e973ef7533 | ||
|
|
2ee2a4f1ac | ||
|
|
2a2bffeb35 | ||
|
|
d04046ecaf | ||
|
|
f24171dc41 | ||
|
|
5b02c77400 | ||
|
|
2e7214b6fa | ||
|
|
d52179c708 | ||
|
|
388f9e6455 | ||
|
|
c547c7f0e7 | ||
|
|
4138abbefa | ||
|
|
1275eb0bf3 | ||
|
|
5ac9e45d86 | ||
|
|
feba788bc6 | ||
|
|
f4d10a4481 | ||
|
|
ff310a0647 | ||
|
|
85505db9b7 | ||
|
|
48b4dd48a4 | ||
|
|
8d46d901d9 | ||
|
|
1930880270 | ||
|
|
fa0df994ba | ||
|
|
909a1767a6 | ||
|
|
dbe59fd041 | ||
|
|
9b65daf439 | ||
|
|
4acdc899f5 | ||
|
|
76957e502d | ||
|
|
909397233c | ||
|
|
211a828730 |
10
Makefile
10
Makefile
@@ -70,8 +70,8 @@ dist-no-debug: all
|
|||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/config
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/config
|
||||||
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
||||||
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
|
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
|
||||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||||
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
|
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
|
||||||
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
|
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
|
||||||
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
|
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
|
||||||
@@ -99,9 +99,13 @@ dist-no-debug: all
|
|||||||
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
|
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
|
||||||
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
||||||
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
|
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
|
||||||
|
cd atmosphere-$(AMSVER); zip -r ../atmosphere-EXPERIMENTAL-$(AMSVER).zip ./*; cd ../;
|
||||||
|
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||||
|
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||||
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
|
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
|
||||||
rm -r atmosphere-$(AMSVER)
|
rm -r atmosphere-$(AMSVER)
|
||||||
mkdir out
|
mkdir out
|
||||||
|
mv atmosphere-EXPERIMENTAL-$(AMSVER).zip out/atmosphere-EXPERIMENTAL-$(AMSVER).zip
|
||||||
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
|
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
|
||||||
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
|
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
|
||||||
|
|
||||||
@@ -120,7 +124,7 @@ dist: dist-no-debug
|
|||||||
mkdir atmosphere-$(AMSVER)-debug
|
mkdir atmosphere-$(AMSVER)-debug
|
||||||
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
|
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
|
||||||
cp fusee/fusee-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
|
cp fusee/fusee-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
|
||||||
cp fusee/fusee-secondary/fusee-secondary.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
||||||
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
|
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
|
||||||
cp sept/sept-secondary/sept-secondary.elf atmosphere-$(AMSVER)-debug/sept-secondary.elf
|
cp sept/sept-secondary/sept-secondary.elf atmosphere-$(AMSVER)-debug/sept-secondary.elf
|
||||||
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf
|
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ stage2_entrypoint = 0xF0000000
|
|||||||
; To force-enable nogc, add nogc = 1
|
; To force-enable nogc, add nogc = 1
|
||||||
; To force-disable nogc, add nogc = 0
|
; To force-disable nogc, add nogc = 0
|
||||||
|
|
||||||
; To opt in to using Atmosphere's NCM reimplementation, add enable_ncm = 1
|
; To opt out of using Atmosphere's NCM reimplementation, add disable_ncm = 1
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Building Atmosphère is a very straightforward process that relies almost exclus
|
|||||||
## Dependencies
|
## Dependencies
|
||||||
+ [devkitA64](https://devkitpro.org)
|
+ [devkitA64](https://devkitpro.org)
|
||||||
+ [devkitARM](https://devkitpro.org)
|
+ [devkitARM](https://devkitpro.org)
|
||||||
+ [Python 2 or 3](https://www.python.org) (optional)
|
+ [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed)
|
||||||
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
|
|||||||
@@ -1,4 +1,39 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## 0.15.0
|
||||||
|
+ fusee-primary's panic display was updated to automatically identify and give suggestions to resolve many of the most common errors users encounter.
|
||||||
|
+ Having been tested as well as I can alone, `mesosphere` (atmosphère's reimplementation of the Nintendo Switch kernel) is now available for users interested in trying it.
|
||||||
|
+ Beginning in this release and until it is stable and well-tested, atmosphère will distribute two zips.
|
||||||
|
+ Users who wish to opt-in to mesosphere should download and extract the "cool kids" zip ("atmosphere-EXPERIMENTAL-").
|
||||||
|
+ Users who do not wish to use mesosphere should continue using the normal zip ("atmosphere-").
|
||||||
|
+ Users may detect whether mesosphere is active in system settings.
|
||||||
|
+ When mesosphere is active, the system version string will display "M.15.0" rather than "0.15.0", and so on for future releases.
|
||||||
|
+ Crash reports and the like will contain information on whether or not the user is using mesosphere, as well.
|
||||||
|
+ There are "probably" no material user-facing benefits to using mesosphere at this time.
|
||||||
|
+ Developers may be interested in the fact that mesosphere provides many newer SVC APIs even when on lower firmware versions.
|
||||||
|
+ The primary benefit to using mesosphere is that any issues you may encounter and report to me will be fixed.
|
||||||
|
+ All users who choose to opt in to using mesosphere have my deepest gratitude.
|
||||||
|
+ **Note:** If using hekate instead of fusee-primary, you will have to wait for the next hekate release for mesosphere to function, as hekate's support has not yet been included in an official release build.
|
||||||
|
+ This will be updated in the release notes when hekate provides a new release.
|
||||||
|
+ As mentioned in previous release notes, when mesosphere is stable and well-tested, it will be enabled by default and atmosphère's version will transition to 1.0.0.
|
||||||
|
+ Having been tested sufficiently over the last half-year, Atmosphere's NCM implementation is now opt-out, rather than opt in.
|
||||||
|
+ In the unlikely event that any issues are encountered, please report them to @SciresM.
|
||||||
|
+ Users interested in opting out of using our implementation should set `stratosphere!disable_ncm = 1` in BCT.ini.
|
||||||
|
+ The NCM implementation will stop being opt-out in a future update, probably around the same time that mesosphere becomes opt-out instead of opt-in.
|
||||||
|
+ Several bugs were fixed, including:
|
||||||
|
+ Loader now sets HBL's thread priority to a higher value when loading it in applet mode.
|
||||||
|
+ This fixes an extremely-slow launch ("hang") when using applet-HBL with certain games that do not suspend while inactive (e.g. Super Mario Sunshine).
|
||||||
|
+ set.mitm now caches user language configuration much more heavily.
|
||||||
|
+ This severely reduces lag in certain games which misuse the "nn::oe::GetDesiredLanguage()" API.
|
||||||
|
+ A bug was fixed that could cause erpt to fatal when loading an official save file that had error report attachments in it.
|
||||||
|
+ General system stability improvements to enhance the user's experience.
|
||||||
|
## 0.14.4
|
||||||
|
+ Several bugs were fixed involving the official jit sysmodule added in 10.0.0.
|
||||||
|
+ A Process handle leak was fixed when JitPlugin NRRs were registered with the `ro` sysmodule.
|
||||||
|
+ This prevented processes using jit from being able to exit, causing a full system freeze.
|
||||||
|
+ The `sm` atmosphere extension to not unregister services when the server's connection is closed was special-case disabled for `jit:u`.
|
||||||
|
+ This extension is normally desirable in order to allow more concurrent processes to exist (as only 0x40 sm connections may ever be concurrently open), but official jit sysmodule relies on the behavior.
|
||||||
|
+ This would cause crashes on attempts to launch a program using jit services more than once per reboot.
|
||||||
|
+ General system stability improvements to enhance the user's experience.
|
||||||
## 0.14.3
|
## 0.14.3
|
||||||
+ Support was added for 10.2.0.
|
+ Support was added for 10.2.0.
|
||||||
+ General system stability improvements to enhance the user's experience.
|
+ General system stability improvements to enhance the user's experience.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ This file is located under the `/atmosphere/config/` folder on your SD card and
|
|||||||
Atmosphère provides its own default splashscreen which is displayed at boot time. However, this can be replaced at will.
|
Atmosphère provides its own default splashscreen which is displayed at boot time. However, this can be replaced at will.
|
||||||
|
|
||||||
The boot splashscreen must be a BMP file, it must be 720x1280 (1280x720 rotated 90 degrees left/counterclockwise/anti-clockwise) resolution, and be in 32-bit ARGB format. You can use image editing software such as GIMP or Photoshop to export the image in this format.
|
The boot splashscreen must be a BMP file, it must be 720x1280 (1280x720 rotated 90 degrees left/counterclockwise/anti-clockwise) resolution, and be in 32-bit ARGB format. You can use image editing software such as GIMP or Photoshop to export the image in this format.
|
||||||
|
|
||||||
Add the following lines to BCT.ini and change the value of `custom_splash` to the actual path and filename of your boot splashscreen:
|
Add the following lines to BCT.ini and change the value of `custom_splash` to the actual path and filename of your boot splashscreen:
|
||||||
```
|
```
|
||||||
[stage2]
|
[stage2]
|
||||||
@@ -29,11 +29,11 @@ nogc = X
|
|||||||
0 = force-disable nogc, so Atmosphère will always enable the Game Card reader.
|
0 = force-disable nogc, so Atmosphère will always enable the Game Card reader.
|
||||||
```
|
```
|
||||||
|
|
||||||
### NCM opt-in
|
### NCM opt-out
|
||||||
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module, but currently this is not enabled by default. If you wish to enable this reimplementation add the following line to the `stratosphere` section:
|
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module. If you wish to disable this reimplementation add the following line to the `stratosphere` section:
|
||||||
```
|
```
|
||||||
[stratosphere]
|
[stratosphere]
|
||||||
enable_ncm = 1
|
disable_ncm = 1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|||||||
@@ -96,10 +96,6 @@ namespace ams::secmon {
|
|||||||
util::ClearMemory(reinterpret_cast<void *>(address + size / 2), size / 2);
|
util::ClearMemory(reinterpret_cast<void *>(address + size / 2), size / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPhysicalMemoryAddress(uintptr_t address) {
|
|
||||||
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearBootCodeHigh() {
|
void ClearBootCodeHigh() {
|
||||||
@@ -130,6 +126,10 @@ namespace ams::secmon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPhysicalMemoryAddress(uintptr_t address) {
|
||||||
|
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
|
||||||
|
}
|
||||||
|
|
||||||
void UnmapTzram() {
|
void UnmapTzram() {
|
||||||
/* Get the tables. */
|
/* Get the tables. */
|
||||||
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
namespace ams::secmon {
|
namespace ams::secmon {
|
||||||
|
|
||||||
|
bool IsPhysicalMemoryAddress(uintptr_t address);
|
||||||
size_t GetPhysicalMemorySize();
|
size_t GetPhysicalMemorySize();
|
||||||
|
|
||||||
void UnmapTzram();
|
void UnmapTzram();
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ namespace ams::secmon::smc {
|
|||||||
{ 0xC3000006, Restriction_Normal, SmcShowError },
|
{ 0xC3000006, Restriction_Normal, SmcShowError },
|
||||||
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
|
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
|
||||||
{ 0xC3000008, Restriction_Normal, SmcReadWriteRegister },
|
{ 0xC3000008, Restriction_Normal, SmcReadWriteRegister },
|
||||||
|
|
||||||
|
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
|
||||||
|
{ 0xC3000409, Restriction_Normal, SmcSetConfig },
|
||||||
};
|
};
|
||||||
|
|
||||||
constinit HandlerInfo g_ams_handlers[] = {
|
constinit HandlerInfo g_ams_handlers[] = {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
#include "../secmon_error.hpp"
|
#include "../secmon_error.hpp"
|
||||||
|
#include "../secmon_map.hpp"
|
||||||
#include "../secmon_misc.hpp"
|
#include "../secmon_misc.hpp"
|
||||||
#include "../secmon_page_mapper.hpp"
|
#include "../secmon_page_mapper.hpp"
|
||||||
#include "../secmon_user_power_management.hpp"
|
#include "../secmon_user_power_management.hpp"
|
||||||
@@ -157,6 +158,8 @@ namespace ams::secmon::smc {
|
|||||||
return value.value;
|
return value.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constinit u64 g_payload_address = 0;
|
||||||
|
|
||||||
SmcResult GetConfig(SmcArguments &args, bool kern) {
|
SmcResult GetConfig(SmcArguments &args, bool kern) {
|
||||||
switch (static_cast<ConfigItem>(args.r[1])) {
|
switch (static_cast<ConfigItem>(args.r[1])) {
|
||||||
case ConfigItem::DisableProgramVerification:
|
case ConfigItem::DisableProgramVerification:
|
||||||
@@ -267,6 +270,14 @@ namespace ams::secmon::smc {
|
|||||||
/* NOTE: This may return values other than 1 in the future. */
|
/* NOTE: This may return values other than 1 in the future. */
|
||||||
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0);
|
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
|
case ConfigItem::ExospherePayloadAddress:
|
||||||
|
/* Gets the physical address of the reboot payload buffer, if one exists. */
|
||||||
|
if (g_payload_address != 0) {
|
||||||
|
args.r[1] = g_payload_address;
|
||||||
|
} else {
|
||||||
|
return SmcResult::NotInitialized;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return SmcResult::InvalidArgument;
|
return SmcResult::InvalidArgument;
|
||||||
}
|
}
|
||||||
@@ -309,6 +320,17 @@ namespace ams::secmon::smc {
|
|||||||
return SmcResult::NotImplemented;
|
return SmcResult::NotImplemented;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ConfigItem::ExospherePayloadAddress:
|
||||||
|
if (g_payload_address == 0) {
|
||||||
|
if (secmon::IsPhysicalMemoryAddress(args.r[2])) {
|
||||||
|
g_payload_address = args.r[2];
|
||||||
|
} else {
|
||||||
|
return SmcResult::InvalidArgument;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return SmcResult::Busy;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return SmcResult::InvalidArgument;
|
return SmcResult::InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace ams::secmon::smc {
|
|||||||
ExosphereBlankProdInfo = 65005,
|
ExosphereBlankProdInfo = 65005,
|
||||||
ExosphereAllowCalWrites = 65006,
|
ExosphereAllowCalWrites = 65006,
|
||||||
ExosphereEmummcType = 65007,
|
ExosphereEmummcType = 65007,
|
||||||
|
ExospherePayloadAddress = 65008,
|
||||||
};
|
};
|
||||||
|
|
||||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||||
|
|||||||
@@ -24,6 +24,9 @@
|
|||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
#include "display/video_fb.h"
|
#include "display/video_fb.h"
|
||||||
|
|
||||||
|
#define PROGRAM_ID_AMS_MITM 0x010041544D530000ull
|
||||||
|
#define PROGRAM_ID_BOOT 0x0100000000000005ull
|
||||||
|
|
||||||
static uint32_t g_panic_code = 0;
|
static uint32_t g_panic_code = 0;
|
||||||
|
|
||||||
static const char *get_error_desc_str(uint32_t error_desc) {
|
static const char *get_error_desc_str(uint32_t error_desc) {
|
||||||
@@ -53,6 +56,61 @@ static const char *get_error_desc_str(uint32_t error_desc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _try_suggest_fix(const atmosphere_fatal_error_ctx *ctx) {
|
||||||
|
/* Try to recognize certain errors automatically, and suggest fixes for them. */
|
||||||
|
const char *suggestion = NULL;
|
||||||
|
|
||||||
|
if (ctx->error_desc == 0xFFE) {
|
||||||
|
if (ctx->program_id == PROGRAM_ID_AMS_MITM) {
|
||||||
|
/* When a user has archive bits set improperly, attempting to create an automatic backup will fail */
|
||||||
|
/* to create the file path with error 0x202 (fs::ResultPathNotFound()) */
|
||||||
|
if (ctx->gprs[0] == 0x202) {
|
||||||
|
/* When the archive bit error is occurring, it manifests as failure to create automatic backup. */
|
||||||
|
/* Thus, we can search the stack for the automatic backups path. */
|
||||||
|
const char * const automatic_backups_prefix = "automatic_backups/X" /* ..... */;
|
||||||
|
const int prefix_len = strlen(automatic_backups_prefix);
|
||||||
|
|
||||||
|
for (size_t i = 0; i + prefix_len < ctx->stack_dump_size; ++i) {
|
||||||
|
if (memcmp(&ctx->stack_dump[i], automatic_backups_prefix, prefix_len) == 0) {
|
||||||
|
suggestion = "The atmosphere directory may improperly have archive\n"
|
||||||
|
"bits set. Please try running an archive bit fixer tool\n"
|
||||||
|
"(for example, the one in Hekate).\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ctx->gprs[0] == 0x249A02) { /* fs::ResultResultExFatUnavailable() */
|
||||||
|
/* When a user installs non-exFAT firm but has an exFAT formatted SD card, this error will */
|
||||||
|
/* be returned on attempt to access the SD card. */
|
||||||
|
suggestion = "Your console has non-exFAT firmware installed, but your SD card\n"
|
||||||
|
"is formatted as exFAT. Format your SD card as FAT32, or manually\n"
|
||||||
|
"flash exFAT firmware to package2.\n";
|
||||||
|
}
|
||||||
|
} else if (ctx->program_id == PROGRAM_ID_BOOT) {
|
||||||
|
/* 9.x -> 10.x updated the API for SvcQueryIoMapping. */
|
||||||
|
/* This can cause the kernel to reject incorrect-ABI calls by boot when a partial update is applied */
|
||||||
|
/* (older kernel in package2, for some reason). */
|
||||||
|
for (size_t i = 0; i < 8; ++i) {
|
||||||
|
if (ctx->gprs[i] == 0xF201) {
|
||||||
|
suggestion = "A partial update may have been improperly performed.\n"
|
||||||
|
"To fix, try manually flashing latest package2 to MMC.\n"
|
||||||
|
"\n"
|
||||||
|
"For help doing this, seek support in the ReSwitched or\n"
|
||||||
|
"Nintendo Homebrew discord servers.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ctx->error_desc == 0xF00) { /* Kernel Panic */
|
||||||
|
suggestion = "Please contact SciresM#0524 on Discord, or create an issue\n"
|
||||||
|
"on the Atmosphere GitHub issue tracker. Thank you very much\n"
|
||||||
|
"for helping to test mesosphere.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suggestion != NULL) {
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n%s", suggestion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void _check_and_display_atmosphere_fatal_error(void) {
|
static void _check_and_display_atmosphere_fatal_error(void) {
|
||||||
/* Check for valid magic. */
|
/* Check for valid magic. */
|
||||||
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
|
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
|
||||||
@@ -86,7 +144,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
|||||||
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic = 0xCCCCCCCC;
|
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic = 0xCCCCCCCC;
|
||||||
|
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "A fatal error occurred when running Atmosph\xe8re.\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "A fatal error occurred when running Atmosph\xe8re.\n");
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Title ID: %016llx\n", ctx.title_id);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Program ID: %016llx\n", ctx.program_id);
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc);
|
||||||
|
|
||||||
/* Save context to the SD card. */
|
/* Save context to the SD card. */
|
||||||
@@ -101,6 +159,9 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to print a fix suggestion via automatic error detection. */
|
||||||
|
_try_suggest_fix(&ctx);
|
||||||
|
|
||||||
/* Display error. */
|
/* Display error. */
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nPress POWER to reboot\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nPress POWER to reboot\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t error_desc;
|
uint32_t error_desc;
|
||||||
uint64_t title_id;
|
uint64_t program_id;
|
||||||
union {
|
union {
|
||||||
uint64_t gprs[32];
|
uint64_t gprs[32];
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -186,11 +186,15 @@ DEPENDS := $(OFILES:.o=.d)
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all : $(OUTPUT).bin
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
$(OUTPUT).bin : $(OUTPUT).elf
|
$(OUTPUT).bin : $(OUTPUT)-experimental.bin
|
||||||
|
@python $(TOPDIR)/fusee_make_standard.py $(OUTPUT)-experimental.bin $(OUTPUT).bin
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
$(OUTPUT)-experimental.bin : $(OUTPUT)-experimental.elf
|
||||||
$(OBJCOPY) -S -O binary $< $@
|
$(OBJCOPY) -S -O binary $< $@
|
||||||
@echo built ... $(notdir $@)
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
$(OUTPUT).elf : $(OFILES)
|
$(OUTPUT)-experimental.elf : $(OFILES)
|
||||||
|
|
||||||
%.elf: $(OFILES)
|
%.elf: $(OFILES)
|
||||||
@echo linking $(notdir $@)
|
@echo linking $(notdir $@)
|
||||||
|
|||||||
37
fusee/fusee-secondary/fusee_make_standard.py
Normal file
37
fusee/fusee-secondary/fusee_make_standard.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import sys, os
|
||||||
|
from struct import pack as pk, unpack as up
|
||||||
|
|
||||||
|
def make_standard(exp):
|
||||||
|
std = exp[:]
|
||||||
|
_, metadata_offset, is_exp = up('<III', exp[:12])
|
||||||
|
assert is_exp == 1
|
||||||
|
|
||||||
|
# Patch the experimental flag to zero.
|
||||||
|
std = std[:8] + pk('<I', 0) + std[12:]
|
||||||
|
|
||||||
|
# Locate the mesosphere content header, patch to be experimental.
|
||||||
|
magic, size, code_ofs, content_ofs, num_contents, ver, sup_ver, rev = up('<IIIIIIII', exp[metadata_offset:metadata_offset + 0x20])
|
||||||
|
for i in range(num_contents):
|
||||||
|
start, size, cnt_type, flag0, flag1, flag2, pad = up('<IIBBBBI', exp[content_ofs + 0x20 * i:content_ofs + 0x20 * i + 0x10])
|
||||||
|
if cnt_type == 10: # CONTENT_TYPE_KRN
|
||||||
|
assert exp[content_ofs + 0x20 * i + 0x10:content_ofs + 0x20 * i + 0x10 + len(b'mesosphere') + 1] == (b'mesosphere\x00')
|
||||||
|
assert flag0 == 0 and flag1 == 0 and flag2 == 0
|
||||||
|
std = std[:content_ofs + 0x20 * i] + pk('<IIBBBBI', start, size, cnt_type, flag0 | 0x1, flag1, flag2, pad) + std[content_ofs + 0x20 * i + 0x10:]
|
||||||
|
|
||||||
|
return std
|
||||||
|
|
||||||
|
|
||||||
|
def main(argc, argv):
|
||||||
|
if argc != 3:
|
||||||
|
print('Usage: %s input output' % argv[0])
|
||||||
|
return 1
|
||||||
|
with open(argv[1], 'rb') as f:
|
||||||
|
experimental = f.read()
|
||||||
|
with open(argv[2], 'wb') as f:
|
||||||
|
f.write(make_standard(experimental))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main(len(sys.argv), sys.argv))
|
||||||
@@ -254,4 +254,6 @@ SECTIONS
|
|||||||
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
|
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
|
||||||
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
|
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
|
||||||
PROVIDE(__kernel_ldr_bin_size__ = kernel_ldr_bin_end - kernel_ldr_bin);
|
PROVIDE(__kernel_ldr_bin_size__ = kernel_ldr_bin_end - kernel_ldr_bin);
|
||||||
|
PROVIDE(__mesosphere_bin_start__ = mesosphere_bin - __start__);
|
||||||
|
PROVIDE(__mesosphere_bin_size__ = mesosphere_bin_end - mesosphere_bin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
#define u8 uint8_t
|
#define u8 uint8_t
|
||||||
#define u32 uint32_t
|
#define u32 uint32_t
|
||||||
#include "exosphere_bin.h"
|
#include "exosphere_bin.h"
|
||||||
|
#include "mesosphere_bin.h"
|
||||||
#include "sept_secondary_00_enc.h"
|
#include "sept_secondary_00_enc.h"
|
||||||
#include "sept_secondary_01_enc.h"
|
#include "sept_secondary_01_enc.h"
|
||||||
#include "sept_secondary_dev_00_enc.h"
|
#include "sept_secondary_dev_00_enc.h"
|
||||||
@@ -66,6 +67,8 @@
|
|||||||
|
|
||||||
extern const uint8_t warmboot_bin[];
|
extern const uint8_t warmboot_bin[];
|
||||||
|
|
||||||
|
extern int fusee_is_experimental(void);
|
||||||
|
|
||||||
static const uint8_t retail_pkc_modulus[0x100] = {
|
static const uint8_t retail_pkc_modulus[0x100] = {
|
||||||
0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD,
|
0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD,
|
||||||
0xCB, 0x4E, 0x4A, 0x52, 0x0B, 0x1A, 0x8E, 0xDE, 0x41, 0x87, 0x6F, 0xB7, 0x31, 0x05, 0x5F, 0xAA,
|
0xCB, 0x4E, 0x4A, 0x52, 0x0B, 0x1A, 0x8E, 0xDE, 0x41, 0x87, 0x6F, 0xB7, 0x31, 0x05, 0x5F, 0xAA,
|
||||||
@@ -209,11 +212,11 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
|
|||||||
strat_cfg->has_nogc_config = true;
|
strat_cfg->has_nogc_config = true;
|
||||||
sscanf(value, "%d", &tmp);
|
sscanf(value, "%d", &tmp);
|
||||||
strat_cfg->enable_nogc = tmp != 0;
|
strat_cfg->enable_nogc = tmp != 0;
|
||||||
} else if (strcmp(name, STRATOSPHERE_ENABLE_NCM_KEY) == 0) {
|
} else if (strcmp(name, STRATOSPHERE_DISABLE_NCM_KEY) == 0) {
|
||||||
sscanf(value, "%d", &tmp);
|
sscanf(value, "%d", &tmp);
|
||||||
strat_cfg->ncm_enabled = tmp != 0;
|
strat_cfg->ncm_disabled = tmp != 0;
|
||||||
if (strat_cfg->ncm_enabled) {
|
if (strat_cfg->ncm_disabled) {
|
||||||
stratosphere_enable_ncm();
|
stratosphere_disable_ncm();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -624,6 +627,7 @@ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
|||||||
uint32_t nxboot_main(void) {
|
uint32_t nxboot_main(void) {
|
||||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||||
|
const bool is_experimental = fusee_is_experimental();
|
||||||
package2_header_t *package2;
|
package2_header_t *package2;
|
||||||
size_t package2_size;
|
size_t package2_size;
|
||||||
void *tsec_fw;
|
void *tsec_fw;
|
||||||
@@ -933,7 +937,6 @@ uint32_t nxboot_main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Configure mesosphere. */
|
/* Configure mesosphere. */
|
||||||
/* TODO: Support non-SD/embedded mesosphere. */
|
|
||||||
{
|
{
|
||||||
size_t sd_meso_size = get_file_size("atmosphere/mesosphere.bin");
|
size_t sd_meso_size = get_file_size("atmosphere/mesosphere.bin");
|
||||||
if (sd_meso_size != 0) {
|
if (sd_meso_size != 0) {
|
||||||
@@ -948,6 +951,20 @@ uint32_t nxboot_main(void) {
|
|||||||
fatal_error("Error: failed to read atmosphere/mesosphere.bin!\n");
|
fatal_error("Error: failed to read atmosphere/mesosphere.bin!\n");
|
||||||
}
|
}
|
||||||
mesosphere_size = sd_meso_size;
|
mesosphere_size = sd_meso_size;
|
||||||
|
} else if (is_experimental) {
|
||||||
|
mesosphere_size = mesosphere_bin_size;
|
||||||
|
|
||||||
|
mesosphere = malloc(mesosphere_size);
|
||||||
|
|
||||||
|
if (mesosphere == NULL) {
|
||||||
|
fatal_error("[NXBOOT] Out of memory!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mesosphere, mesosphere_bin, mesosphere_size);
|
||||||
|
|
||||||
|
if (mesosphere_size == 0) {
|
||||||
|
fatal_error("[NXBOOT] Could not read embedded mesosphere!\n");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mesosphere = NULL;
|
mesosphere = NULL;
|
||||||
mesosphere_size = 0;
|
mesosphere_size = 0;
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ _start:
|
|||||||
|
|
||||||
.word (_metadata - _start)
|
.word (_metadata - _start)
|
||||||
|
|
||||||
|
_is_experimental:
|
||||||
|
.word 0x00000001 /* is experimental */
|
||||||
|
|
||||||
_crt0:
|
_crt0:
|
||||||
/* Switch to system mode, mask all interrupts, clear all flags */
|
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||||
msr cpsr_cxsf, #0xDF
|
msr cpsr_cxsf, #0xDF
|
||||||
@@ -68,6 +71,14 @@ _crt0:
|
|||||||
ldr r1, [r1]
|
ldr r1, [r1]
|
||||||
b main
|
b main
|
||||||
|
|
||||||
|
.arm
|
||||||
|
.global fusee_is_experimental
|
||||||
|
.type fusee_is_experimental, %function
|
||||||
|
fusee_is_experimental:
|
||||||
|
ldr r0, =_is_experimental
|
||||||
|
ldr r0, [r0]
|
||||||
|
bx lr
|
||||||
|
|
||||||
/* Fusee-secondary header. */
|
/* Fusee-secondary header. */
|
||||||
.align 5
|
.align 5
|
||||||
_metadata:
|
_metadata:
|
||||||
@@ -135,6 +146,17 @@ _content_headers:
|
|||||||
.asciz "exosphere"
|
.asciz "exosphere"
|
||||||
.align 5
|
.align 5
|
||||||
|
|
||||||
|
/* mesosphere content header */
|
||||||
|
.word __mesosphere_bin_start__
|
||||||
|
.word __mesosphere_bin_size__
|
||||||
|
.byte CONTENT_TYPE_KRN
|
||||||
|
.byte CONTENT_FLAG_NONE
|
||||||
|
.byte CONTENT_FLAG_NONE
|
||||||
|
.byte CONTENT_FLAG_NONE
|
||||||
|
.word 0xCCCCCCCC
|
||||||
|
.asciz "mesosphere"
|
||||||
|
.align 5
|
||||||
|
|
||||||
/* fusee_primary content header */
|
/* fusee_primary content header */
|
||||||
.word __fusee_primary_bin_start__
|
.word __fusee_primary_bin_start__
|
||||||
.word __fusee_primary_bin_size__
|
.word __fusee_primary_bin_size__
|
||||||
@@ -249,7 +271,7 @@ _content_headers:
|
|||||||
.word __ncm_kip_start__
|
.word __ncm_kip_start__
|
||||||
.word __ncm_kip_size__
|
.word __ncm_kip_size__
|
||||||
.byte CONTENT_TYPE_KIP
|
.byte CONTENT_TYPE_KIP
|
||||||
.byte CONTENT_FLAG0_EXPERIMENTAL
|
.byte CONTENT_FLAG_NONE
|
||||||
.byte CONTENT_FLAG_NONE
|
.byte CONTENT_FLAG_NONE
|
||||||
.byte CONTENT_FLAG_NONE
|
.byte CONTENT_FLAG_NONE
|
||||||
.word 0xCCCCCCCC
|
.word 0xCCCCCCCC
|
||||||
@@ -267,17 +289,6 @@ _content_headers:
|
|||||||
.asciz "emummc"
|
.asciz "emummc"
|
||||||
.align 5
|
.align 5
|
||||||
|
|
||||||
/* kernel_ldr content header */
|
|
||||||
.word __kernel_ldr_bin_start__
|
|
||||||
.word __kernel_ldr_bin_size__
|
|
||||||
.byte CONTENT_TYPE_KLD
|
|
||||||
.byte CONTENT_FLAG_NONE
|
|
||||||
.byte CONTENT_FLAG_NONE
|
|
||||||
.byte CONTENT_FLAG_NONE
|
|
||||||
.word 0xCCCCCCCC
|
|
||||||
.asciz "kernel_ldr"
|
|
||||||
.align 5
|
|
||||||
|
|
||||||
/* splash_screen content header */
|
/* splash_screen content header */
|
||||||
.word __splash_screen_bmp_start__
|
.word __splash_screen_bmp_start__
|
||||||
.word __splash_screen_bmp_size__
|
.word __splash_screen_bmp_size__
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ static bool g_stratosphere_pm_enabled = true;
|
|||||||
static bool g_stratosphere_ams_mitm_enabled = true;
|
static bool g_stratosphere_ams_mitm_enabled = true;
|
||||||
static bool g_stratosphere_spl_enabled = true;
|
static bool g_stratosphere_spl_enabled = true;
|
||||||
static bool g_stratosphere_boot_enabled = true;
|
static bool g_stratosphere_boot_enabled = true;
|
||||||
static bool g_stratosphere_ncm_enabled = false;
|
static bool g_stratosphere_ncm_enabled = true;
|
||||||
|
|
||||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
|
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
|
||||||
|
|
||||||
@@ -58,17 +58,17 @@ emummc_fs_ver_t stratosphere_get_fs_version(void) {
|
|||||||
return g_fs_ver;
|
return g_fs_ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stratosphere_enable_ncm(void) {
|
void stratosphere_disable_ncm(void) {
|
||||||
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
|
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
|
||||||
/* and does not think it likely there is any possibility of undesirable behavior */
|
/* and does not think it likely there is any possibility of undesirable behavior */
|
||||||
/* when using the NCM reimplementation. However, because NCM manages critical save games */
|
/* when using the NCM reimplementation. However, because NCM manages critical save games */
|
||||||
/* the implementation will default to off for some time, until the code has been thoroughly */
|
/* the implementation may be optionally disabled for those not comfortable using it. */
|
||||||
/* tested in practice. */
|
|
||||||
|
|
||||||
/* PLEASE NOTE: The default behavior will be NCM on in a future atmosphere release, */
|
|
||||||
/* and this opt-in functionality will be removed at that time. */
|
|
||||||
|
|
||||||
g_stratosphere_ncm_enabled = true;
|
/* PLEASE NOTE: The NCM reimplementation has been well-tested, and correspondingly opt-out */
|
||||||
|
/* functionality will be removed in Atmosphere 1.0.0. */
|
||||||
|
|
||||||
|
g_stratosphere_ncm_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GCC doesn't consider the size as const... we have to write it ourselves. */
|
/* GCC doesn't consider the size as const... we have to write it ourselves. */
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware);
|
|||||||
ini1_header_t *stratosphere_get_sd_files_ini1(void);
|
ini1_header_t *stratosphere_get_sd_files_ini1(void);
|
||||||
void stratosphere_free_ini1(void);
|
void stratosphere_free_ini1(void);
|
||||||
|
|
||||||
void stratosphere_enable_ncm(void);
|
void stratosphere_disable_ncm(void);
|
||||||
|
|
||||||
emummc_fs_ver_t stratosphere_get_fs_version(void);
|
emummc_fs_ver_t stratosphere_get_fs_version(void);
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_in
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
bool has_nogc_config;
|
bool has_nogc_config;
|
||||||
bool enable_nogc;
|
bool enable_nogc;
|
||||||
bool ncm_enabled;
|
bool ncm_disabled;
|
||||||
} stratosphere_cfg_t;
|
} stratosphere_cfg_t;
|
||||||
|
|
||||||
#define STRATOSPHERE_NOGC_KEY "nogc"
|
#define STRATOSPHERE_NOGC_KEY "nogc"
|
||||||
#define STRATOSPHERE_ENABLE_NCM_KEY "enable_ncm"
|
#define STRATOSPHERE_DISABLE_NCM_KEY "disable_ncm"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||||
branch = master
|
branch = master
|
||||||
commit = 48dbf4808f4f2042de8c45e9ec471a8f60d5d621
|
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
||||||
parent = 47d0d5c6abc1c9957cd05c63b02ee5e712179b80
|
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ endif
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS ?=
|
||||||
|
|
||||||
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
||||||
export ATMOSPHERE_SETTINGS := -fPIE -g
|
export ATMOSPHERE_SETTINGS := -fPIE -g $(ATMOSPHERE_BUILD_SETTINGS)
|
||||||
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
|
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
|
||||||
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
|
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
|
||||||
-Wno-format-truncation -Wno-format-zero-length -Wno-stringop-truncation
|
-Wno-format-truncation -Wno-format-zero-length -Wno-stringop-truncation
|
||||||
@@ -132,10 +134,15 @@ FIND_SOURCE_FILES=$(foreach dir,$1,$(filter-out $(notdir $(wildcard $(dir)/*.arc
|
|||||||
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),os,$(ATMOSPHERE_OS_NAME),$2)) \
|
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),os,$(ATMOSPHERE_OS_NAME),$2)) \
|
||||||
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES_EX,$(dir),cpu,$(ATMOSPHERE_CPU_NAME) $(ATMOSPHERE_CPU_EXTENSIONS),$2))
|
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES_EX,$(dir),cpu,$(ATMOSPHERE_CPU_NAME) $(ATMOSPHERE_CPU_EXTENSIONS),$2))
|
||||||
|
|
||||||
|
ATMOSPHERE_GCH_IDENTIFIER ?= ams_placeholder_gch_identifier
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# Rules for compiling pre-compiled headers
|
# Rules for compiling pre-compiled headers
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%.gch: %.hpp
|
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
|
||||||
@echo $<
|
$(SILENTMSG) Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
|
||||||
$(CXX) -w -x c++-header -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||||
@cp $@ $(<).gch
|
|
||||||
|
%.hpp.gch: %.hpp
|
||||||
|
$(SILENTMSG) Precompiling $(notdir $<)
|
||||||
|
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
|||||||
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
|
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
|
||||||
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
|
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
|
||||||
|
|
||||||
export LIBS := -lmesosphere
|
export LIBS := -l$(LIBMESOSPHERE_NAME)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# list of directories containing libraries, this must be the top level containing
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in common atmosphere configuration
|
# pull in common atmosphere configuration
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
|
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||||
@@ -28,7 +30,7 @@ LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
|
|||||||
# no real need to edit anything past this point unless you need to add additional
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
# rules for different file extensions
|
# rules for different file extensions
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
ifneq ($(__RECURSIVE__),1)
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
||||||
@@ -54,7 +56,7 @@ endif
|
|||||||
|
|
||||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
export GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.gch),$(notdir $(hdr)))
|
export GCH_DIRS := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
|
||||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
@@ -62,41 +64,70 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
-I.
|
-I.
|
||||||
|
|
||||||
.PHONY: clean all
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS :=
|
||||||
|
all: release
|
||||||
|
|
||||||
|
define ATMOSPHERE_ADD_TARGET
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
|
||||||
|
|
||||||
|
$(strip $1): $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||||
|
|
||||||
|
$$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2) : $$(ATMOSPHERE_LIBRARY_DIR) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(SOURCES) $$(INCLUDES) $$(GCH_DIRS)
|
||||||
|
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(CURDIR)/$$@ $(3) \
|
||||||
|
ATMOSPHERE_GCH_IDENTIFIER="$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1)" \
|
||||||
|
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
-f $$(THIS_MAKEFILE)
|
||||||
|
|
||||||
|
clean-$(strip $1):
|
||||||
|
@echo clean $(strip $1) ...
|
||||||
|
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||||
|
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
|
||||||
|
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, $(TARGET)_debug.a, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
|
||||||
|
))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: lib/$(TARGET).a
|
|
||||||
|
|
||||||
lib:
|
-include $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME).mk
|
||||||
|
|
||||||
|
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
|
||||||
|
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
|
||||||
|
|
||||||
|
.PHONY: clean all $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||||
|
|
||||||
|
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
|
||||||
release:
|
$(ATMOSPHERE_BUILD_DIR)/%:
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
|
||||||
lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
|
|
||||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
|
||||||
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
|
|
||||||
DEPSDIR=$(CURDIR)/release \
|
|
||||||
--no-print-directory -C release \
|
|
||||||
-f $(CURDIR)/Makefile
|
|
||||||
|
|
||||||
dist-bin: all
|
|
||||||
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib
|
|
||||||
|
|
||||||
dist-src:
|
|
||||||
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile
|
|
||||||
|
|
||||||
dist: dist-src dist-bin
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@rm -fr release lib *.bz2
|
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2 $(ALL_GCH_FILES)
|
||||||
|
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
|
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
|
||||||
|
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES),$(notdir $(patsubst %.hpp.gch/,%.d,$(dir $(hdr)))))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# main targets
|
# main targets
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace ams::kern {
|
|||||||
private:
|
private:
|
||||||
friend class KScopedSchedulerLock;
|
friend class KScopedSchedulerLock;
|
||||||
friend class KScopedSchedulerLockAndSleep;
|
friend class KScopedSchedulerLockAndSleep;
|
||||||
|
friend class KScopedDisableDispatch;
|
||||||
private:
|
private:
|
||||||
SchedulingState state;
|
SchedulingState state;
|
||||||
bool is_active;
|
bool is_active;
|
||||||
@@ -161,8 +162,9 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void ScheduleOnInterrupt() {
|
ALWAYS_INLINE void ScheduleOnInterrupt() {
|
||||||
KScopedDisableDispatch dd;
|
GetCurrentThread().DisableDispatch();
|
||||||
this->Schedule();
|
this->Schedule();
|
||||||
|
GetCurrentThread().EnableDispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RescheduleOtherCores(u64 cores_needing_scheduling);
|
void RescheduleOtherCores(u64 cores_needing_scheduling);
|
||||||
|
|||||||
@@ -559,20 +559,7 @@ namespace ams::kern {
|
|||||||
GetCurrentThread().DisableDispatch();
|
GetCurrentThread().DisableDispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE ~KScopedDisableDispatch() {
|
~KScopedDisableDispatch();
|
||||||
GetCurrentThread().EnableDispatch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class KScopedEnableDispatch {
|
|
||||||
public:
|
|
||||||
explicit ALWAYS_INLINE KScopedEnableDispatch() {
|
|
||||||
GetCurrentThread().EnableDispatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE ~KScopedEnableDispatch() {
|
|
||||||
GetCurrentThread().DisableDispatch();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ALWAYS_INLINE KExceptionContext *GetExceptionContext(KThread *thread) {
|
ALWAYS_INLINE KExceptionContext *GetExceptionContext(KThread *thread) {
|
||||||
|
|||||||
@@ -308,6 +308,15 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
g_secure_applet_memory_used = false;
|
g_secure_applet_memory_used = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 GetVersionIdentifier() {
|
||||||
|
u64 value = kern::GetTargetFirmware();
|
||||||
|
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MICRO) << 32;
|
||||||
|
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MINOR) << 40;
|
||||||
|
value |= static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MAJOR) << 48;
|
||||||
|
value |= static_cast<u64>('M') << 56;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialization. */
|
/* Initialization. */
|
||||||
@@ -534,10 +543,14 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
|
|
||||||
void KSystemControl::StopSystem(void *arg) {
|
void KSystemControl::StopSystem(void *arg) {
|
||||||
if (arg != nullptr) {
|
if (arg != nullptr) {
|
||||||
|
/* Get the address of the legacy IRAM region. */
|
||||||
|
const KVirtualAddress iram_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 64_KB;
|
||||||
|
constexpr size_t RebootPayloadSize = 0x2E000;
|
||||||
|
|
||||||
/* NOTE: Atmosphere extension; if we received an exception context from Panic(), */
|
/* NOTE: Atmosphere extension; if we received an exception context from Panic(), */
|
||||||
/* generate a fatal error report using it. */
|
/* generate a fatal error report using it. */
|
||||||
const KExceptionContext *e_ctx = static_cast<const KExceptionContext *>(arg);
|
const KExceptionContext *e_ctx = static_cast<const KExceptionContext *>(arg);
|
||||||
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 0x3E000);
|
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(iram_address + RebootPayloadSize);
|
||||||
|
|
||||||
/* Clear the fatal context. */
|
/* Clear the fatal context. */
|
||||||
std::memset(f_ctx, 0xCC, sizeof(*f_ctx));
|
std::memset(f_ctx, 0xCC, sizeof(*f_ctx));
|
||||||
@@ -553,6 +566,10 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
/* Set module base. */
|
/* Set module base. */
|
||||||
f_ctx->module_base = KMemoryLayout::GetKernelCodeRegionExtents().GetAddress();
|
f_ctx->module_base = KMemoryLayout::GetKernelCodeRegionExtents().GetAddress();
|
||||||
|
|
||||||
|
/* Set afsr1. */
|
||||||
|
f_ctx->afsr0 = 0;
|
||||||
|
f_ctx->afsr1 = GetVersionIdentifier();
|
||||||
|
|
||||||
/* Copy registers. */
|
/* Copy registers. */
|
||||||
for (size_t i = 0; i < util::size(e_ctx->x); ++i) {
|
for (size_t i = 0; i < util::size(e_ctx->x); ++i) {
|
||||||
f_ctx->gprs[i] = e_ctx->x[i];
|
f_ctx->gprs[i] = e_ctx->x[i];
|
||||||
@@ -581,8 +598,27 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trigger a reboot to rcm. */
|
/* Try to get a payload address. */
|
||||||
smc::init::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToRcm);
|
const KMemoryRegion *cached_region = nullptr;
|
||||||
|
u64 reboot_payload_paddr = 0;
|
||||||
|
if (smc::TryGetConfig(std::addressof(reboot_payload_paddr), 1, smc::ConfigItem::ExospherePayloadAddress) && KMemoryLayout::IsLinearMappedPhysicalAddress(cached_region, reboot_payload_paddr, RebootPayloadSize)) {
|
||||||
|
/* If we have a payload, reboot to it. */
|
||||||
|
const KVirtualAddress reboot_payload = KMemoryLayout::GetLinearVirtualAddress(KPhysicalAddress(reboot_payload_paddr));
|
||||||
|
|
||||||
|
/* Clear IRAM. */
|
||||||
|
std::memset(GetVoidPointer(iram_address), 0xCC, RebootPayloadSize);
|
||||||
|
|
||||||
|
/* Copy the payload to iram. */
|
||||||
|
for (size_t i = 0; i < RebootPayloadSize / sizeof(u32); ++i) {
|
||||||
|
GetPointer<volatile u32>(iram_address)[i] = GetPointer<volatile u32>(reboot_payload)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reboot. */
|
||||||
|
smc::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToPayload);
|
||||||
|
} else {
|
||||||
|
/* If we don't have a payload, reboot to rcm. */
|
||||||
|
smc::SetConfig(smc::ConfigItem::ExosphereNeedsReboot, smc::UserRebootType_ToRcm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_call_smc_on_panic) {
|
if (g_call_smc_on_panic) {
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
FunctionId_Panic = 0xC3000006,
|
FunctionId_Panic = 0xC3000006,
|
||||||
FunctionId_ConfigureCarveout = 0xC3000007,
|
FunctionId_ConfigureCarveout = 0xC3000007,
|
||||||
FunctionId_ReadWriteRegister = 0xC3000008,
|
FunctionId_ReadWriteRegister = 0xC3000008,
|
||||||
|
|
||||||
|
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
|
||||||
|
FunctionId_SetConfig = 0xC3000409,
|
||||||
};
|
};
|
||||||
|
|
||||||
void CallPrivilegedSecureMonitorFunction(SecureMonitorArguments &args) {
|
void CallPrivilegedSecureMonitorFunction(SecureMonitorArguments &args) {
|
||||||
@@ -140,35 +143,6 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
args.x[7] = x7;
|
args.x[7] = x7;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallUserSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
|
|
||||||
/* Load arguments into registers. */
|
|
||||||
register u64 x0 asm("x0") = args.x[0];
|
|
||||||
register u64 x1 asm("x1") = args.x[1];
|
|
||||||
register u64 x2 asm("x2") = args.x[2];
|
|
||||||
register u64 x3 asm("x3") = args.x[3];
|
|
||||||
register u64 x4 asm("x4") = args.x[4];
|
|
||||||
register u64 x5 asm("x5") = args.x[5];
|
|
||||||
register u64 x6 asm("x6") = args.x[6];
|
|
||||||
register u64 x7 asm("x7") = args.x[7];
|
|
||||||
|
|
||||||
/* Actually make the call. */
|
|
||||||
__asm__ __volatile__("smc #0"
|
|
||||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
|
||||||
:
|
|
||||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Store arguments to output. */
|
|
||||||
args.x[0] = x0;
|
|
||||||
args.x[1] = x1;
|
|
||||||
args.x[2] = x2;
|
|
||||||
args.x[3] = x3;
|
|
||||||
args.x[4] = x4;
|
|
||||||
args.x[5] = x5;
|
|
||||||
args.x[6] = x6;
|
|
||||||
args.x[7] = x7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Global lock for generate random bytes. */
|
/* Global lock for generate random bytes. */
|
||||||
KSpinLock g_generate_random_lock;
|
KSpinLock g_generate_random_lock;
|
||||||
|
|
||||||
@@ -210,21 +184,30 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetConfig(ConfigItem config_item, u64 value) {
|
|
||||||
SecureMonitorArguments args = { UserFunctionId_SetConfig, static_cast<u32>(config_item), 0, value };
|
|
||||||
CallUserSecureMonitorFunctionForInit(args);
|
|
||||||
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
bool TryGetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||||
SecureMonitorArguments args = { FunctionId_GetConfig, static_cast<u32>(config_item) };
|
SecureMonitorArguments args = { FunctionId_GetConfig, static_cast<u32>(config_item) };
|
||||||
CallPrivilegedSecureMonitorFunction(args);
|
CallPrivilegedSecureMonitorFunction(args);
|
||||||
MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success));
|
if (static_cast<SmcResult>(args.x[0]) != SmcResult::Success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < num_qwords && i < 7; i++) {
|
for (size_t i = 0; i < num_qwords && i < 7; i++) {
|
||||||
out[i] = args.x[1 + i];
|
out[i] = args.x[1 + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||||
|
MESOSPHERE_ABORT_UNLESS(TryGetConfig(out, num_qwords, config_item));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetConfig(ConfigItem config_item, u64 value) {
|
||||||
|
SecureMonitorArguments args = { FunctionId_SetConfig, static_cast<u32>(config_item), 0, value };
|
||||||
|
CallPrivilegedSecureMonitorFunction(args);
|
||||||
|
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value) {
|
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value) {
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
ExosphereNeedsShutdown = 65002,
|
ExosphereNeedsShutdown = 65002,
|
||||||
ExosphereGitCommitHash = 65003,
|
ExosphereGitCommitHash = 65003,
|
||||||
ExosphereHasRcmBugPatch = 65004,
|
ExosphereHasRcmBugPatch = 65004,
|
||||||
|
ExosphereBlankProdInfo = 65005,
|
||||||
|
ExosphereAllowCalWrites = 65006,
|
||||||
|
ExosphereEmummcType = 65007,
|
||||||
|
ExospherePayloadAddress = 65008,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SmcResult {
|
enum class SmcResult {
|
||||||
@@ -89,12 +93,14 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
UserRebootType_ToPayload = 2,
|
UserRebootType_ToPayload = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO: Rest of Secure Monitor API. */
|
|
||||||
void GenerateRandomBytes(void *dst, size_t size);
|
void GenerateRandomBytes(void *dst, size_t size);
|
||||||
|
bool TryGetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
||||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
||||||
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
bool ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
||||||
void ConfigureCarveout(size_t which, uintptr_t address, size_t size);
|
void ConfigureCarveout(size_t which, uintptr_t address, size_t size);
|
||||||
|
|
||||||
|
bool SetConfig(ConfigItem config_item, u64 value);
|
||||||
|
|
||||||
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
|
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
|
||||||
|
|
||||||
void NORETURN Panic(u32 color);
|
void NORETURN Panic(u32 color);
|
||||||
@@ -108,8 +114,6 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
void GenerateRandomBytes(void *dst, size_t size);
|
void GenerateRandomBytes(void *dst, size_t size);
|
||||||
bool ReadWriteRegister(u32 *out, u64 address, u32 mask, u32 value);
|
bool ReadWriteRegister(u32 *out, u64 address, u32 mask, u32 value);
|
||||||
|
|
||||||
bool SetConfig(ConfigItem config_item, u64 value);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -73,15 +73,16 @@ namespace ams::kern {
|
|||||||
s32 num_waiters = 0;
|
s32 num_waiters = 0;
|
||||||
{
|
{
|
||||||
KScopedSchedulerLock sl;
|
KScopedSchedulerLock sl;
|
||||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
|
||||||
|
|
||||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
|
||||||
|
|
||||||
/* Check the userspace value. */
|
/* Check the userspace value. */
|
||||||
s32 user_value;
|
s32 user_value;
|
||||||
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
||||||
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
||||||
|
|
||||||
|
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||||
|
|
||||||
|
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||||
|
|
||||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
KThread *target_thread = std::addressof(*it);
|
KThread *target_thread = std::addressof(*it);
|
||||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||||
@@ -108,26 +109,54 @@ namespace ams::kern {
|
|||||||
|
|
||||||
/* Determine the updated value. */
|
/* Determine the updated value. */
|
||||||
s32 new_value;
|
s32 new_value;
|
||||||
if (count <= 0) {
|
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {
|
||||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
if (count <= 0) {
|
||||||
new_value = value - 1;
|
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
|
new_value = value - 2;
|
||||||
|
} else {
|
||||||
|
new_value = value + 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
new_value = value + 1;
|
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
|
auto tmp_it = it;
|
||||||
|
s32 tmp_num_waiters = 0;
|
||||||
|
while ((++tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
|
||||||
|
if ((tmp_num_waiters++) >= count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp_num_waiters < count) {
|
||||||
|
new_value = value - 1;
|
||||||
|
} else {
|
||||||
|
new_value = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new_value = value + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto tmp_it = it;
|
if (count <= 0) {
|
||||||
int tmp_num_waiters = 0;
|
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||||
while ((tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
new_value = value - 1;
|
||||||
++tmp_num_waiters;
|
} else {
|
||||||
++tmp_it;
|
new_value = value + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp_num_waiters == 0) {
|
|
||||||
new_value = value + 1;
|
|
||||||
} else if (tmp_num_waiters <= count) {
|
|
||||||
new_value = value - 1;
|
|
||||||
} else {
|
} else {
|
||||||
new_value = value;
|
auto tmp_it = it;
|
||||||
|
s32 tmp_num_waiters = 0;
|
||||||
|
while ((tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
||||||
|
++tmp_num_waiters;
|
||||||
|
++tmp_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp_num_waiters == 0) {
|
||||||
|
new_value = value + 1;
|
||||||
|
} else if (tmp_num_waiters <= count) {
|
||||||
|
new_value = value - 1;
|
||||||
|
} else {
|
||||||
|
new_value = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -205,13 +205,8 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Close threads in the list. */
|
/* Close threads in the list. */
|
||||||
if (num_waiters > MaxThreads) {
|
for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) {
|
||||||
auto it = thread_list.begin();
|
(*it).Close();
|
||||||
while (it != thread_list.end()) {
|
|
||||||
KThread *thread = std::addressof(*it);
|
|
||||||
thread->Close();
|
|
||||||
it = thread_list.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
KScopedDisableDispatch::~KScopedDisableDispatch() {
|
||||||
|
if (GetCurrentThread().GetDisableDispatchCount() <= 1) {
|
||||||
|
Kernel::GetScheduler().RescheduleCurrentCore();
|
||||||
|
} else {
|
||||||
|
GetCurrentThread().EnableDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in common atmosphere configuration
|
# pull in common atmosphere configuration
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in switch rules
|
# pull in switch rules
|
||||||
@@ -15,7 +17,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/stratosphere.hpp
|
PRECOMPILED_HEADERS := $(CURRENT_DIRECTORY)/include/stratosphere.hpp
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
||||||
@@ -66,7 +68,7 @@ endif
|
|||||||
|
|
||||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
export GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.gch),$(notdir $(hdr)))
|
export GCH_FILES := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
|
||||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
@@ -103,12 +105,12 @@ dist: dist-src dist-bin
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@rm -fr release lib *.bz2 include/stratosphere.hpp.gch
|
@rm -fr release lib *.bz2 $(GCH_FILES)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
|
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES:.gch=.d),$(notdir $(hdr)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# main targets
|
# main targets
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace ams::spl::smc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Functions. */
|
/* Functions. */
|
||||||
Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords);
|
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords);
|
||||||
Result GetConfig(u64 *out, size_t num_qwords, spl::ConfigItem which);
|
Result GetConfig(u64 *out, size_t num_qwords, spl::ConfigItem which);
|
||||||
Result GetResult(Result *out, AsyncOperationKey op);
|
Result GetResult(Result *out, AsyncOperationKey op);
|
||||||
Result GetResultData(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op);
|
Result GetResultData(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op);
|
||||||
@@ -59,8 +59,12 @@ namespace ams::spl::smc {
|
|||||||
Result AtmosphereGetEmummcConfig(void *out_config, void *out_paths, u32 storage_id);
|
Result AtmosphereGetEmummcConfig(void *out_config, void *out_paths, u32 storage_id);
|
||||||
|
|
||||||
/* Helpers. */
|
/* Helpers. */
|
||||||
|
inline Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords) {
|
||||||
|
return SetConfig(which, nullptr, value, num_qwords);
|
||||||
|
}
|
||||||
|
|
||||||
inline Result SetConfig(spl::ConfigItem which, const u64 value) {
|
inline Result SetConfig(spl::ConfigItem which, const u64 value) {
|
||||||
return SetConfig(which, &value, 1);
|
return SetConfig(which, std::addressof(value), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ namespace ams::spl {
|
|||||||
ExosphereBlankProdInfo = 65005,
|
ExosphereBlankProdInfo = 65005,
|
||||||
ExosphereAllowCalWrites = 65006,
|
ExosphereAllowCalWrites = 65006,
|
||||||
ExosphereEmummcType = 65007,
|
ExosphereEmummcType = 65007,
|
||||||
|
ExospherePayloadAddress = 65008,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -235,3 +236,4 @@ constexpr inline SplConfigItem SplConfigItem_ExosphereHasRcmBugPatch = static_ca
|
|||||||
constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast<SplConfigItem>(65005);
|
constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast<SplConfigItem>(65005);
|
||||||
constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast<SplConfigItem>(65006);
|
constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast<SplConfigItem>(65006);
|
||||||
constexpr inline SplConfigItem SplConfigItem_ExosphereEmummcType = static_cast<SplConfigItem>(65007);
|
constexpr inline SplConfigItem SplConfigItem_ExosphereEmummcType = static_cast<SplConfigItem>(65007);
|
||||||
|
constexpr inline SplConfigItem SplConfigItem_ExospherePayloadAddress = static_cast<SplConfigItem>(65008);
|
||||||
|
|||||||
@@ -74,7 +74,10 @@ namespace ams {
|
|||||||
ams_ctx.pc = ctx->pc.x;
|
ams_ctx.pc = ctx->pc.x;
|
||||||
ams_ctx.pstate = ctx->pstate;
|
ams_ctx.pstate = ctx->pstate;
|
||||||
ams_ctx.afsr0 = ctx->afsr0;
|
ams_ctx.afsr0 = ctx->afsr0;
|
||||||
ams_ctx.afsr1 = ctx->afsr1;
|
ams_ctx.afsr1 = (static_cast<u64>(::ams::exosphere::GetVersion(ATMOSPHERE_RELEASE_VERSION)) << 32) | static_cast<u64>(hos::GetVersion());
|
||||||
|
if (svc::IsKernelMesosphere()) {
|
||||||
|
ams_ctx.afsr1 |= (static_cast<u64>('M') << (BITSIZEOF(u64) - BITSIZEOF(u8)));
|
||||||
|
}
|
||||||
ams_ctx.far = ctx->far.x;
|
ams_ctx.far = ctx->far.x;
|
||||||
ams_ctx.report_identifier = armGetSystemTick();
|
ams_ctx.report_identifier = armGetSystemTick();
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace ams::erpt::srv {
|
|||||||
attachment_id.uuid.ToString(uuid_str, sizeof(uuid_str));
|
attachment_id.uuid.ToString(uuid_str, sizeof(uuid_str));
|
||||||
|
|
||||||
AttachmentFileName attachment_name;
|
AttachmentFileName attachment_name;
|
||||||
std::snprintf(attachment_name.name, sizeof(attachment_name.name), "%s/%s.att", ReportStoragePath, uuid_str);
|
std::snprintf(attachment_name.name, sizeof(attachment_name.name), "%s:/%s.att", ReportStoragePath, uuid_str);
|
||||||
return attachment_name;
|
return attachment_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,12 @@
|
|||||||
|
|
||||||
namespace ams::spl::smc {
|
namespace ams::spl::smc {
|
||||||
|
|
||||||
Result SetConfig(spl::ConfigItem which, const u64 *value, size_t num_qwords) {
|
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords) {
|
||||||
SecmonArgs args;
|
SecmonArgs args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::SetConfig);
|
args.X[0] = static_cast<u64>(FunctionId::SetConfig);
|
||||||
args.X[1] = static_cast<u64>(which);
|
args.X[1] = static_cast<u64>(which);
|
||||||
args.X[2] = 0;
|
args.X[2] = reinterpret_cast<u64>(address);
|
||||||
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
||||||
args.X[3 + i] = value[i];
|
args.X[3 + i] = value[i];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 14
|
#define ATMOSPHERE_RELEASE_VERSION_MINOR 15
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 3
|
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0
|
||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
||||||
|
|
||||||
|
|||||||
@@ -22,58 +22,267 @@
|
|||||||
|
|
||||||
namespace ams::util {
|
namespace ams::util {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
class IntrusiveRedBlackTreeImpl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct IntrusiveRedBlackTreeNode {
|
struct IntrusiveRedBlackTreeNode {
|
||||||
NON_COPYABLE(IntrusiveRedBlackTreeNode);
|
NON_COPYABLE(IntrusiveRedBlackTreeNode);
|
||||||
private:
|
private:
|
||||||
RB_ENTRY(IntrusiveRedBlackTreeNode) entry;
|
RB_ENTRY(IntrusiveRedBlackTreeNode) entry;
|
||||||
|
|
||||||
|
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||||
|
|
||||||
template<class, class, class>
|
template<class, class, class>
|
||||||
friend class IntrusiveRedBlackTree;
|
friend class IntrusiveRedBlackTree;
|
||||||
|
|
||||||
template<class, class>
|
|
||||||
friend class IntrusiveRedBlackTreeImpl;
|
|
||||||
public:
|
public:
|
||||||
constexpr IntrusiveRedBlackTreeNode() : entry() { /* ... */}
|
constexpr IntrusiveRedBlackTreeNode() : entry() { /* ... */}
|
||||||
};
|
};
|
||||||
static_assert(std::is_literal_type<IntrusiveRedBlackTreeNode>::value);
|
static_assert(std::is_literal_type<IntrusiveRedBlackTreeNode>::value);
|
||||||
|
|
||||||
template<class T, class Traits>
|
template<class T, class Traits, class Comparator>
|
||||||
class IntrusiveRedBlackTreeImpl {
|
class IntrusiveRedBlackTree;
|
||||||
NON_COPYABLE(IntrusiveRedBlackTreeImpl);
|
|
||||||
protected:
|
namespace impl {
|
||||||
RB_HEAD(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode);
|
|
||||||
using RootType = IntrusiveRedBlackTreeRoot;
|
class IntrusiveRedBlackTreeImpl {
|
||||||
protected:
|
NON_COPYABLE(IntrusiveRedBlackTreeImpl);
|
||||||
IntrusiveRedBlackTreeRoot root;
|
private:
|
||||||
|
template<class, class, class>
|
||||||
|
friend class ::ams::util::IntrusiveRedBlackTree;
|
||||||
|
private:
|
||||||
|
RB_HEAD(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode);
|
||||||
|
using RootType = IntrusiveRedBlackTreeRoot;
|
||||||
|
private:
|
||||||
|
IntrusiveRedBlackTreeRoot root;
|
||||||
|
public:
|
||||||
|
template<bool Const>
|
||||||
|
class Iterator;
|
||||||
|
|
||||||
|
using value_type = IntrusiveRedBlackTreeNode;
|
||||||
|
using size_type = size_t;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
using pointer = value_type *;
|
||||||
|
using const_pointer = const value_type *;
|
||||||
|
using reference = value_type &;
|
||||||
|
using const_reference = const value_type &;
|
||||||
|
using iterator = Iterator<false>;
|
||||||
|
using const_iterator = Iterator<true>;
|
||||||
|
|
||||||
|
template<bool Const>
|
||||||
|
class Iterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using value_type = typename IntrusiveRedBlackTreeImpl::value_type;
|
||||||
|
using difference_type = typename IntrusiveRedBlackTreeImpl::difference_type;
|
||||||
|
using pointer = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_pointer, IntrusiveRedBlackTreeImpl::pointer>::type;
|
||||||
|
using reference = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_reference, IntrusiveRedBlackTreeImpl::reference>::type;
|
||||||
|
private:
|
||||||
|
pointer node;
|
||||||
|
public:
|
||||||
|
explicit Iterator(pointer n) : node(n) { /* ... */ }
|
||||||
|
|
||||||
|
bool operator==(const Iterator &rhs) const {
|
||||||
|
return this->node == rhs.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator &rhs) const {
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer operator->() const {
|
||||||
|
return this->node;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const {
|
||||||
|
return *this->node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator &operator++() {
|
||||||
|
this->node = GetNext(this->node);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator &operator--() {
|
||||||
|
this->node = GetPrev(this->node);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator++(int) {
|
||||||
|
const Iterator it{*this};
|
||||||
|
++(*this);
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator--(int) {
|
||||||
|
const Iterator it{*this};
|
||||||
|
--(*this);
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Iterator<true>() const {
|
||||||
|
return Iterator<true>(this->node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
/* Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot. */
|
||||||
|
RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry);
|
||||||
|
private:
|
||||||
|
/* Define accessors using RB_* functions. */
|
||||||
|
constexpr ALWAYS_INLINE void InitializeImpl() {
|
||||||
|
RB_INIT(&this->root);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmptyImpl() const {
|
||||||
|
return RB_EMPTY(&this->root);
|
||||||
|
}
|
||||||
|
|
||||||
|
IntrusiveRedBlackTreeNode *GetMinImpl() const {
|
||||||
|
return RB_MIN(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
||||||
|
}
|
||||||
|
|
||||||
|
IntrusiveRedBlackTreeNode *GetMaxImpl() const {
|
||||||
|
return RB_MAX(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
||||||
|
}
|
||||||
|
|
||||||
|
IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
|
||||||
|
return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
static IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) {
|
||||||
|
return RB_NEXT(IntrusiveRedBlackTreeRoot, nullptr, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) {
|
||||||
|
return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNext(IntrusiveRedBlackTreeNode const *node) {
|
||||||
|
return static_cast<const IntrusiveRedBlackTreeNode *>(GetNext(const_cast<IntrusiveRedBlackTreeNode *>(node)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetPrev(IntrusiveRedBlackTreeNode const *node) {
|
||||||
|
return static_cast<const IntrusiveRedBlackTreeNode *>(GetPrev(const_cast<IntrusiveRedBlackTreeNode *>(node)));
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
constexpr IntrusiveRedBlackTreeImpl() : root() {
|
||||||
|
this->InitializeImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterator accessors. */
|
||||||
|
iterator begin() {
|
||||||
|
return iterator(this->GetMinImpl());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return const_iterator(this->GetMinImpl());
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return iterator(static_cast<IntrusiveRedBlackTreeNode *>(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return const_iterator(static_cast<const IntrusiveRedBlackTreeNode *>(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const {
|
||||||
|
return this->begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const {
|
||||||
|
return this->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator iterator_to(reference ref) {
|
||||||
|
return iterator(&ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator iterator_to(const_reference ref) const {
|
||||||
|
return const_iterator(&ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content management. */
|
||||||
|
bool empty() const {
|
||||||
|
return this->EmptyImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
reference back() {
|
||||||
|
return *this->GetMaxImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reference back() const {
|
||||||
|
return *this->GetMaxImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
reference front() {
|
||||||
|
return *this->GetMinImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reference front() const {
|
||||||
|
return *this->GetMinImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator erase(iterator it) {
|
||||||
|
auto cur = std::addressof(*it);
|
||||||
|
auto next = GetNext(cur);
|
||||||
|
this->RemoveImpl(cur);
|
||||||
|
return iterator(next);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Traits, class Comparator>
|
||||||
|
class IntrusiveRedBlackTree {
|
||||||
|
NON_COPYABLE(IntrusiveRedBlackTree);
|
||||||
public:
|
public:
|
||||||
|
using ImplType = impl::IntrusiveRedBlackTreeImpl;
|
||||||
|
private:
|
||||||
|
ImplType impl;
|
||||||
|
public:
|
||||||
|
struct IntrusiveRedBlackTreeRootWithCompare : ImplType::IntrusiveRedBlackTreeRoot{};
|
||||||
|
|
||||||
template<bool Const>
|
template<bool Const>
|
||||||
class Iterator;
|
class Iterator;
|
||||||
|
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using difference_type = ptrdiff_t;
|
using difference_type = ptrdiff_t;
|
||||||
using pointer = T *;
|
using pointer = T *;
|
||||||
using const_pointer = const T *;
|
using const_pointer = const T *;
|
||||||
using reference = T &;
|
using reference = T &;
|
||||||
using const_reference = const T &;
|
using const_reference = const T &;
|
||||||
using iterator = Iterator<false>;
|
using iterator = Iterator<false>;
|
||||||
using const_iterator = Iterator<true>;
|
using const_iterator = Iterator<true>;
|
||||||
|
|
||||||
template<bool Const>
|
template<bool Const>
|
||||||
class Iterator {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
friend class IntrusiveRedBlackTree<T, Traits, Comparator>;
|
||||||
using value_type = typename IntrusiveRedBlackTreeImpl::value_type;
|
|
||||||
using difference_type = typename IntrusiveRedBlackTreeImpl::difference_type;
|
|
||||||
using pointer = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_pointer, IntrusiveRedBlackTreeImpl::pointer>::type;
|
|
||||||
using reference = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_reference, IntrusiveRedBlackTreeImpl::reference>::type;
|
|
||||||
private:
|
|
||||||
pointer node;
|
|
||||||
public:
|
|
||||||
explicit Iterator(pointer n) : node(n) { /* ... */ }
|
|
||||||
|
|
||||||
|
using ImplIterator = typename std::conditional<Const, ImplType::const_iterator, ImplType::iterator>::type;
|
||||||
|
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using value_type = typename IntrusiveRedBlackTree::value_type;
|
||||||
|
using difference_type = typename IntrusiveRedBlackTree::difference_type;
|
||||||
|
using pointer = typename std::conditional<Const, IntrusiveRedBlackTree::const_pointer, IntrusiveRedBlackTree::pointer>::type;
|
||||||
|
using reference = typename std::conditional<Const, IntrusiveRedBlackTree::const_reference, IntrusiveRedBlackTree::reference>::type;
|
||||||
|
private:
|
||||||
|
ImplIterator iterator;
|
||||||
|
private:
|
||||||
|
explicit Iterator(ImplIterator it) : iterator(it) { /* ... */ }
|
||||||
|
|
||||||
|
explicit Iterator(ImplIterator::pointer p) : iterator(p) { /* ... */ }
|
||||||
|
|
||||||
|
ImplIterator GetImplIterator() const {
|
||||||
|
return this->iterator;
|
||||||
|
}
|
||||||
|
public:
|
||||||
bool operator==(const Iterator &rhs) const {
|
bool operator==(const Iterator &rhs) const {
|
||||||
return this->node == rhs.node;
|
return this->iterator == rhs.iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Iterator &rhs) const {
|
bool operator!=(const Iterator &rhs) const {
|
||||||
@@ -81,99 +290,77 @@ namespace ams::util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pointer operator->() const {
|
pointer operator->() const {
|
||||||
return this->node;
|
return Traits::GetParent(std::addressof(*this->iterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
reference operator*() const {
|
reference operator*() const {
|
||||||
return *this->node;
|
return *Traits::GetParent(std::addressof(*this->iterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator &operator++() {
|
Iterator &operator++() {
|
||||||
this->node = Traits::GetParent(GetNext(Traits::GetNode(this->node)));
|
++this->iterator;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator &operator--() {
|
Iterator &operator--() {
|
||||||
this->node = Traits::GetParent(GetPrev(Traits::GetNode(this->node)));
|
--this->iterator;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator++(int) {
|
Iterator operator++(int) {
|
||||||
const Iterator it{*this};
|
const Iterator it{*this};
|
||||||
++(*this);
|
++this->iterator;
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator--(int) {
|
Iterator operator--(int) {
|
||||||
const Iterator it{*this};
|
const Iterator it{*this};
|
||||||
--(*this);
|
--this->iterator;
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator Iterator<true>() const {
|
operator Iterator<true>() const {
|
||||||
return Iterator<true>(this->node);
|
return Iterator<true>(this->iterator);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
protected:
|
|
||||||
/* Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot. */
|
|
||||||
RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry);
|
|
||||||
private:
|
private:
|
||||||
|
/* Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot. */
|
||||||
|
RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode, entry, CompareImpl);
|
||||||
|
private:
|
||||||
|
static int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) {
|
||||||
|
return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
/* Define accessors using RB_* functions. */
|
/* Define accessors using RB_* functions. */
|
||||||
constexpr ALWAYS_INLINE void InitializeImpl() {
|
IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
|
||||||
RB_INIT(&this->root);
|
return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare, static_cast<IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmptyImpl() const {
|
IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||||
return RB_EMPTY(&this->root);
|
return RB_FIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode *GetMinImpl() const {
|
IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||||
return RB_MIN(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
return RB_NFIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
||||||
}
|
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode *GetMaxImpl() const {
|
|
||||||
return RB_MAX(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
|
||||||
}
|
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
|
|
||||||
return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node);
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
static constexpr inline IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) {
|
constexpr ALWAYS_INLINE IntrusiveRedBlackTree() : impl() { /* ... */ }
|
||||||
return RB_NEXT(IntrusiveRedBlackTreeRoot, nullptr, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr inline IntrusiveRedBlackTreeNode const *GetNext(IntrusiveRedBlackTreeNode const *node) {
|
|
||||||
return const_cast<const IntrusiveRedBlackTreeNode *>(GetNext(const_cast<IntrusiveRedBlackTreeNode *>(node)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr inline IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) {
|
|
||||||
return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr inline IntrusiveRedBlackTreeNode const *GetPrev(IntrusiveRedBlackTreeNode const *node) {
|
|
||||||
return const_cast<const IntrusiveRedBlackTreeNode *>(GetPrev(const_cast<IntrusiveRedBlackTreeNode *>(node)));
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeImpl() : root() {
|
|
||||||
this->InitializeImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterator accessors. */
|
/* Iterator accessors. */
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
return iterator(Traits::GetParent(this->GetMinImpl()));
|
return iterator(this->impl.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator begin() const {
|
const_iterator begin() const {
|
||||||
return const_iterator(Traits::GetParent(this->GetMinImpl()));
|
return const_iterator(this->impl.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator end() {
|
iterator end() {
|
||||||
return iterator(Traits::GetParent(static_cast<IntrusiveRedBlackTreeNode *>(nullptr)));
|
return iterator(this->impl.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator end() const {
|
const_iterator end() const {
|
||||||
return const_iterator(Traits::GetParent(static_cast<IntrusiveRedBlackTreeNode *>(nullptr)));
|
return const_iterator(this->impl.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cbegin() const {
|
const_iterator cbegin() const {
|
||||||
@@ -185,93 +372,50 @@ namespace ams::util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
iterator iterator_to(reference ref) {
|
iterator iterator_to(reference ref) {
|
||||||
return iterator(&ref);
|
return iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator iterator_to(const_reference ref) const {
|
const_iterator iterator_to(const_reference ref) const {
|
||||||
return const_iterator(&ref);
|
return const_iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Content management. */
|
/* Content management. */
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return this->EmptyImpl();
|
return this->impl.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
reference back() {
|
reference back() {
|
||||||
return *Traits::GetParent(this->GetMaxImpl());
|
return *Traits::GetParent(std::addressof(this->impl.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const_reference back() const {
|
const_reference back() const {
|
||||||
return *Traits::GetParent(this->GetMaxImpl());
|
return *Traits::GetParent(std::addressof(this->impl.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
reference front() {
|
reference front() {
|
||||||
return *Traits::GetParent(this->GetMinImpl());
|
return *Traits::GetParent(std::addressof(this->impl.front()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const_reference front() const {
|
const_reference front() const {
|
||||||
return *Traits::GetParent(this->GetMinImpl());
|
return *Traits::GetParent(std::addressof(this->impl.front()));
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator erase(iterator it) {
|
iterator erase(iterator it) {
|
||||||
auto cur = Traits::GetNode(&*it);
|
return iterator(this->impl.erase(it.GetImplIterator()));
|
||||||
auto next = Traits::GetParent(GetNext(cur));
|
|
||||||
this->RemoveImpl(cur);
|
|
||||||
return iterator(next);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template<class T, class Traits, class Comparator>
|
|
||||||
class IntrusiveRedBlackTree : public IntrusiveRedBlackTreeImpl<T, Traits> {
|
|
||||||
NON_COPYABLE(IntrusiveRedBlackTree);
|
|
||||||
public:
|
|
||||||
using ImplType = IntrusiveRedBlackTreeImpl<T, Traits>;
|
|
||||||
|
|
||||||
struct IntrusiveRedBlackTreeRootWithCompare : ImplType::IntrusiveRedBlackTreeRoot{};
|
|
||||||
|
|
||||||
using value_type = ImplType::value_type;
|
|
||||||
using size_type = ImplType::size_type;
|
|
||||||
using difference_type = ImplType::difference_type;
|
|
||||||
using pointer = ImplType::pointer;
|
|
||||||
using const_pointer = ImplType::const_pointer;
|
|
||||||
using reference = ImplType::reference;
|
|
||||||
using const_reference = ImplType::const_reference;
|
|
||||||
using iterator = ImplType::iterator;
|
|
||||||
using const_iterator = ImplType::const_iterator;
|
|
||||||
protected:
|
|
||||||
/* Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot. */
|
|
||||||
RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode, entry, CompareImpl);
|
|
||||||
private:
|
|
||||||
static int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) {
|
|
||||||
return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Define accessors using RB_* functions. */
|
|
||||||
IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
|
|
||||||
return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare, static_cast<IntrusiveRedBlackTreeRootWithCompare *>(&this->root), node);
|
|
||||||
}
|
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
|
||||||
return RB_FIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
|
||||||
return RB_NFIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTree() : ImplType() { /* ... */ }
|
|
||||||
|
|
||||||
iterator insert(reference ref) {
|
iterator insert(reference ref) {
|
||||||
this->InsertImpl(Traits::GetNode(&ref));
|
ImplType::pointer node = Traits::GetNode(std::addressof(ref));
|
||||||
return iterator(&ref);
|
this->InsertImpl(node);
|
||||||
|
return iterator(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator find(const_reference ref) const {
|
iterator find(const_reference ref) const {
|
||||||
return iterator(Traits::GetParent(this->FindImpl(Traits::GetNode(&ref))));
|
return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref))));
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator nfind(const_reference ref) const {
|
iterator nfind(const_reference ref) const {
|
||||||
return iterator(Traits::GetParent(this->NFindImpl(Traits::GetNode(&ref))));
|
return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref))));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -283,12 +427,12 @@ namespace ams::util {
|
|||||||
public:
|
public:
|
||||||
template<class Comparator>
|
template<class Comparator>
|
||||||
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraits, Comparator>;
|
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraits, Comparator>;
|
||||||
using TreeTypeImpl = IntrusiveRedBlackTreeImpl<Derived, IntrusiveRedBlackTreeMemberTraits>;
|
using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
|
||||||
private:
|
private:
|
||||||
template<class, class, class>
|
template<class, class, class>
|
||||||
friend class IntrusiveRedBlackTree;
|
friend class IntrusiveRedBlackTree;
|
||||||
template<class, class>
|
|
||||||
friend class IntrusiveRedBlackTreeImpl;
|
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||||
|
|
||||||
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||||
return std::addressof(parent->*Member);
|
return std::addressof(parent->*Member);
|
||||||
@@ -318,7 +462,7 @@ namespace ams::util {
|
|||||||
public:
|
public:
|
||||||
template<class Comparator>
|
template<class Comparator>
|
||||||
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>;
|
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>;
|
||||||
using TreeTypeImpl = IntrusiveRedBlackTreeImpl<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert>;
|
using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
|
||||||
|
|
||||||
static constexpr bool IsValid() {
|
static constexpr bool IsValid() {
|
||||||
TYPED_STORAGE(Derived) DerivedStorage = {};
|
TYPED_STORAGE(Derived) DerivedStorage = {};
|
||||||
@@ -327,8 +471,8 @@ namespace ams::util {
|
|||||||
private:
|
private:
|
||||||
template<class, class, class>
|
template<class, class, class>
|
||||||
friend class IntrusiveRedBlackTree;
|
friend class IntrusiveRedBlackTree;
|
||||||
template<class, class>
|
|
||||||
friend class IntrusiveRedBlackTreeImpl;
|
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||||
|
|
||||||
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||||
return std::addressof(parent->*Member);
|
return std::addressof(parent->*Member);
|
||||||
@@ -350,11 +494,11 @@ namespace ams::util {
|
|||||||
template<class Derived>
|
template<class Derived>
|
||||||
class IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
|
class IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
|
||||||
public:
|
public:
|
||||||
constexpr ALWAYS_INLINE Derived *GetPrev();
|
constexpr ALWAYS_INLINE Derived *GetPrev() { return static_cast< Derived *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this)); }
|
||||||
constexpr ALWAYS_INLINE const Derived *GetPrev() const;
|
constexpr ALWAYS_INLINE const Derived *GetPrev() const { return static_cast<const Derived *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this)); }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Derived *GetNext();
|
constexpr ALWAYS_INLINE Derived *GetNext() { return static_cast< Derived *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this)); }
|
||||||
constexpr ALWAYS_INLINE const Derived *GetNext() const;
|
constexpr ALWAYS_INLINE const Derived *GetNext() const { return static_cast<const Derived *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
@@ -362,12 +506,12 @@ namespace ams::util {
|
|||||||
public:
|
public:
|
||||||
template<class Comparator>
|
template<class Comparator>
|
||||||
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeBaseTraits, Comparator>;
|
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeBaseTraits, Comparator>;
|
||||||
using TreeTypeImpl = IntrusiveRedBlackTreeImpl<Derived, IntrusiveRedBlackTreeBaseTraits>;
|
using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
|
||||||
private:
|
private:
|
||||||
template<class, class, class>
|
template<class, class, class>
|
||||||
friend class IntrusiveRedBlackTree;
|
friend class IntrusiveRedBlackTree;
|
||||||
template<class, class>
|
|
||||||
friend class IntrusiveRedBlackTreeImpl;
|
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||||
|
|
||||||
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||||
return static_cast<IntrusiveRedBlackTreeNode *>(parent);
|
return static_cast<IntrusiveRedBlackTreeNode *>(parent);
|
||||||
@@ -386,16 +530,4 @@ namespace ams::util {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Derived>
|
|
||||||
constexpr Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetPrev() { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<Derived *>(TreeType::GetPrev(static_cast<Derived *>(this))); }
|
|
||||||
|
|
||||||
template<class Derived>
|
|
||||||
constexpr const Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetPrev() const { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<const Derived *>(TreeType::GetPrev(static_cast<const Derived *>(this))); }
|
|
||||||
|
|
||||||
template<class Derived>
|
|
||||||
constexpr Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetNext() { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<Derived *>(TreeType::GetNext(static_cast<Derived *>(this))); }
|
|
||||||
|
|
||||||
template<class Derived>
|
|
||||||
constexpr const Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetNext() const { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<const Derived *>(TreeType::GetNext(static_cast<const Derived *>(this))); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,41 @@
|
|||||||
TARGETS := kernel.bin kernel_ldr.bin
|
ATMOSPHERE_BUILD_CONFIGS :=
|
||||||
CLEAN_TARGETS := $(foreach target,$(TARGETS),$(target:.bin=)-clean)
|
all: release
|
||||||
|
|
||||||
SUBFOLDERS := $(MODULES)
|
define ATMOSPHERE_ADD_TARGET
|
||||||
|
|
||||||
all: mesosphere.bin
|
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
|
||||||
|
|
||||||
clean: $(CLEAN_TARGETS)
|
$(strip $1): mesosphere$(strip $2).bin
|
||||||
@rm -f mesosphere.bin
|
|
||||||
|
|
||||||
mesosphere.bin: $(TARGETS)
|
mesosphere$(strip $2).bin: kernel/kernel$(strip $2).bin kernel_ldr/kernel_ldr$(strip $2).bin
|
||||||
@python build_mesosphere.py
|
@python build_mesosphere.py kernel_ldr/kernel_ldr$(strip $2).bin kernel/kernel$(strip $2).bin mesosphere$(strip $2).bin
|
||||||
@echo "Built mesosphere.bin..."
|
@echo "Built mesosphere$(strip $2).bin..."
|
||||||
|
|
||||||
$(TARGETS): check_libmeso
|
kernel/kernel$(strip $2).bin: check_libmeso$(strip $1)
|
||||||
$(MAKE) -C $(@:.bin=)
|
@$$(MAKE) -C kernel $(strip $1)
|
||||||
@cp $(@:.bin=)/$(@) $(@)
|
|
||||||
|
|
||||||
check_libmeso:
|
kernel_ldr/kernel_ldr$(strip $2).bin: check_libmeso$(strip $1)
|
||||||
@$(MAKE) --no-print-directory -C ../libraries/libmesosphere
|
@$$(MAKE) -C kernel_ldr $(strip $1)
|
||||||
|
|
||||||
$(CLEAN_TARGETS):
|
check_libmeso$(strip $1):
|
||||||
$(MAKE) -C $(@:-clean=) clean
|
@$$(MAKE) -C ../libraries/libmesosphere $(strip $1)
|
||||||
@rm -f $(@:-clean=).bin
|
|
||||||
|
|
||||||
.PHONY: all clean $(CLEAN_TARGETS)
|
clean-$(strip $1):
|
||||||
|
@$$(MAKE) -C ../libraries/libmesosphere clean-$(strip $1)
|
||||||
|
@$$(MAKE) -C kernel clean-$(strip $1)
|
||||||
|
@$$(MAKE) -C kernel_ldr clean-$(strip $1)
|
||||||
|
@rm -f mesosphere$(strip $2).bin
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, release, ,))
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug,))
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit,))
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@$(MAKE) -C ../libraries/libmesosphere clean
|
||||||
|
@$(MAKE) -C kernel clean
|
||||||
|
@$(MAKE) -C kernel_ldr clean
|
||||||
|
@rm -f mesosphere*.bin
|
||||||
|
|
||||||
|
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ def align_up(val, algn):
|
|||||||
|
|
||||||
|
|
||||||
def main(argc, argv):
|
def main(argc, argv):
|
||||||
if argc != 1:
|
if argc != 4:
|
||||||
print('Usage: %s' % argv[0])
|
print('Usage: %s kernel_ldr.bin kernel.bin output.bin' % argv[0])
|
||||||
return 1
|
return 1
|
||||||
with open('kernel_ldr/kernel_ldr.bin', 'rb') as f:
|
with open(argv[1], 'rb') as f:
|
||||||
kernel_ldr = f.read()
|
kernel_ldr = f.read()
|
||||||
with open('kernel/kernel.bin', 'rb') as f:
|
with open(argv[2], 'rb') as f:
|
||||||
kernel = f.read()
|
kernel = f.read()
|
||||||
kernel_metadata_offset = 4
|
kernel_metadata_offset = 4
|
||||||
assert (kernel_metadata_offset <= len(kernel) - 0x40)
|
assert (kernel_metadata_offset <= len(kernel) - 0x40)
|
||||||
@@ -37,7 +37,7 @@ def main(argc, argv):
|
|||||||
kernel_ldr_end = kernel_ldr_offset + len(kernel_ldr)
|
kernel_ldr_end = kernel_ldr_offset + len(kernel_ldr)
|
||||||
mesosphere_end = align_up(kernel_ldr_end, 0x1000)
|
mesosphere_end = align_up(kernel_ldr_end, 0x1000)
|
||||||
|
|
||||||
with open('mesosphere.bin', 'wb') as f:
|
with open(argv[3], 'wb') as f:
|
||||||
f.write(kernel[:kernel_metadata_offset + 4])
|
f.write(kernel[:kernel_metadata_offset + 4])
|
||||||
f.write(pk('<QQI', embedded_ini_offset, kernel_ldr_offset, atmosphere_target_firmware(10, 1, 0)))
|
f.write(pk('<QQI', embedded_ini_offset, kernel_ldr_offset, atmosphere_target_firmware(10, 1, 0)))
|
||||||
f.write(kernel[kernel_metadata_offset + 0x18:])
|
f.write(kernel[kernel_metadata_offset + 0x18:])
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in common atmosphere configuration
|
# pull in common atmosphere configuration
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/mesosphere.mk
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
include $(CURRENT_DIRECTORY)/../../libraries/config/templates/mesosphere.mk
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# no real need to edit anything past this point unless you need to add additional
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
# rules for different file extensions
|
# rules for different file extensions
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
ifneq ($(__RECURSIVE__),1)
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
||||||
export TOPDIR := $(CURDIR)
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
|
||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
||||||
@@ -44,41 +42,72 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
-I.
|
-I.
|
||||||
|
|
||||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
|
||||||
|
|
||||||
.PHONY: $(BUILD) clean all
|
export TOPDIR := $(CURRENT_DIRECTORY)
|
||||||
|
|
||||||
|
OUTPUT_BASE := $(TOPDIR)/$(notdir $(TOPDIR))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: $(BUILD) check_libmeso
|
|
||||||
|
|
||||||
$(BUILD): check_libmeso
|
ATMOSPHERE_BUILD_CONFIGS :=
|
||||||
|
all: release
|
||||||
|
|
||||||
|
define ATMOSPHERE_ADD_TARGET
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
|
||||||
|
|
||||||
|
$(strip $1): check_libmeso_$(strip $1) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1)
|
||||||
|
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(OUTPUT_BASE)$(strip $2) $(3) \
|
||||||
|
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
LIBMESOSPHERE_NAME=mesosphere$(strip $2) \
|
||||||
|
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
-f $$(THIS_MAKEFILE)
|
||||||
|
|
||||||
|
check_libmeso_$(strip $1):
|
||||||
|
@$$(MAKE) --no-print-directory -C ../../libraries/libmesosphere $(strip $1)
|
||||||
|
|
||||||
|
clean-$(strip $1):
|
||||||
|
@echo clean $(strip $1) ...
|
||||||
|
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).elf
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, release, , \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(ATMOSPHERE_BUILD_DIR)/%:
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
|
||||||
|
|
||||||
check_libmeso:
|
|
||||||
@$(MAKE) --no-print-directory -C ../../libraries/libmesosphere
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
|
||||||
@echo clean ...
|
|
||||||
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf
|
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
.PHONY: all
|
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d)
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# main targets
|
# main targets
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all : $(OUTPUT).bin
|
|
||||||
|
|
||||||
$(OUTPUT).bin : $(OUTPUT).elf
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
||||||
@echo built ... $(notdir $@)
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
$(OUTPUT).elf : $(OFILES) ../../../libraries/libmesosphere/lib/libmesosphere.a
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
$(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libmesosphere/$(ATMOSPHERE_LIBRARY_DIR)/lib$(LIBMESOSPHERE_NAME).a
|
||||||
|
|
||||||
%.elf:
|
%.elf:
|
||||||
@echo linking $(notdir $@)
|
@echo linking $(notdir $@)
|
||||||
@@ -101,4 +130,4 @@ kern_libc_generic.o: CFLAGS += -fno-builtin
|
|||||||
|
|
||||||
#---------------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------------
|
||||||
endif
|
endif
|
||||||
#---------------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------------
|
||||||
@@ -1,20 +1,18 @@
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# pull in common atmosphere configuration
|
# pull in common atmosphere configuration
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/mesosphere.mk
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
include $(CURRENT_DIRECTORY)/../../libraries/config/templates/mesosphere.mk
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# no real need to edit anything past this point unless you need to add additional
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
# rules for different file extensions
|
# rules for different file extensions
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
ifneq ($(__RECURSIVE__),1)
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
|
||||||
export TOPDIR := $(CURDIR)
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
|
||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
||||||
@@ -44,41 +42,72 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
-I.
|
-I.
|
||||||
|
|
||||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
|
||||||
|
|
||||||
.PHONY: $(BUILD) clean all
|
export TOPDIR := $(CURRENT_DIRECTORY)
|
||||||
|
|
||||||
|
OUTPUT_BASE := $(TOPDIR)/$(notdir $(TOPDIR))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: $(BUILD) check_libmeso
|
|
||||||
|
|
||||||
$(BUILD): check_libmeso
|
ATMOSPHERE_BUILD_CONFIGS :=
|
||||||
|
all: release
|
||||||
|
|
||||||
|
define ATMOSPHERE_ADD_TARGET
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
|
||||||
|
|
||||||
|
$(strip $1): check_libmeso_$(strip $1) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1)
|
||||||
|
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(OUTPUT_BASE)$(strip $2) $(3) \
|
||||||
|
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
LIBMESOSPHERE_NAME=mesosphere$(strip $2) \
|
||||||
|
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
|
||||||
|
-f $$(THIS_MAKEFILE)
|
||||||
|
|
||||||
|
check_libmeso_$(strip $1):
|
||||||
|
@$$(MAKE) --no-print-directory -C ../../libraries/libmesosphere $(strip $1)
|
||||||
|
|
||||||
|
clean-$(strip $1):
|
||||||
|
@echo clean $(strip $1) ...
|
||||||
|
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).elf
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, release, , \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit, \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(ATMOSPHERE_BUILD_DIR)/%:
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
|
||||||
|
|
||||||
check_libmeso:
|
|
||||||
@$(MAKE) --no-print-directory -C ../../libraries/libmesosphere
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
|
||||||
@echo clean ...
|
|
||||||
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf
|
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
.PHONY: all
|
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d)
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# main targets
|
# main targets
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all : $(OUTPUT).bin
|
|
||||||
|
|
||||||
$(OUTPUT).bin : $(OUTPUT).elf
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
||||||
@echo built ... $(notdir $@)
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
$(OUTPUT).elf : $(OFILES) ../../../libraries/libmesosphere/lib/libmesosphere.a
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
$(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libmesosphere/$(ATMOSPHERE_LIBRARY_DIR)/lib$(LIBMESOSPHERE_NAME).a
|
||||||
|
|
||||||
%.elf:
|
%.elf:
|
||||||
@echo linking $(notdir $@)
|
@echo linking $(notdir $@)
|
||||||
@@ -101,4 +130,4 @@ kern_libc_generic.o: CFLAGS += -fno-builtin
|
|||||||
|
|
||||||
#---------------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------------
|
||||||
endif
|
endif
|
||||||
#---------------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------------
|
||||||
@@ -64,6 +64,10 @@ namespace ams::mitm {
|
|||||||
/* Emummc file protection. */
|
/* Emummc file protection. */
|
||||||
FsFile g_emummc_file;
|
FsFile g_emummc_file;
|
||||||
|
|
||||||
|
/* Maintain exclusive access to the fusee-secondary archive. */
|
||||||
|
FsFile g_secondary_file;
|
||||||
|
FsFile g_sept_payload_file;
|
||||||
|
|
||||||
constexpr inline bool IsHexadecimal(const char *str) {
|
constexpr inline bool IsHexadecimal(const char *str) {
|
||||||
while (*str) {
|
while (*str) {
|
||||||
if (std::isxdigit(static_cast<unsigned char>(*str))) {
|
if (std::isxdigit(static_cast<unsigned char>(*str))) {
|
||||||
@@ -129,6 +133,15 @@ namespace ams::mitm {
|
|||||||
R_ABORT_UNLESS(fsFileWrite(&g_bis_key_file, 0, bis_keys, sizeof(bis_keys), FsWriteOption_Flush));
|
R_ABORT_UNLESS(fsFileWrite(&g_bis_key_file, 0, bis_keys, sizeof(bis_keys), FsWriteOption_Flush));
|
||||||
/* NOTE: g_bis_key_file is intentionally not closed here. This prevents any other process from opening it. */
|
/* NOTE: g_bis_key_file is intentionally not closed here. This prevents any other process from opening it. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open a reference to the fusee-secondary archive. */
|
||||||
|
/* As upcoming/current atmosphere releases will contain more than one zip which users much choose between, */
|
||||||
|
/* maintaining an open reference prevents cleanly the issue of "automatic" updaters selecting the incorrect */
|
||||||
|
/* zip, and encourages good updating hygiene -- atmosphere should not be updated on SD while HOS is alive. */
|
||||||
|
{
|
||||||
|
R_ABORT_UNLESS(mitm::fs::OpenSdFile(std::addressof(g_secondary_file), "/atmosphere/fusee-secondary.bin", ams::fs::OpenMode_Read));
|
||||||
|
R_ABORT_UNLESS(mitm::fs::OpenSdFile(std::addressof(g_sept_payload_file), "/sept/payload.bin", ams::fs::OpenMode_Read));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialization implementation */
|
/* Initialization implementation */
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ namespace ams::mitm::bpc {
|
|||||||
/* Copy in payload. */
|
/* Copy in payload. */
|
||||||
std::memcpy(g_reboot_payload, payload, payload_size);
|
std::memcpy(g_reboot_payload, payload, payload_size);
|
||||||
|
|
||||||
|
/* Note to the secure monitor that we have a payload. */
|
||||||
|
spl::smc::SetConfig(spl::ConfigItem::ExospherePayloadAddress, g_reboot_payload, nullptr, 0);
|
||||||
|
|
||||||
/* NOTE: Preferred reboot type may be overrwritten when parsed from settings during boot. */
|
/* NOTE: Preferred reboot type may be overrwritten when parsed from settings during boot. */
|
||||||
g_reboot_type = RebootType::ToPayload;
|
g_reboot_type = RebootType::ToPayload;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,37 +15,94 @@
|
|||||||
*/
|
*/
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
#include "set_mitm_service.hpp"
|
#include "set_mitm_service.hpp"
|
||||||
|
#include "set_shim.h"
|
||||||
|
|
||||||
namespace ams::mitm::settings {
|
namespace ams::mitm::settings {
|
||||||
|
|
||||||
using namespace ams::settings;
|
using namespace ams::settings;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constinit os::ProcessId g_application_process_id = os::InvalidProcessId;
|
||||||
|
constinit cfg::OverrideLocale g_application_locale;
|
||||||
|
constinit bool g_valid_language;
|
||||||
|
constinit bool g_valid_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMitmService::SetMitmService(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : sf::MitmServiceImplBase(std::forward<std::shared_ptr<::Service>>(s), c) {
|
||||||
|
if (this->client_info.program_id == ncm::SystemProgramId::Ns) {
|
||||||
|
os::ProcessId application_process_id;
|
||||||
|
if (R_SUCCEEDED(pm::dmnt::GetApplicationProcessId(std::addressof(application_process_id))) && g_application_process_id == application_process_id) {
|
||||||
|
this->locale = g_application_locale;
|
||||||
|
this->is_valid_language = g_valid_language;
|
||||||
|
this->is_valid_region = g_valid_region;
|
||||||
|
this->got_locale = true;
|
||||||
|
} else {
|
||||||
|
this->InvalidateLocale();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->InvalidateLocale();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Result SetMitmService::EnsureLocale() {
|
Result SetMitmService::EnsureLocale() {
|
||||||
|
/* Optimization: if locale has already been gotten, we can stop. */
|
||||||
|
if (AMS_LIKELY(this->got_locale)) {
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
std::scoped_lock lk(this->lock);
|
std::scoped_lock lk(this->lock);
|
||||||
|
|
||||||
const bool is_ns = this->client_info.program_id == ncm::SystemProgramId::Ns;
|
const bool is_ns = this->client_info.program_id == ncm::SystemProgramId::Ns;
|
||||||
|
|
||||||
if (!this->got_locale) {
|
if (!this->got_locale) {
|
||||||
std::memset(&this->locale, 0xCC, sizeof(this->locale));
|
|
||||||
ncm::ProgramId program_id = this->client_info.program_id;
|
ncm::ProgramId program_id = this->client_info.program_id;
|
||||||
|
os::ProcessId application_process_id = os::InvalidProcessId;
|
||||||
|
|
||||||
if (is_ns) {
|
if (is_ns) {
|
||||||
/* When NS asks for a locale, refresh to get the current application locale. */
|
/* When NS asks for a locale, refresh to get the current application locale. */
|
||||||
os::ProcessId application_process_id;
|
R_TRY(pm::dmnt::GetApplicationProcessId(std::addressof(application_process_id)));
|
||||||
R_TRY(pm::dmnt::GetApplicationProcessId(&application_process_id));
|
R_TRY(pm::info::GetProgramId(std::addressof(program_id), application_process_id));
|
||||||
R_TRY(pm::info::GetProgramId(&program_id, application_process_id));
|
}
|
||||||
|
this->locale = cfg::GetOverrideLocale(program_id);
|
||||||
|
this->is_valid_language = settings::IsValidLanguageCode(this->locale.language_code);
|
||||||
|
this->is_valid_region = settings::IsValidRegionCode(this->locale.region_code);
|
||||||
|
this->got_locale = true;
|
||||||
|
|
||||||
|
if (is_ns) {
|
||||||
|
g_application_locale = this->locale;
|
||||||
|
g_valid_language = this->is_valid_language;
|
||||||
|
g_valid_region = this->is_valid_region;
|
||||||
|
g_application_process_id = application_process_id;
|
||||||
}
|
}
|
||||||
this->locale = cfg::GetOverrideLocale(program_id);
|
|
||||||
this->got_locale = !is_ns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetMitmService::InvalidateLocale() {
|
||||||
|
std::scoped_lock lk(this->lock);
|
||||||
|
|
||||||
|
std::memset(std::addressof(this->locale), 0xCC, sizeof(this->locale));
|
||||||
|
this->is_valid_language = false;
|
||||||
|
this->is_valid_region = false;
|
||||||
|
this->got_locale = false;
|
||||||
|
}
|
||||||
|
|
||||||
Result SetMitmService::GetLanguageCode(sf::Out<settings::LanguageCode> out) {
|
Result SetMitmService::GetLanguageCode(sf::Out<settings::LanguageCode> out) {
|
||||||
this->EnsureLocale();
|
this->EnsureLocale();
|
||||||
|
|
||||||
/* If there's no override locale, just use the actual one. */
|
/* If there's no override locale, just use the actual one. */
|
||||||
R_UNLESS(settings::IsValidLanguageCode(this->locale.language_code), sm::mitm::ResultShouldForwardToSession());
|
if (AMS_UNLIKELY(!this->is_valid_language)) {
|
||||||
|
static_assert(sizeof(u64) == sizeof(settings::LanguageCode));
|
||||||
|
R_TRY(setGetLanguageCodeFwd(this->forward_service.get(), reinterpret_cast<u64 *>(std::addressof(this->locale.language_code))));
|
||||||
|
|
||||||
|
this->is_valid_language = true;
|
||||||
|
if (this->client_info.program_id == ncm::SystemProgramId::Ns) {
|
||||||
|
g_application_locale.language_code = this->locale.language_code;
|
||||||
|
g_valid_language = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out.SetValue(this->locale.language_code);
|
out.SetValue(this->locale.language_code);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
@@ -55,7 +112,16 @@ namespace ams::mitm::settings {
|
|||||||
this->EnsureLocale();
|
this->EnsureLocale();
|
||||||
|
|
||||||
/* If there's no override locale, just use the actual one. */
|
/* If there's no override locale, just use the actual one. */
|
||||||
R_UNLESS(settings::IsValidRegionCode(this->locale.region_code), sm::mitm::ResultShouldForwardToSession());
|
if (AMS_UNLIKELY(!this->is_valid_region)) {
|
||||||
|
static_assert(sizeof(::SetRegion) == sizeof(settings::RegionCode));
|
||||||
|
R_TRY(setGetRegionCodeFwd(this->forward_service.get(), reinterpret_cast<::SetRegion *>(std::addressof(this->locale.region_code))));
|
||||||
|
|
||||||
|
this->is_valid_region = true;
|
||||||
|
if (this->client_info.program_id == ncm::SystemProgramId::Ns) {
|
||||||
|
g_application_locale.region_code = this->locale.region_code;
|
||||||
|
g_valid_region = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out.SetValue(this->locale.region_code);
|
out.SetValue(this->locale.region_code);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ namespace ams::mitm::settings {
|
|||||||
os::Mutex lock{false};
|
os::Mutex lock{false};
|
||||||
cfg::OverrideLocale locale;
|
cfg::OverrideLocale locale;
|
||||||
bool got_locale = false;
|
bool got_locale = false;
|
||||||
|
bool is_valid_language = false;
|
||||||
|
bool is_valid_region = false;
|
||||||
public:
|
public:
|
||||||
using MitmServiceImplBase::MitmServiceImplBase;
|
SetMitmService(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c);
|
||||||
public:
|
public:
|
||||||
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
|
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
|
||||||
/* We will mitm:
|
/* We will mitm:
|
||||||
@@ -44,6 +46,7 @@ namespace ams::mitm::settings {
|
|||||||
return client_info.program_id == ncm::SystemProgramId::Ns || is_game;
|
return client_info.program_id == ncm::SystemProgramId::Ns || is_game;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
void InvalidateLocale();
|
||||||
Result EnsureLocale();
|
Result EnsureLocale();
|
||||||
public:
|
public:
|
||||||
Result GetLanguageCode(sf::Out<ams::settings::LanguageCode> out);
|
Result GetLanguageCode(sf::Out<ams::settings::LanguageCode> out);
|
||||||
|
|||||||
36
stratosphere/ams_mitm/source/set_mitm/set_shim.c
Normal file
36
stratosphere/ams_mitm/source/set_mitm/set_shim.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include "set_shim.h"
|
||||||
|
|
||||||
|
static Result _setCmdNoInOut64(Service* srv, u64 *out, u32 cmd_id) {
|
||||||
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _setCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
||||||
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forwarding shims. */
|
||||||
|
Result setGetLanguageCodeFwd(Service *s, u64* out) {
|
||||||
|
return _setCmdNoInOut64(s, out, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result setGetRegionCodeFwd(Service *s, SetRegion *out) {
|
||||||
|
s32 code=0;
|
||||||
|
Result rc = _setCmdNoInOutU32(s, (u32*)&code, 4);
|
||||||
|
if (R_SUCCEEDED(rc) && out) *out = code;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
20
stratosphere/ams_mitm/source/set_mitm/set_shim.h
Normal file
20
stratosphere/ams_mitm/source/set_mitm/set_shim.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* @file set_shim.h
|
||||||
|
* @brief Settings Services (fs) IPC wrapper for set.mitm.
|
||||||
|
* @author SciresM
|
||||||
|
* @copyright libnx Authors
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forwarding shims. */
|
||||||
|
Result setGetLanguageCodeFwd(Service *s, u64* out);
|
||||||
|
Result setGetRegionCodeFwd(Service *s, SetRegion *out);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -56,10 +56,18 @@ namespace ams::mitm::settings {
|
|||||||
const auto api_info = exosphere::GetApiInfo();
|
const auto api_info = exosphere::GetApiInfo();
|
||||||
const char emummc_char = emummc::IsActive() ? 'E' : 'S';
|
const char emummc_char = emummc::IsActive() ? 'E' : 'S';
|
||||||
|
|
||||||
|
/* NOTE: While Mesosphere is in experimental/opt-in, we will display it as part of the firmware. */
|
||||||
|
const char mesosphere_char = svc::IsKernelMesosphere() ? 'M' : '0';
|
||||||
|
|
||||||
|
/* TODO: Remove separate display for mesosphere vs not mesosphere in Atmosphere 1.0.0. */
|
||||||
|
AMS_ABORT_UNLESS(api_info.GetMajorVersion() == 0);
|
||||||
|
|
||||||
/* NOTE: We have carefully accounted for the size of the string we print. */
|
/* NOTE: We have carefully accounted for the size of the string we print. */
|
||||||
/* No truncation occurs assuming two-digits for all version number components. */
|
/* No truncation occurs assuming two-digits for all version number components. */
|
||||||
char display_version[sizeof(g_ams_firmware_version.display_version)];
|
char display_version[sizeof(g_ams_firmware_version.display_version)];
|
||||||
std::snprintf(display_version, sizeof(display_version), "%s|AMS %u.%u.%u|%c", g_ams_firmware_version.display_version, api_info.GetMajorVersion(), api_info.GetMinorVersion(), api_info.GetMicroVersion(), emummc_char);
|
|
||||||
|
std::snprintf(display_version, sizeof(display_version), "%s|AMS %c.%u.%u|%c", g_ams_firmware_version.display_version, mesosphere_char, api_info.GetMinorVersion(), api_info.GetMicroVersion(), emummc_char);
|
||||||
|
|
||||||
std::memcpy(g_ams_firmware_version.display_version, display_version, sizeof(display_version));
|
std::memcpy(g_ams_firmware_version.display_version, display_version, sizeof(display_version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -351,6 +351,10 @@ namespace ams::creport {
|
|||||||
|
|
||||||
void CrashReport::SaveToFile(ScopedFile &file) {
|
void CrashReport::SaveToFile(ScopedFile &file) {
|
||||||
file.WriteFormat("Atmosphère Crash Report (v1.5):\n");
|
file.WriteFormat("Atmosphère Crash Report (v1.5):\n");
|
||||||
|
|
||||||
|
/* TODO: Remove in Atmosphere 1.0.0. */
|
||||||
|
file.WriteFormat("Mesosphere: %s\n", svc::IsKernelMesosphere() ? "Enabled" : "Disabled");
|
||||||
|
|
||||||
file.WriteFormat("Result: 0x%X (2%03d-%04d)\n\n", this->result.GetValue(), this->result.GetModule(), this->result.GetDescription());
|
file.WriteFormat("Result: 0x%X (2%03d-%04d)\n\n", this->result.GetValue(), this->result.GetModule(), this->result.GetDescription());
|
||||||
|
|
||||||
/* Process Info. */
|
/* Process Info. */
|
||||||
|
|||||||
@@ -214,7 +214,9 @@ namespace ams::fatal::srv {
|
|||||||
font::AddSpacingLines(0.5f);
|
font::AddSpacingLines(0.5f);
|
||||||
font::PrintFormatLine( "Program: %016lX", static_cast<u64>(this->context->program_id));
|
font::PrintFormatLine( "Program: %016lX", static_cast<u64>(this->context->program_id));
|
||||||
font::AddSpacingLines(0.5f);
|
font::AddSpacingLines(0.5f);
|
||||||
font::PrintFormatLine("Firmware: %s (Atmosphère %u.%u.%u-%s)", config.GetFirmwareVersion().display_version, ATMOSPHERE_RELEASE_VERSION, ams::GetGitRevision());
|
|
||||||
|
/* TODO: Remove Mesosphere identifier in 1.0.0. */
|
||||||
|
font::PrintFormatLine("Firmware: %s (Atmosphère%s %u.%u.%u-%s)", config.GetFirmwareVersion().display_version, svc::IsKernelMesosphere() ? " M" : "", ATMOSPHERE_RELEASE_VERSION, ams::GetGitRevision());
|
||||||
font::AddSpacingLines(1.5f);
|
font::AddSpacingLines(1.5f);
|
||||||
if (!exosphere::ResultVersionMismatch::Includes(this->context->result)) {
|
if (!exosphere::ResultVersionMismatch::Includes(this->context->result)) {
|
||||||
font::Print(config.GetErrorDescription());
|
font::Print(config.GetErrorDescription());
|
||||||
|
|||||||
@@ -198,6 +198,8 @@ namespace ams::ldr {
|
|||||||
if (status.IsHbl()) {
|
if (status.IsHbl()) {
|
||||||
if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), SdOrBaseMetaPath, fs::OpenMode_Read))) {
|
if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), SdOrBaseMetaPath, fs::OpenMode_Read))) {
|
||||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(LoadMetaFromFile(file, &g_original_meta_cache))) {
|
if (R_SUCCEEDED(LoadMetaFromFile(file, &g_original_meta_cache))) {
|
||||||
Meta *o_meta = &g_original_meta_cache.meta;
|
Meta *o_meta = &g_original_meta_cache.meta;
|
||||||
|
|
||||||
@@ -212,6 +214,15 @@ namespace ams::ldr {
|
|||||||
caps::SetProgramInfoFlags(program_info_flags, meta->aci_kac, meta->aci->kac_size);
|
caps::SetProgramInfoFlags(program_info_flags, meta->aci_kac, meta->aci->kac_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When hbl is applet, adjust main thread priority. */
|
||||||
|
if ((caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet) {
|
||||||
|
constexpr auto HblMainThreadPriorityApplication = 44;
|
||||||
|
constexpr auto HblMainThreadPriorityApplet = 40;
|
||||||
|
if (meta->npdm->main_thread_priority == HblMainThreadPriorityApplication) {
|
||||||
|
meta->npdm->main_thread_priority = HblMainThreadPriorityApplet;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (hos::GetVersion() >= hos::Version_10_0_0) {
|
} else if (hos::GetVersion() >= hos::Version_10_0_0) {
|
||||||
/* If storage id is none, there is no base code filesystem, and thus it is impossible for us to validate. */
|
/* If storage id is none, there is no base code filesystem, and thus it is impossible for us to validate. */
|
||||||
/* However, if we're an application, we are guaranteed a base code filesystem. */
|
/* However, if we're an application, we are guaranteed a base code filesystem. */
|
||||||
|
|||||||
@@ -382,13 +382,13 @@ namespace ams::ro::impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Context utilities. */
|
/* Context utilities. */
|
||||||
Result RegisterProcess(size_t *out_context_id, Handle process_handle, os::ProcessId process_id) {
|
Result RegisterProcess(size_t *out_context_id, os::ManagedHandle process_handle, os::ProcessId process_id) {
|
||||||
/* Validate process handle. */
|
/* Validate process handle. */
|
||||||
{
|
{
|
||||||
os::ProcessId handle_pid = os::InvalidProcessId;
|
os::ProcessId handle_pid = os::InvalidProcessId;
|
||||||
|
|
||||||
/* Validate handle is a valid process handle. */
|
/* Validate handle is a valid process handle. */
|
||||||
R_UNLESS(R_SUCCEEDED(os::TryGetProcessId(&handle_pid, process_handle)), ResultInvalidProcess());
|
R_UNLESS(R_SUCCEEDED(os::TryGetProcessId(&handle_pid, process_handle.Get())), ResultInvalidProcess());
|
||||||
|
|
||||||
/* Validate process id. */
|
/* Validate process id. */
|
||||||
R_UNLESS(handle_pid == process_id, ResultInvalidProcess());
|
R_UNLESS(handle_pid == process_id, ResultInvalidProcess());
|
||||||
@@ -397,7 +397,7 @@ namespace ams::ro::impl {
|
|||||||
/* Check if a process context already exists. */
|
/* Check if a process context already exists. */
|
||||||
R_UNLESS(GetContextByProcessId(process_id) == nullptr, ResultInvalidSession());
|
R_UNLESS(GetContextByProcessId(process_id) == nullptr, ResultInvalidSession());
|
||||||
|
|
||||||
*out_context_id = AllocateContext(process_handle, process_id);
|
*out_context_id = AllocateContext(process_handle.Move(), process_id);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,13 +413,13 @@ namespace ams::ro::impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Service implementations. */
|
/* Service implementations. */
|
||||||
Result RegisterModuleInfo(size_t context_id, Handle process_h, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind, bool enforce_nrr_kind) {
|
Result RegisterModuleInfo(size_t context_id, os::ManagedHandle process_handle, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind, bool enforce_nrr_kind) {
|
||||||
/* Get context. */
|
/* Get context. */
|
||||||
ProcessContext *context = GetContextById(context_id);
|
ProcessContext *context = GetContextById(context_id);
|
||||||
AMS_ABORT_UNLESS(context != nullptr);
|
AMS_ABORT_UNLESS(context != nullptr);
|
||||||
|
|
||||||
/* Get program id. */
|
/* Get program id. */
|
||||||
const ncm::ProgramId program_id = context->GetProgramId(process_h);
|
const ncm::ProgramId program_id = context->GetProgramId(process_handle.Get());
|
||||||
|
|
||||||
/* Validate address/size. */
|
/* Validate address/size. */
|
||||||
R_TRY(ValidateAddressAndNonZeroSize(nrr_address, nrr_size));
|
R_TRY(ValidateAddressAndNonZeroSize(nrr_address, nrr_size));
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ namespace ams::ro::impl {
|
|||||||
bool ShouldEaseNroRestriction();
|
bool ShouldEaseNroRestriction();
|
||||||
|
|
||||||
/* Context utilities. */
|
/* Context utilities. */
|
||||||
Result RegisterProcess(size_t *out_context_id, Handle process_handle, os::ProcessId process_id);
|
Result RegisterProcess(size_t *out_context_id, os::ManagedHandle process_handle, os::ProcessId process_id);
|
||||||
Result ValidateProcess(size_t context_id, os::ProcessId process_id);
|
Result ValidateProcess(size_t context_id, os::ProcessId process_id);
|
||||||
void UnregisterProcess(size_t context_id);
|
void UnregisterProcess(size_t context_id);
|
||||||
|
|
||||||
/* Service implementations. */
|
/* Service implementations. */
|
||||||
Result RegisterModuleInfo(size_t context_id, Handle process_h, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind, bool enforce_nrr_kind);
|
Result RegisterModuleInfo(size_t context_id, os::ManagedHandle process_h, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind, bool enforce_nrr_kind);
|
||||||
Result UnregisterModuleInfo(size_t context_id, u64 nrr_address);
|
Result UnregisterModuleInfo(size_t context_id, u64 nrr_address);
|
||||||
Result MapManualLoadModuleMemory(u64 *out_address, size_t context_id, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
|
Result MapManualLoadModuleMemory(u64 *out_address, size_t context_id, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
|
||||||
Result UnmapManualLoadModuleMemory(size_t context_id, u64 nro_address);
|
Result UnmapManualLoadModuleMemory(size_t context_id, u64 nro_address);
|
||||||
|
|||||||
@@ -56,12 +56,20 @@ namespace ams::ro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result RoService::RegisterProcessHandle(const sf::ClientProcessId &client_pid, sf::CopyHandle process_h) {
|
Result RoService::RegisterProcessHandle(const sf::ClientProcessId &client_pid, sf::CopyHandle process_h) {
|
||||||
return impl::RegisterProcess(std::addressof(this->context_id), process_h.GetValue(), client_pid.GetValue());
|
/* Ensure we manage references to the process handle correctly. */
|
||||||
|
os::ManagedHandle process_handle(process_h.GetValue());
|
||||||
|
|
||||||
|
/* Register the process. */
|
||||||
|
return impl::RegisterProcess(std::addressof(this->context_id), std::move(process_handle), client_pid.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result RoService::RegisterProcessModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h) {
|
Result RoService::RegisterProcessModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h) {
|
||||||
|
/* Ensure we manage references to the process handle correctly. */
|
||||||
|
os::ManagedHandle process_handle(process_h.GetValue());
|
||||||
|
|
||||||
|
/* Register the module. */
|
||||||
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
|
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
|
||||||
return impl::RegisterModuleInfo(this->context_id, process_h.GetValue(), nrr_address, nrr_size, this->nrr_kind, this->nrr_kind == NrrKind_JitPlugin);
|
return impl::RegisterModuleInfo(this->context_id, std::move(process_handle), nrr_address, nrr_size, this->nrr_kind, this->nrr_kind == NrrKind_JitPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,6 +350,12 @@ namespace ams::sm::impl {
|
|||||||
return service == ServiceName::Encode("fsp-srv");
|
return service == ServiceName::Encode("fsp-srv");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShouldCloseOnClientDisconnect(ServiceName service) {
|
||||||
|
/* jit sysmodule is closed and relaunched by am for each application which uses it. */
|
||||||
|
constexpr auto JitU = ServiceName::Encode("jit:u");
|
||||||
|
return service == JitU;
|
||||||
|
}
|
||||||
|
|
||||||
Result GetMitmServiceHandleImpl(Handle *out, ServiceInfo *service_info, const MitmProcessInfo &client_info) {
|
Result GetMitmServiceHandleImpl(Handle *out, ServiceInfo *service_info, const MitmProcessInfo &client_info) {
|
||||||
/* Send command to query if we should mitm. */
|
/* Send command to query if we should mitm. */
|
||||||
bool should_mitm;
|
bool should_mitm;
|
||||||
@@ -419,6 +425,28 @@ namespace ams::sm::impl {
|
|||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Client disconnection callback. */
|
||||||
|
void OnClientDisconnected(os::ProcessId process_id) {
|
||||||
|
/* Ensure that the process id is valid. */
|
||||||
|
if (process_id == os::InvalidProcessId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: Nintendo unregisters all services a process hosted on client close. */
|
||||||
|
/* We do not do this as an atmosphere extension, in order to reduce the number */
|
||||||
|
/* of sessions open at any given time. */
|
||||||
|
/* However, certain system behavior (jit) relies on this occurring. */
|
||||||
|
/* As such, we will special case the system components which rely on the behavior. */
|
||||||
|
for (size_t i = 0; i < ServiceCountMax; i++) {
|
||||||
|
if (g_service_list[i].name != InvalidServiceName && g_service_list[i].owner_process_id == process_id) {
|
||||||
|
if (ShouldCloseOnClientDisconnect(g_service_list[i].name)) {
|
||||||
|
g_service_list[i].Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process management. */
|
/* Process management. */
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
|
|
||||||
namespace ams::sm::impl {
|
namespace ams::sm::impl {
|
||||||
|
|
||||||
|
/* Client disconnection callback. */
|
||||||
|
void OnClientDisconnected(os::ProcessId process_id);
|
||||||
|
|
||||||
/* Process management. */
|
/* Process management. */
|
||||||
Result RegisterProcess(os::ProcessId process_id, ncm::ProgramId program_id, cfg::OverrideStatus, const void *acid_sac, size_t acid_sac_size, const void *aci_sac, size_t aci_sac_size);
|
Result RegisterProcess(os::ProcessId process_id, ncm::ProgramId program_id, cfg::OverrideStatus, const void *acid_sac, size_t acid_sac_size, const void *aci_sac, size_t aci_sac_size);
|
||||||
Result UnregisterProcess(os::ProcessId process_id);
|
Result UnregisterProcess(os::ProcessId process_id);
|
||||||
|
|||||||
@@ -19,6 +19,12 @@
|
|||||||
|
|
||||||
namespace ams::sm {
|
namespace ams::sm {
|
||||||
|
|
||||||
|
UserService::~UserService() {
|
||||||
|
if (this->has_initialized) {
|
||||||
|
impl::OnClientDisconnected(this->process_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Result UserService::RegisterClient(const sf::ClientProcessId &client_process_id) {
|
Result UserService::RegisterClient(const sf::ClientProcessId &client_process_id) {
|
||||||
this->process_id = client_process_id.GetValue();
|
this->process_id = client_process_id.GetValue();
|
||||||
this->has_initialized = true;
|
this->has_initialized = true;
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ namespace ams::sm {
|
|||||||
bool has_initialized = false;
|
bool has_initialized = false;
|
||||||
private:
|
private:
|
||||||
Result EnsureInitialized();
|
Result EnsureInitialized();
|
||||||
|
public:
|
||||||
|
virtual ~UserService();
|
||||||
public:
|
public:
|
||||||
/* Official commands. */
|
/* Official commands. */
|
||||||
Result RegisterClient(const sf::ClientProcessId &client_process_id);
|
Result RegisterClient(const sf::ClientProcessId &client_process_id);
|
||||||
|
|||||||
@@ -273,11 +273,12 @@ def get_full(nxo):
|
|||||||
s.resolved = LOAD_BASE + s.value
|
s.resolved = LOAD_BASE + s.value
|
||||||
if s.name:
|
if s.name:
|
||||||
if s.type == STT_FUNC:
|
if s.type == STT_FUNC:
|
||||||
print(hex(s.resolved), s.name)
|
#print(hex(s.resolved), s.name)
|
||||||
idaapi.add_entry(s.resolved, s.resolved, s.name, 0)
|
#idaapi.add_entry(s.resolved, s.resolved, s.name, 0)
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
idaapi.force_name(s.resolved, s.name)
|
#idaapi.force_name(s.resolved, s.name)
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
# NULL symbol
|
# NULL symbol
|
||||||
s.resolved = 0
|
s.resolved = 0
|
||||||
@@ -353,12 +354,18 @@ def find_categories(full, num_fields):
|
|||||||
return list(up('<'+'I'*num_fields, full[ind:ind+4*num_fields]))
|
return list(up('<'+'I'*num_fields, full[ind:ind+4*num_fields]))
|
||||||
|
|
||||||
def find_types(full, num_fields):
|
def find_types(full, num_fields):
|
||||||
KNOWN = range(10) + [4, 4, 2, 4]
|
KNOWN = range(10) + [4, 4, 2, 4]
|
||||||
ind = full.index(''.join(pk('<I', i) for i in KNOWN))
|
KNOWN_OLD = range(10) + [4, 4, 0, 4]
|
||||||
|
try:
|
||||||
|
ind = full.index(''.join(pk('<I', i) for i in KNOWN))
|
||||||
|
except ValueError:
|
||||||
|
ind = full.index(''.join(pk('<I', i) for i in KNOWN_OLD))
|
||||||
return list(up('<'+'I'*num_fields, full[ind:ind+4*num_fields]))
|
return list(up('<'+'I'*num_fields, full[ind:ind+4*num_fields]))
|
||||||
|
|
||||||
def find_flags(full, num_fields):
|
def find_flags(full, num_fields):
|
||||||
KNOWN = '\x00' + ('\x01'*6) + '\x00\x01\x01\x00'
|
KNOWN = '\x00' + ('\x01'*6) + '\x00\x01\x01\x00'
|
||||||
|
if num_fields < 443 + len(KNOWN):
|
||||||
|
return [0] * num_fields
|
||||||
ind = full.index(KNOWN) - 443
|
ind = full.index(KNOWN) - 443
|
||||||
return list(up('<'+'B'*num_fields, full[ind:ind+num_fields]))
|
return list(up('<'+'B'*num_fields, full[ind:ind+num_fields]))
|
||||||
|
|
||||||
@@ -372,10 +379,10 @@ def flg_to_string(f):
|
|||||||
return FIELD_FLAGS[f] if f in FIELD_FLAGS else 'FieldFlag_Unknown%d' % f
|
return FIELD_FLAGS[f] if f in FIELD_FLAGS else 'FieldFlag_Unknown%d' % f
|
||||||
|
|
||||||
def main(argc, argv):
|
def main(argc, argv):
|
||||||
if argc != 2:
|
if argc != 2 and not (argc == 3 and argv[1] == '-f'):
|
||||||
print 'Usage: %s erpt_nso' % argv[0]
|
print 'Usage: %s [-f] erpt_nso' % argv[0]
|
||||||
return 1
|
return 1
|
||||||
f = open(argv[1], 'rb')
|
f = open(argv[-1], 'rb')
|
||||||
nxo = nxo64.load_nxo(f)
|
nxo = nxo64.load_nxo(f)
|
||||||
full = get_full(nxo)
|
full = get_full(nxo)
|
||||||
field_table = locate_fields(full)
|
field_table = locate_fields(full)
|
||||||
@@ -389,11 +396,13 @@ def main(argc, argv):
|
|||||||
mc = max(len(cat_to_string(c)) for c in cats)
|
mc = max(len(cat_to_string(c)) for c in cats)
|
||||||
mt = max(len(typ_to_string(t)) for t in types)
|
mt = max(len(typ_to_string(t)) for t in types)
|
||||||
ml = max(len(flg_to_string(f)) for f in flags)
|
ml = max(len(flg_to_string(f)) for f in flags)
|
||||||
|
if argc == 3:
|
||||||
|
mf, mc, mt, ml = (64, 48, 32, 32)
|
||||||
format_string = '- %%-%ds %%-%ds %%-%ds %%-%ds' % (mf+1, mc+1, mt+1, ml)
|
format_string = '- %%-%ds %%-%ds %%-%ds %%-%ds' % (mf+1, mc+1, mt+1, ml)
|
||||||
for i in xrange(NUM_FIELDS):
|
for i in xrange(NUM_FIELDS):
|
||||||
f, c, t, l = fields[i], cat_to_string(cats[i]), typ_to_string(types[i]), flg_to_string(flags[i])
|
f, c, t, l = fields[i], cat_to_string(cats[i]), typ_to_string(types[i]), flg_to_string(flags[i])
|
||||||
print format_string % (f+',', c+',', t+',', l)
|
print format_string % (f+',', c+',', t+',', l)
|
||||||
with open(argv[1]+'.hpp', 'w') as out:
|
with open(argv[-1]+'.hpp', 'w') as out:
|
||||||
out.write(HEADER)
|
out.write(HEADER)
|
||||||
out.write('#define AMS_ERPT_FOREACH_FIELD_TYPE(HANDLER) \\\n')
|
out.write('#define AMS_ERPT_FOREACH_FIELD_TYPE(HANDLER) \\\n')
|
||||||
for tp in sorted(list(set(types + FIELD_TYPES.keys()))):
|
for tp in sorted(list(set(types + FIELD_TYPES.keys()))):
|
||||||
|
|||||||
Reference in New Issue
Block a user