mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-04 16:53:48 -04:00
stratosphere: only hold sm sessions open when needed
This commit is contained in:
parent
c3875796df
commit
b09adb6a34
16 changed files with 432 additions and 403 deletions
|
@ -13,7 +13,7 @@
|
|||
* 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 <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
@ -54,12 +54,12 @@ static void ClearLaunchedTitles() {
|
|||
|
||||
static void LaunchTitle(u64 title_id, FsStorageId storage_id, u32 launch_flags, u64 *pid) {
|
||||
u64 local_pid = 0;
|
||||
|
||||
|
||||
/* Don't launch a title twice during boot2. */
|
||||
if (HasLaunchedTitle(title_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Result rc = Registration::LaunchProcessByTidSid(Registration::TidSid{title_id, storage_id}, launch_flags, &local_pid);
|
||||
switch (rc) {
|
||||
case ResultKernelResourceExhausted:
|
||||
|
@ -81,7 +81,7 @@ static void LaunchTitle(u64 title_id, FsStorageId storage_id, u32 launch_flags,
|
|||
if (pid) {
|
||||
*pid = local_pid;
|
||||
}
|
||||
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
SetLaunchedTitle(title_id);
|
||||
}
|
||||
|
@ -92,22 +92,26 @@ static bool GetGpioPadLow(GpioPadName pad) {
|
|||
if (R_FAILED(gpioOpenSession(&button, pad))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Ensure we close even on early return. */
|
||||
ON_SCOPE_EXIT { gpioPadClose(&button); };
|
||||
|
||||
|
||||
/* Set direction input. */
|
||||
gpioPadSetDirection(&button, GpioDirection_Input);
|
||||
|
||||
|
||||
GpioValue val;
|
||||
return R_SUCCEEDED(gpioPadGetValue(&button, &val)) && val == GpioValue_Low;
|
||||
}
|
||||
|
||||
static bool IsMaintenanceMode() {
|
||||
/* Contact set:sys, retrieve boot!force_maintenance. */
|
||||
if (R_SUCCEEDED(setsysInitialize())) {
|
||||
Result rc;
|
||||
DoWithSmSession([&]() {
|
||||
rc = setsysInitialize();
|
||||
});
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
ON_SCOPE_EXIT { setsysExit(); };
|
||||
|
||||
|
||||
u8 force_maintenance = 1;
|
||||
setsysGetSettingsItemValue("boot", "force_maintenance", &force_maintenance, sizeof(force_maintenance));
|
||||
if (force_maintenance != 0) {
|
||||
|
@ -116,12 +120,15 @@ static bool IsMaintenanceMode() {
|
|||
}
|
||||
|
||||
/* Contact GPIO, read plus/minus buttons. */
|
||||
if (R_SUCCEEDED(gpioInitialize())) {
|
||||
DoWithSmSession([&]() {
|
||||
rc = gpioInitialize();
|
||||
});
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
ON_SCOPE_EXIT { gpioExit(); };
|
||||
|
||||
|
||||
return GetGpioPadLow(GpioPadName_ButtonVolUp) && GetGpioPadLow(GpioPadName_ButtonVolDown);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -168,42 +175,48 @@ static const std::tuple<u64, bool> g_additional_launch_programs[] = {
|
|||
};
|
||||
|
||||
static void MountSdCard() {
|
||||
Handle tmp_hnd = 0;
|
||||
static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"};
|
||||
for (unsigned int i = 0; i < sizeof(required_active_services) / sizeof(required_active_services[0]); i++) {
|
||||
if (R_FAILED(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i])))) {
|
||||
/* TODO: Panic */
|
||||
} else {
|
||||
svcCloseHandle(tmp_hnd);
|
||||
DoWithSmSession([&]() {
|
||||
Handle tmp_hnd = 0;
|
||||
static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"};
|
||||
for (unsigned int i = 0; i < sizeof(required_active_services) / sizeof(required_active_services[0]); i++) {
|
||||
if (R_FAILED(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i])))) {
|
||||
/* TODO: Panic */
|
||||
} else {
|
||||
svcCloseHandle(tmp_hnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
fsdevMountSdmc();
|
||||
}
|
||||
|
||||
static void WaitForMitm(const char *service) {
|
||||
bool mitm_installed = false;
|
||||
|
||||
Result rc = smManagerAmsInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
Result rc;
|
||||
DoWithSmSession([&]() {
|
||||
if (R_FAILED((rc = smManagerAmsInitialize()))) {
|
||||
std::abort();
|
||||
}
|
||||
});
|
||||
|
||||
while (R_FAILED((rc = smManagerAmsHasMitm(&mitm_installed, service))) || !mitm_installed) {
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
svcSleepThread(1000000ull);
|
||||
}
|
||||
|
||||
smManagerAmsExit();
|
||||
}
|
||||
|
||||
void EmbeddedBoot2::Main() {
|
||||
/* Wait until fs.mitm has installed itself. We want this to happen as early as possible. */
|
||||
WaitForMitm("fsp-srv");
|
||||
|
||||
|
||||
/* Clear titles. */
|
||||
ClearLaunchedTitles();
|
||||
|
||||
/* psc, bus, pcv is the minimal set of required titles to get SD card. */
|
||||
/* psc, bus, pcv is the minimal set of required titles to get SD card. */
|
||||
/* bus depends on pcie, and pcv depends on settings. */
|
||||
/* Launch psc. */
|
||||
LaunchTitle(TitleId_Psc, FsStorageId_NandSystem, 0, NULL);
|
||||
|
@ -215,16 +228,16 @@ void EmbeddedBoot2::Main() {
|
|||
LaunchTitle(TitleId_Settings, FsStorageId_NandSystem, 0, NULL);
|
||||
/* Launch pcv. */
|
||||
LaunchTitle(TitleId_Pcv, FsStorageId_NandSystem, 0, NULL);
|
||||
|
||||
|
||||
/* At this point, the SD card can be mounted. */
|
||||
MountSdCard();
|
||||
|
||||
|
||||
/* Find out whether we are maintenance mode. */
|
||||
bool maintenance = IsMaintenanceMode();
|
||||
if (maintenance) {
|
||||
BootModeService::SetMaintenanceBootForEmbeddedBoot2();
|
||||
}
|
||||
|
||||
|
||||
/* Wait for other atmosphere mitm modules to initialize. */
|
||||
WaitForMitm("set:sys");
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) {
|
||||
|
@ -232,16 +245,16 @@ void EmbeddedBoot2::Main() {
|
|||
} else {
|
||||
WaitForMitm("bpc:c");
|
||||
}
|
||||
|
||||
|
||||
/* Launch usb. */
|
||||
LaunchTitle(TitleId_Usb, FsStorageId_NandSystem, 0, NULL);
|
||||
|
||||
|
||||
/* Launch tma. */
|
||||
LaunchTitle(TitleId_Tma, FsStorageId_NandSystem, 0, NULL);
|
||||
|
||||
|
||||
/* Launch Atmosphere dmnt, using FsStorageId_None to force SD card boot. */
|
||||
LaunchTitle(TitleId_Dmnt, FsStorageId_None, 0, NULL);
|
||||
|
||||
|
||||
/* Launch default programs. */
|
||||
for (auto &launch_program : g_additional_launch_programs) {
|
||||
if (!maintenance || std::get<bool>(launch_program)) {
|
||||
|
@ -253,7 +266,7 @@ void EmbeddedBoot2::Main() {
|
|||
LaunchTitle(TitleId_Npns, FsStorageId_NandSystem, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allow for user-customizable programs. */
|
||||
DIR *titles_dir = opendir("sdmc:/atmosphere/titles");
|
||||
struct dirent *ent;
|
||||
|
@ -288,10 +301,10 @@ void EmbeddedBoot2::Main() {
|
|||
}
|
||||
closedir(titles_dir);
|
||||
}
|
||||
|
||||
|
||||
/* We no longer need the SD card. */
|
||||
fsdevUnmountAll();
|
||||
|
||||
|
||||
/* Free the memory used to track what boot2 launches. */
|
||||
ClearLaunchedTitles();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* 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 <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
@ -38,7 +38,7 @@ extern "C" {
|
|||
#define INNER_HEAP_SIZE 0x30000
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
@ -72,10 +72,10 @@ void RegisterPrivilegedProcessesWithFs() {
|
|||
/* Ensures that all privileged processes are registered with full FS permissions. */
|
||||
constexpr u64 PRIVILEGED_PROCESS_MIN = 0;
|
||||
constexpr u64 PRIVILEGED_PROCESS_MAX = 0x4F;
|
||||
|
||||
|
||||
const u32 PRIVILEGED_FAH[0x1C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
|
||||
const u32 PRIVILEGED_FAC[0x2C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
|
||||
u32 num_pids;
|
||||
u64 pids[PRIVILEGED_PROCESS_MAX+1];
|
||||
if (R_SUCCEEDED(svcGetProcessList(&num_pids, pids, sizeof(pids)/sizeof(pids[0])))) {
|
||||
|
@ -96,54 +96,52 @@ void RegisterPrivilegedProcessesWithFs() {
|
|||
|
||||
void __appInit(void) {
|
||||
Result rc;
|
||||
|
||||
|
||||
SetFirmwareVersionForLibnx();
|
||||
|
||||
rc = smInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = fsprInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
/* This works around a bug with process permissions on < 4.0.0. */
|
||||
RegisterPrivilegedProcessesWithFs();
|
||||
|
||||
rc = smManagerAmsInitialize();
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
smManagerAmsEndInitialDefers();
|
||||
} else {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = smManagerInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = lrInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = ldrPmInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = splInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = fsInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
DoWithSmSession([&]() {
|
||||
rc = fsprInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
/* This works around a bug with process permissions on < 4.0.0. */
|
||||
RegisterPrivilegedProcessesWithFs();
|
||||
|
||||
rc = smManagerAmsInitialize();
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
smManagerAmsEndInitialDefers();
|
||||
smManagerAmsExit();
|
||||
} else {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = smManagerInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = lrInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = ldrPmInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = splInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
rc = fsInitialize();
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
});
|
||||
|
||||
CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
|
||||
}
|
||||
|
||||
|
@ -156,14 +154,13 @@ void __appExit(void) {
|
|||
fsprExit();
|
||||
lrExit();
|
||||
fsExit();
|
||||
smExit();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
HosThread process_track_thread;
|
||||
consoleDebugInit(debugDevice_SVC);
|
||||
|
||||
|
||||
/* Initialize and spawn the Process Tracking thread. */
|
||||
Registration::InitializeSystemResources();
|
||||
if (R_FAILED(process_track_thread.Initialize(&ProcessTracking::MainLoop, NULL, 0x4000, 0x15))) {
|
||||
|
@ -172,19 +169,19 @@ int main(int argc, char **argv)
|
|||
if (R_FAILED(process_track_thread.Start())) {
|
||||
/* TODO: Panic. */
|
||||
}
|
||||
|
||||
|
||||
/* TODO: What's a good timeout value to use here? */
|
||||
auto server_manager = new WaitableManager(1);
|
||||
|
||||
|
||||
/* TODO: Create services. */
|
||||
server_manager->AddWaitable(new ServiceServer<ShellService>("pm:shell", 3));
|
||||
server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 2));
|
||||
server_manager->AddWaitable(new ServiceServer<BootModeService>("pm:bm", 6));
|
||||
server_manager->AddWaitable(new ServiceServer<InformationService>("pm:info", 1));
|
||||
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
server_manager->Process();
|
||||
|
||||
|
||||
/* Cleanup. */
|
||||
delete server_manager;
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue