Atmosphere/stratosphere/pm/source/impl/pm_process_manager.cpp

695 lines
29 KiB
C++
Raw Normal View History

2019-06-29 11:20:36 +02:00
/*
* Copyright (c) 2018-2020 Atmosphère-NX
2019-06-29 11:20:36 +02:00
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
2019-06-29 11:20:36 +02:00
#include "pm_process_manager.hpp"
#include "pm_resource_manager.hpp"
#include "pm_process_info.hpp"
namespace ams::pm::impl {
2019-06-29 11:20:36 +02:00
namespace {
/* Types. */
enum HookType {
HookType_ProgramId = (1 << 0),
2019-06-29 11:20:36 +02:00
HookType_Application = (1 << 1),
};
struct LaunchProcessArgs {
2019-10-15 07:49:06 +02:00
os::ProcessId *out_process_id;
ncm::ProgramLocation location;
2019-06-29 11:20:36 +02:00
u32 flags;
};
2020-04-14 07:19:44 +02:00
#define GET_FLAG_MASK(flag) (hos_version >= hos::Version_5_0_0 ? static_cast<u32>(LaunchFlags_##flag) : static_cast<u32>(LaunchFlagsDeprecated_##flag))
2019-06-29 11:20:36 +02:00
inline bool ShouldSignalOnExit(u32 launch_flags) {
2019-10-15 07:49:06 +02:00
const auto hos_version = hos::GetVersion();
2019-06-29 11:20:36 +02:00
return launch_flags & GET_FLAG_MASK(SignalOnExit);
}
inline bool ShouldSignalOnStart(u32 launch_flags) {
2019-10-15 07:49:06 +02:00
const auto hos_version = hos::GetVersion();
2020-04-14 07:19:44 +02:00
if (hos_version < hos::Version_2_0_0) {
2019-06-29 11:20:36 +02:00
return false;
}
return launch_flags & GET_FLAG_MASK(SignalOnStart);
}
inline bool ShouldSignalOnException(u32 launch_flags) {
2019-10-15 07:49:06 +02:00
const auto hos_version = hos::GetVersion();
2019-06-29 11:20:36 +02:00
return launch_flags & GET_FLAG_MASK(SignalOnException);
}
inline bool ShouldSignalOnDebugEvent(u32 launch_flags) {
2019-10-15 07:49:06 +02:00
const auto hos_version = hos::GetVersion();
2019-06-29 11:20:36 +02:00
return launch_flags & GET_FLAG_MASK(SignalOnDebugEvent);
}
inline bool ShouldStartSuspended(u32 launch_flags) {
2019-10-15 07:49:06 +02:00
const auto hos_version = hos::GetVersion();
2019-06-29 11:20:36 +02:00
return launch_flags & GET_FLAG_MASK(StartSuspended);
}
inline bool ShouldDisableAslr(u32 launch_flags) {
2019-10-15 07:49:06 +02:00
const auto hos_version = hos::GetVersion();
2019-06-29 11:20:36 +02:00
return launch_flags & GET_FLAG_MASK(DisableAslr);
}
#undef GET_FLAG_MASK
template<size_t MaxProcessInfos>
class ProcessInfoAllocator {
NON_COPYABLE(ProcessInfoAllocator);
NON_MOVEABLE(ProcessInfoAllocator);
static_assert(MaxProcessInfos >= 0x40, "MaxProcessInfos is too small.");
private:
TYPED_STORAGE(ProcessInfo) process_info_storages[MaxProcessInfos];
bool process_info_allocated[MaxProcessInfos];
os::Mutex lock;
private:
constexpr inline size_t GetProcessInfoIndex(ProcessInfo *process_info) const {
return process_info - GetPointer(this->process_info_storages[0]);
}
public:
2020-04-08 11:21:35 +02:00
constexpr ProcessInfoAllocator() : lock(false) {
std::memset(this->process_info_storages, 0, sizeof(this->process_info_storages));
std::memset(this->process_info_allocated, 0, sizeof(this->process_info_allocated));
}
void *AllocateProcessInfoStorage() {
std::scoped_lock lk(this->lock);
for (size_t i = 0; i < MaxProcessInfos; i++) {
if (!this->process_info_allocated[i]) {
this->process_info_allocated[i] = true;
2019-10-18 19:37:03 +02:00
std::memset(&this->process_info_storages[i], 0, sizeof(this->process_info_storages[i]));
return GetPointer(this->process_info_storages[i]);
}
}
return nullptr;
}
void FreeProcessInfo(ProcessInfo *process_info) {
std::scoped_lock lk(this->lock);
const size_t index = this->GetProcessInfoIndex(process_info);
2020-02-23 08:05:14 +01:00
AMS_ABORT_UNLESS(index < MaxProcessInfos);
AMS_ABORT_UNLESS(this->process_info_allocated[index]);
process_info->~ProcessInfo();
this->process_info_allocated[index] = false;
}
};
2019-06-29 11:20:36 +02:00
/* Process Tracking globals. */
void ProcessTrackingMain(void *arg);
2020-04-08 11:21:35 +02:00
os::ThreadType g_process_track_thread;
alignas(os::ThreadStackAlignment) u8 g_process_track_thread_stack[16_KB];
2019-06-29 11:20:36 +02:00
/* Process lists. */
ProcessList g_process_list;
ProcessList g_dead_process_list;
/* Process Info Allocation. */
/* Note: The kernel slabheap is size 0x50 -- we allow slightly larger to account for the dead process list. */
constexpr size_t MaxProcessCount = 0x60;
ProcessInfoAllocator<MaxProcessCount> g_process_info_allocator;
2019-06-29 11:20:36 +02:00
/* Global events. */
2020-04-08 11:21:35 +02:00
os::SystemEventType g_process_event;
os::SystemEventType g_hook_to_create_process_event;
os::SystemEventType g_hook_to_create_application_process_event;
os::SystemEventType g_boot_finished_event;
2019-06-29 11:20:36 +02:00
/* Process Launch synchronization globals. */
2020-04-08 11:21:35 +02:00
os::Mutex g_launch_program_lock(false);
os::Event g_process_launch_start_event(os::EventClearMode_AutoClear);
os::Event g_process_launch_finish_event(os::EventClearMode_AutoClear);
Result g_process_launch_result = ResultSuccess();
2019-06-29 11:20:36 +02:00
LaunchProcessArgs g_process_launch_args = {};
/* Hook globals. */
std::atomic<ncm::ProgramId> g_program_id_hook;
2019-06-29 11:20:36 +02:00
std::atomic<bool> g_application_hook;
/* Forward declarations. */
2020-04-08 11:21:35 +02:00
Result LaunchProcess(os::WaitableManagerType &waitable_manager, const LaunchProcessArgs &args);
void OnProcessSignaled(ProcessListAccessor &list, ProcessInfo *process_info);
2019-06-29 11:20:36 +02:00
/* Helpers. */
void ProcessTrackingMain(void *arg) {
/* This is the main loop of the process tracking thread. */
/* Setup waitable manager. */
2020-04-08 11:21:35 +02:00
os::WaitableManagerType process_waitable_manager;
os::WaitableHolderType start_event_holder;
os::InitializeWaitableManager(std::addressof(process_waitable_manager));
os::InitializeWaitableHolder(std::addressof(start_event_holder), g_process_launch_start_event.GetBase());
os::LinkWaitableHolder(std::addressof(process_waitable_manager), std::addressof(start_event_holder));
while (true) {
2020-04-08 11:21:35 +02:00
auto signaled_holder = os::WaitAny(std::addressof(process_waitable_manager));
if (signaled_holder == &start_event_holder) {
/* Launch start event signaled. */
/* TryWait will clear signaled, preventing duplicate notifications. */
if (g_process_launch_start_event.TryWait()) {
g_process_launch_result = LaunchProcess(process_waitable_manager, g_process_launch_args);
g_process_launch_finish_event.Signal();
}
} else {
/* Some process was signaled. */
ProcessListAccessor list(g_process_list);
2020-04-08 11:21:35 +02:00
OnProcessSignaled(list, reinterpret_cast<ProcessInfo *>(os::GetWaitableHolderUserData(signaled_holder)));
}
}
2019-06-29 11:20:36 +02:00
}
inline u32 GetLoaderCreateProcessFlags(u32 launch_flags) {
u32 ldr_flags = 0;
2020-04-14 07:19:44 +02:00
if (ShouldSignalOnException(launch_flags) || (hos::GetVersion() >= hos::Version_2_0_0 && !ShouldStartSuspended(launch_flags))) {
2019-06-29 11:20:36 +02:00
ldr_flags |= ldr::CreateProcessFlag_EnableDebug;
}
if (ShouldDisableAslr(launch_flags)) {
ldr_flags |= ldr::CreateProcessFlag_DisableAslr;
}
return ldr_flags;
}
2019-07-03 07:21:47 +02:00
bool HasApplicationProcess() {
ProcessListAccessor list(g_process_list);
for (auto &process : *list) {
if (process.IsApplication()) {
2019-07-03 07:21:47 +02:00
return true;
}
}
return false;
}
Result StartProcess(ProcessInfo *process_info, const ldr::ProgramInfo *program_info) {
2019-06-29 11:20:36 +02:00
R_TRY(svcStartProcess(process_info->GetHandle(), program_info->main_thread_priority, program_info->default_cpu_id, program_info->main_thread_stack_size));
process_info->SetState(svc::ProcessState_Running);
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
void CleanupProcessInfo(ProcessListAccessor &list, ProcessInfo *process_info) {
/* Remove the process from the list. */
list->Remove(process_info);
/* Delete the process. */
g_process_info_allocator.FreeProcessInfo(process_info);
}
2020-04-08 11:21:35 +02:00
Result LaunchProcess(os::WaitableManagerType &waitable_manager, const LaunchProcessArgs &args) {
2019-06-29 11:20:36 +02:00
/* Get Program Info. */
ldr::ProgramInfo program_info;
cfg::OverrideStatus override_status;
R_TRY(ldr::pm::AtmosphereGetProgramInfo(&program_info, &override_status, args.location));
2019-06-29 11:20:36 +02:00
const bool is_application = (program_info.flags & ldr::ProgramInfoFlag_ApplicationTypeMask) == ldr::ProgramInfoFlag_Application;
2020-04-14 07:19:44 +02:00
const bool allow_debug = (program_info.flags & ldr::ProgramInfoFlag_AllowDebug) || hos::GetVersion() < hos::Version_2_0_0;
2019-06-29 11:20:36 +02:00
/* Ensure we only try to run one application. */
R_UNLESS(!is_application || !HasApplicationProcess(), pm::ResultApplicationRunning());
2019-06-29 11:20:36 +02:00
/* Fix the program location to use the right program id. */
const ncm::ProgramLocation location = ncm::ProgramLocation::Make(program_info.program_id, static_cast<ncm::StorageId>(args.location.storage_id));
2019-06-29 11:20:36 +02:00
/* Pin the program with loader. */
ldr::PinId pin_id;
R_TRY(ldr::pm::AtmospherePinProgram(&pin_id, location, override_status));
2019-06-29 11:20:36 +02:00
/* Ensure resources are available. */
resource::WaitResourceAvailable(&program_info);
/* Actually create the process. */
Handle process_handle;
{
auto pin_guard = SCOPE_GUARD { ldr::pm::UnpinProgram(pin_id); };
R_TRY(ldr::pm::CreateProcess(&process_handle, pin_id, GetLoaderCreateProcessFlags(args.flags), resource::GetResourceLimitHandle(&program_info)));
pin_guard.Cancel();
}
2019-06-29 11:20:36 +02:00
/* Get the process id. */
os::ProcessId process_id = os::GetProcessId(process_handle);
2019-06-29 11:20:36 +02:00
/* Make new process info. */
void *process_info_storage = g_process_info_allocator.AllocateProcessInfoStorage();
2020-02-23 08:05:14 +01:00
AMS_ABORT_UNLESS(process_info_storage != nullptr);
ProcessInfo *process_info = new (process_info_storage) ProcessInfo(process_handle, process_id, pin_id, location, override_status);
/* Link new process info. */
{
ProcessListAccessor list(g_process_list);
list->push_back(*process_info);
process_info->LinkToWaitableManager(waitable_manager);
}
/* Prevent resource leakage if register fails. */
auto cleanup_guard = SCOPE_GUARD {
ProcessListAccessor list(g_process_list);
process_info->Cleanup();
CleanupProcessInfo(list, process_info);
};
2019-06-29 11:20:36 +02:00
const u8 *acid_sac = program_info.ac_buffer;
const u8 *aci_sac = acid_sac + program_info.acid_sac_size;
const u8 *acid_fac = aci_sac + program_info.aci_sac_size;
const u8 *aci_fah = acid_fac + program_info.acid_fac_size;
/* Register with FS and SM. */
2019-11-21 09:28:32 +01:00
R_TRY(fsprRegisterProgram(static_cast<u64>(process_id), static_cast<u64>(location.program_id), static_cast<NcmStorageId>(location.storage_id), aci_fah, program_info.aci_fah_size, acid_fac, program_info.acid_fac_size));
R_TRY(sm::manager::RegisterProcess(process_id, location.program_id, override_status, acid_sac, program_info.acid_sac_size, aci_sac, program_info.aci_sac_size));
2019-06-29 11:20:36 +02:00
/* Set flags. */
if (is_application) {
process_info->SetApplication();
}
if (ShouldSignalOnStart(args.flags) && allow_debug) {
2019-06-29 11:20:36 +02:00
process_info->SetSignalOnStart();
}
if (ShouldSignalOnExit(args.flags)) {
2019-06-29 11:20:36 +02:00
process_info->SetSignalOnExit();
}
if (ShouldSignalOnDebugEvent(args.flags) && allow_debug) {
2019-06-29 11:20:36 +02:00
process_info->SetSignalOnDebugEvent();
}
/* Process hooks/signaling. */
if (location.program_id == g_program_id_hook) {
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_hook_to_create_process_event));
Implement the NCM sysmodule (closes #91) * Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Updated AddOnContentLocationResolver and RegisteredLocationResolver to 9.0.0 * Finished updating lr to 9.0.0 * Updated NCM to 9.0.0 * Fix libstrat includes * Fixed application launching * title_id_2 -> owner_tid * Updated to new-ipc * Change to using pure virtuals * Title Id -> Program Id * Fixed compilation against master * std::scoped_lock<> -> std::scoped_lock * Adopted R_UNLESS and R_CONVERT * Prefix namespace to Results * Adopt std::numeric_limits * Fixed incorrect error handling in ReadFile * Adopted AMS_ABORT_UNLESS * Adopt util::GenerateUuid() * Syntax improvements * ncm_types: Address review * Address more review comments * Updated copyrights * Address more feedback * More feedback addressed * More changes * Move dispatch tables out of interface files * Addressed remaining comments * lr: move into libstratosphere * ncm: Fix logic inversion * lr: Add comments * lr: Remove whitespace * ncm: Start addressing feedback * ncm: Cleanup InitializeContentManager * lr: support client-side usage * lr_service -> lr_api * ncm: Begin refactoring content manager * ncm: More content manager improvements * ncm: Content manager mount improvements * ldr: use lr bindings * lr bindings usage: minor fixes * ncm/lr: Pointer placement * ncm: placeholder accessor cleanup * ncm: minor fixes * ncm: refactor rights cache * ncm: content meta database cleanup * ncm: move content meta database impl out of interface file * ncm: Use const ContentMetaKey & * ncm: fix other non-const ContentMetaKey references * ncm: content meta database cleanup * ncm: content storage fixes for 2.0.0 * ncm: add missing end of file newlines * ncm: implement ContentMetaReader * ncm: client-side api * ncm: trim trailing spaces * ncm: FS_MAX_PATH-1 -> fs::EntryNameLengthMax * ncm: Use PathString and Path * fs: implement accessor wrappers for ncm * fs: implement user fs wrappers * fs: add MountSdCard * ncm: move to content manager impl * ncm: fix up main * kvdb: use fs:: * fs: Add wrappers needed for ncm * ncm: use fs bindings, other refactoring * ncm: minor fixes * fsa: fix ReadFile without size output * fs: add substorage, rom path tool * ncm: fix dangling fsdev usage * fs: fix bug in Commit * fs: fixed incorrect mode check * fs: implement Mount(System)Data * ncm: don't delete hos * results: add R_SUCCEED_IF * ams-except-ncm: use R_SUCCEED_IF * ncm: added comments * ncm: fix api definitions * ncm: use R_SUCCEED_IF * pm: think of the savings * ncm: employ kernel strats * ncm: Nintendo has 5 MiB of heap. Give ourselves 4 to be safe, pending analysis * ncm: refactor IDs, split types header into many headers * ams.mitm: use fs bindings instead of stdio * fs: SystemData uses SystemDataId * ncm: improve meta-db accuracy * ncm: inline getlatestkey * fs: improve UnsupportedOperation results * fs: modernize mount utils * ams: misc fixes for merge-errors * fs: improve unsupportedoperation results * git subrepo pull emummc subrepo: subdir: "emummc" merged: "d12dd546" upstream: origin: "https://github.com/m4xw/emuMMC" branch: "develop" commit: "d12dd546" git-subrepo: version: "0.4.1" origin: "???" commit: "???" * util: add boundedmap * ncm: minor style fixes * ncm: don't unmount if mounting fails * lr: bug fixes * ncm: implement ncm.for-initialize + ncm.for-safemode * lr: ncm::ProgramId::Invalid -> ncm::InvalidProgramId * ncm: fix open directory mode on 1.0.0 * ncm: fix fs use, implement more of < 4.0.0 for-initialize/safemode * ncm: implement packagedcontent -> content for building metadb * ncm: fix save data flag management * ncm: address some review suggestions (thanks @leoetlino!) * updater: use fs bindings * fs: implement MountCode * fs: prefer make_unique to operator new * ncm: implement remaining ContentMetaDatabaseBuilder functionality Co-authored-by: Michael Scire <SciresM@gmail.com>
2020-03-08 09:06:23 +01:00
g_program_id_hook = ncm::InvalidProgramId;
2019-06-29 11:20:36 +02:00
} else if (is_application && g_application_hook) {
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_hook_to_create_application_process_event));
2019-06-29 11:20:36 +02:00
g_application_hook = false;
} else if (!ShouldStartSuspended(args.flags)) {
2019-06-29 11:20:36 +02:00
R_TRY(StartProcess(process_info, &program_info));
}
/* We succeeded, so we can cancel our cleanup. */
cleanup_guard.Cancel();
2019-06-29 11:20:36 +02:00
*args.out_process_id = process_id;
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
void OnProcessSignaled(ProcessListAccessor &list, ProcessInfo *process_info) {
/* Reset the process's signal. */
svcResetSignal(process_info->GetHandle());
2019-06-29 11:20:36 +02:00
/* Update the process's state. */
const svc::ProcessState old_state = process_info->GetState();
{
s64 tmp = 0;
R_ABORT_UNLESS(svc::GetProcessInfo(&tmp, process_info->GetHandle(), svc::ProcessInfoType_ProcessState));
process_info->SetState(static_cast<svc::ProcessState>(tmp));
}
const svc::ProcessState new_state = process_info->GetState();
2019-06-29 11:20:36 +02:00
/* If we're transitioning away from crashed, clear waiting attached. */
if (old_state == svc::ProcessState_Crashed && new_state != svc::ProcessState_Crashed) {
process_info->ClearExceptionWaitingAttach();
}
2019-06-29 11:20:36 +02:00
switch (new_state) {
case svc::ProcessState_Created:
case svc::ProcessState_CreatedAttached:
case svc::ProcessState_Terminating:
break;
case svc::ProcessState_Running:
if (process_info->ShouldSignalOnDebugEvent()) {
process_info->ClearSuspended();
process_info->SetSuspendedStateChanged();
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_process_event));
2020-04-14 07:19:44 +02:00
} else if (hos::GetVersion() >= hos::Version_2_0_0 && process_info->ShouldSignalOnStart()) {
process_info->SetStartedStateChanged();
process_info->ClearSignalOnStart();
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_process_event));
}
process_info->ClearUnhandledException();
break;
case svc::ProcessState_Crashed:
if (!process_info->HasUnhandledException()) {
process_info->SetExceptionOccurred();
os::SignalSystemEvent(std::addressof(g_process_event));
}
process_info->SetExceptionWaitingAttach();
break;
case svc::ProcessState_RunningAttached:
if (process_info->ShouldSignalOnDebugEvent()) {
process_info->ClearSuspended();
process_info->SetSuspendedStateChanged();
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_process_event));
}
process_info->ClearUnhandledException();
break;
case svc::ProcessState_Terminated:
/* Free process resources, unlink from waitable manager. */
process_info->Cleanup();
2020-04-14 07:19:44 +02:00
if (hos::GetVersion() < hos::Version_5_0_0 && process_info->ShouldSignalOnExit()) {
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_process_event));
} else {
/* Handle the case where we need to keep the process alive some time longer. */
2020-04-14 07:19:44 +02:00
if (hos::GetVersion() >= hos::Version_5_0_0 && process_info->ShouldSignalOnExit()) {
/* Remove from the living list. */
list->Remove(process_info);
/* Add the process to the list of dead processes. */
{
ProcessListAccessor dead_list(g_dead_process_list);
dead_list->push_back(*process_info);
}
/* Signal. */
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_process_event));
} else {
/* Actually delete process. */
CleanupProcessInfo(list, process_info);
}
}
break;
case svc::ProcessState_DebugBreak:
if (process_info->ShouldSignalOnDebugEvent()) {
process_info->SetSuspended();
process_info->SetSuspendedStateChanged();
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_process_event));
}
break;
2019-06-29 11:20:36 +02:00
}
}
}
/* Initialization. */
Result InitializeProcessManager() {
/* Create events. */
2020-04-08 11:21:35 +02:00
R_ABORT_UNLESS(os::CreateSystemEvent(std::addressof(g_process_event), os::EventClearMode_AutoClear, true));
R_ABORT_UNLESS(os::CreateSystemEvent(std::addressof(g_hook_to_create_process_event), os::EventClearMode_AutoClear, true));
R_ABORT_UNLESS(os::CreateSystemEvent(std::addressof(g_hook_to_create_application_process_event), os::EventClearMode_AutoClear, true));
R_ABORT_UNLESS(os::CreateSystemEvent(std::addressof(g_boot_finished_event), os::EventClearMode_AutoClear, true));
2019-06-29 11:20:36 +02:00
/* Initialize resource limits. */
R_TRY(resource::InitializeResourceManager());
2020-04-08 11:21:35 +02:00
/* Create thread. */
R_ABORT_UNLESS(os::CreateThread(std::addressof(g_process_track_thread), ProcessTrackingMain, nullptr, g_process_track_thread_stack, sizeof(g_process_track_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(pm, ProcessTrack)));
os::SetThreadNamePointer(std::addressof(g_process_track_thread), AMS_GET_SYSTEM_THREAD_NAME(pm, ProcessTrack));
2020-04-08 11:21:35 +02:00
2019-06-29 11:20:36 +02:00
/* Start thread. */
2020-04-08 11:21:35 +02:00
os::StartThread(std::addressof(g_process_track_thread));
2019-06-29 11:20:36 +02:00
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
/* Process Management. */
Result LaunchProgram(os::ProcessId *out_process_id, const ncm::ProgramLocation &loc, u32 flags) {
/* Ensure we only try to launch one program at a time. */
2020-02-23 08:11:28 +01:00
std::scoped_lock lk(g_launch_program_lock);
2019-06-29 11:20:36 +02:00
/* Set global arguments, signal, wait. */
g_process_launch_args = {
.out_process_id = out_process_id,
.location = loc,
.flags = flags,
};
g_process_launch_start_event.Signal();
2019-09-24 12:15:36 +02:00
g_process_launch_finish_event.Wait();
2019-06-29 11:20:36 +02:00
return g_process_launch_result;
}
2019-10-15 07:49:06 +02:00
Result StartProcess(os::ProcessId process_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(process_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
R_UNLESS(!process_info->HasStarted(), pm::ResultAlreadyStarted());
2019-06-29 11:20:36 +02:00
ldr::ProgramInfo program_info;
R_TRY(ldr::pm::GetProgramInfo(&program_info, process_info->GetProgramLocation()));
2019-06-29 11:20:36 +02:00
return StartProcess(process_info, &program_info);
}
2019-10-15 07:49:06 +02:00
Result TerminateProcess(os::ProcessId process_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(process_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
2019-06-29 11:20:36 +02:00
return svcTerminateProcess(process_info->GetHandle());
}
Result TerminateProgram(ncm::ProgramId program_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(program_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
2019-06-29 11:20:36 +02:00
return svcTerminateProcess(process_info->GetHandle());
}
Result GetProcessEventHandle(Handle *out) {
2020-04-08 11:21:35 +02:00
*out = os::GetReadableHandleOfSystemEvent(std::addressof(g_process_event));
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
Result GetProcessEventInfo(ProcessEventInfo *out) {
/* Check for event from current process. */
{
ProcessListAccessor list(g_process_list);
for (auto &process : *list) {
if (process.HasStarted() && process.HasStartedStateChanged()) {
process.ClearStartedStateChanged();
2019-06-29 11:20:36 +02:00
out->event = GetProcessEventValue(ProcessEvent::Started);
out->process_id = process.GetProcessId();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
if (process.HasSuspendedStateChanged()) {
process.ClearSuspendedStateChanged();
if (process.IsSuspended()) {
out->event = GetProcessEventValue(ProcessEvent::DebugBreak);
2019-06-29 11:20:36 +02:00
} else {
out->event = GetProcessEventValue(ProcessEvent::DebugRunning);
}
out->process_id = process.GetProcessId();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
if (process.HasExceptionOccurred()) {
process.ClearExceptionOccurred();
2019-06-29 11:20:36 +02:00
out->event = GetProcessEventValue(ProcessEvent::Exception);
out->process_id = process.GetProcessId();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
2020-04-14 07:19:44 +02:00
if (hos::GetVersion() < hos::Version_5_0_0 && process.ShouldSignalOnExit() && process.HasTerminated()) {
2019-06-29 11:20:36 +02:00
out->event = GetProcessEventValue(ProcessEvent::Exited);
out->process_id = process.GetProcessId();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
}
}
/* Check for event from exited process. */
2020-04-14 07:19:44 +02:00
if (hos::GetVersion() >= hos::Version_5_0_0) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor dead_list(g_dead_process_list);
if (!dead_list->empty()) {
auto &process_info = dead_list->front();
2019-06-29 11:20:36 +02:00
out->event = GetProcessEventValue(ProcessEvent::Exited);
out->process_id = process_info.GetProcessId();
CleanupProcessInfo(dead_list, &process_info);
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
}
2019-10-15 07:49:06 +02:00
out->process_id = os::ProcessId{};
2019-06-29 11:20:36 +02:00
out->event = GetProcessEventValue(ProcessEvent::None);
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
2019-10-15 07:49:06 +02:00
Result CleanupProcess(os::ProcessId process_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(process_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
R_UNLESS(process_info->HasTerminated(), pm::ResultNotTerminated());
2019-06-29 11:20:36 +02:00
CleanupProcessInfo(list, process_info);
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
2019-10-15 07:49:06 +02:00
Result ClearExceptionOccurred(os::ProcessId process_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(process_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
2019-06-29 11:20:36 +02:00
process_info->ClearExceptionOccurred();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
/* Information Getters. */
Result GetModuleIdList(u32 *out_count, u8 *out_buf, size_t max_out_count, u64 unused) {
/* This function was always stubbed... */
*out_count = 0;
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
2019-10-15 07:49:06 +02:00
Result GetExceptionProcessIdList(u32 *out_count, os::ProcessId *out_process_ids, size_t max_out_count) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
size_t count = 0;
for (auto &process : *list) {
if (process.HasExceptionWaitingAttach()) {
out_process_ids[count++] = process.GetProcessId();
2019-06-29 11:20:36 +02:00
}
}
*out_count = static_cast<u32>(count);
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
Result GetProcessId(os::ProcessId *out, ncm::ProgramId program_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(program_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
2019-06-29 11:20:36 +02:00
*out = process_info->GetProcessId();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
Result GetProgramId(ncm::ProgramId *out, os::ProcessId process_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(process_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
2019-06-29 11:20:36 +02:00
*out = process_info->GetProgramLocation().program_id;
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
2019-10-15 07:49:06 +02:00
Result GetApplicationProcessId(os::ProcessId *out_process_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
for (auto &process : *list) {
if (process.IsApplication()) {
*out_process_id = process.GetProcessId();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
}
return pm::ResultProcessNotFound();
2019-06-29 11:20:36 +02:00
}
Result AtmosphereGetProcessInfo(Handle *out_process_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
2019-06-29 11:20:36 +02:00
ProcessListAccessor list(g_process_list);
auto process_info = list->Find(process_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
2019-06-29 11:20:36 +02:00
*out_process_handle = process_info->GetHandle();
*out_loc = process_info->GetProgramLocation();
*out_status = process_info->GetOverrideStatus();
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
/* Hook API. */
Result HookToCreateProcess(Handle *out_hook, ncm::ProgramId program_id) {
2019-06-29 11:20:36 +02:00
*out_hook = INVALID_HANDLE;
{
Implement the NCM sysmodule (closes #91) * Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Updated AddOnContentLocationResolver and RegisteredLocationResolver to 9.0.0 * Finished updating lr to 9.0.0 * Updated NCM to 9.0.0 * Fix libstrat includes * Fixed application launching * title_id_2 -> owner_tid * Updated to new-ipc * Change to using pure virtuals * Title Id -> Program Id * Fixed compilation against master * std::scoped_lock<> -> std::scoped_lock * Adopted R_UNLESS and R_CONVERT * Prefix namespace to Results * Adopt std::numeric_limits * Fixed incorrect error handling in ReadFile * Adopted AMS_ABORT_UNLESS * Adopt util::GenerateUuid() * Syntax improvements * ncm_types: Address review * Address more review comments * Updated copyrights * Address more feedback * More feedback addressed * More changes * Move dispatch tables out of interface files * Addressed remaining comments * lr: move into libstratosphere * ncm: Fix logic inversion * lr: Add comments * lr: Remove whitespace * ncm: Start addressing feedback * ncm: Cleanup InitializeContentManager * lr: support client-side usage * lr_service -> lr_api * ncm: Begin refactoring content manager * ncm: More content manager improvements * ncm: Content manager mount improvements * ldr: use lr bindings * lr bindings usage: minor fixes * ncm/lr: Pointer placement * ncm: placeholder accessor cleanup * ncm: minor fixes * ncm: refactor rights cache * ncm: content meta database cleanup * ncm: move content meta database impl out of interface file * ncm: Use const ContentMetaKey & * ncm: fix other non-const ContentMetaKey references * ncm: content meta database cleanup * ncm: content storage fixes for 2.0.0 * ncm: add missing end of file newlines * ncm: implement ContentMetaReader * ncm: client-side api * ncm: trim trailing spaces * ncm: FS_MAX_PATH-1 -> fs::EntryNameLengthMax * ncm: Use PathString and Path * fs: implement accessor wrappers for ncm * fs: implement user fs wrappers * fs: add MountSdCard * ncm: move to content manager impl * ncm: fix up main * kvdb: use fs:: * fs: Add wrappers needed for ncm * ncm: use fs bindings, other refactoring * ncm: minor fixes * fsa: fix ReadFile without size output * fs: add substorage, rom path tool * ncm: fix dangling fsdev usage * fs: fix bug in Commit * fs: fixed incorrect mode check * fs: implement Mount(System)Data * ncm: don't delete hos * results: add R_SUCCEED_IF * ams-except-ncm: use R_SUCCEED_IF * ncm: added comments * ncm: fix api definitions * ncm: use R_SUCCEED_IF * pm: think of the savings * ncm: employ kernel strats * ncm: Nintendo has 5 MiB of heap. Give ourselves 4 to be safe, pending analysis * ncm: refactor IDs, split types header into many headers * ams.mitm: use fs bindings instead of stdio * fs: SystemData uses SystemDataId * ncm: improve meta-db accuracy * ncm: inline getlatestkey * fs: improve UnsupportedOperation results * fs: modernize mount utils * ams: misc fixes for merge-errors * fs: improve unsupportedoperation results * git subrepo pull emummc subrepo: subdir: "emummc" merged: "d12dd546" upstream: origin: "https://github.com/m4xw/emuMMC" branch: "develop" commit: "d12dd546" git-subrepo: version: "0.4.1" origin: "???" commit: "???" * util: add boundedmap * ncm: minor style fixes * ncm: don't unmount if mounting fails * lr: bug fixes * ncm: implement ncm.for-initialize + ncm.for-safemode * lr: ncm::ProgramId::Invalid -> ncm::InvalidProgramId * ncm: fix open directory mode on 1.0.0 * ncm: fix fs use, implement more of < 4.0.0 for-initialize/safemode * ncm: implement packagedcontent -> content for building metadb * ncm: fix save data flag management * ncm: address some review suggestions (thanks @leoetlino!) * updater: use fs bindings * fs: implement MountCode * fs: prefer make_unique to operator new * ncm: implement remaining ContentMetaDatabaseBuilder functionality Co-authored-by: Michael Scire <SciresM@gmail.com>
2020-03-08 09:06:23 +01:00
ncm::ProgramId old_value = ncm::InvalidProgramId;
R_UNLESS(g_program_id_hook.compare_exchange_strong(old_value, program_id), pm::ResultDebugHookInUse());
2019-06-29 11:20:36 +02:00
}
2020-04-08 11:21:35 +02:00
*out_hook = os::GetReadableHandleOfSystemEvent(std::addressof(g_hook_to_create_process_event));
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
Result HookToCreateApplicationProcess(Handle *out_hook) {
*out_hook = INVALID_HANDLE;
{
bool old_value = false;
R_UNLESS(g_application_hook.compare_exchange_strong(old_value, true), pm::ResultDebugHookInUse());
2019-06-29 11:20:36 +02:00
}
2020-04-08 11:21:35 +02:00
*out_hook = os::GetReadableHandleOfSystemEvent(std::addressof(g_hook_to_create_application_process_event));
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
Result ClearHook(u32 which) {
if (which & HookType_ProgramId) {
Implement the NCM sysmodule (closes #91) * Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Updated AddOnContentLocationResolver and RegisteredLocationResolver to 9.0.0 * Finished updating lr to 9.0.0 * Updated NCM to 9.0.0 * Fix libstrat includes * Fixed application launching * title_id_2 -> owner_tid * Updated to new-ipc * Change to using pure virtuals * Title Id -> Program Id * Fixed compilation against master * std::scoped_lock<> -> std::scoped_lock * Adopted R_UNLESS and R_CONVERT * Prefix namespace to Results * Adopt std::numeric_limits * Fixed incorrect error handling in ReadFile * Adopted AMS_ABORT_UNLESS * Adopt util::GenerateUuid() * Syntax improvements * ncm_types: Address review * Address more review comments * Updated copyrights * Address more feedback * More feedback addressed * More changes * Move dispatch tables out of interface files * Addressed remaining comments * lr: move into libstratosphere * ncm: Fix logic inversion * lr: Add comments * lr: Remove whitespace * ncm: Start addressing feedback * ncm: Cleanup InitializeContentManager * lr: support client-side usage * lr_service -> lr_api * ncm: Begin refactoring content manager * ncm: More content manager improvements * ncm: Content manager mount improvements * ldr: use lr bindings * lr bindings usage: minor fixes * ncm/lr: Pointer placement * ncm: placeholder accessor cleanup * ncm: minor fixes * ncm: refactor rights cache * ncm: content meta database cleanup * ncm: move content meta database impl out of interface file * ncm: Use const ContentMetaKey & * ncm: fix other non-const ContentMetaKey references * ncm: content meta database cleanup * ncm: content storage fixes for 2.0.0 * ncm: add missing end of file newlines * ncm: implement ContentMetaReader * ncm: client-side api * ncm: trim trailing spaces * ncm: FS_MAX_PATH-1 -> fs::EntryNameLengthMax * ncm: Use PathString and Path * fs: implement accessor wrappers for ncm * fs: implement user fs wrappers * fs: add MountSdCard * ncm: move to content manager impl * ncm: fix up main * kvdb: use fs:: * fs: Add wrappers needed for ncm * ncm: use fs bindings, other refactoring * ncm: minor fixes * fsa: fix ReadFile without size output * fs: add substorage, rom path tool * ncm: fix dangling fsdev usage * fs: fix bug in Commit * fs: fixed incorrect mode check * fs: implement Mount(System)Data * ncm: don't delete hos * results: add R_SUCCEED_IF * ams-except-ncm: use R_SUCCEED_IF * ncm: added comments * ncm: fix api definitions * ncm: use R_SUCCEED_IF * pm: think of the savings * ncm: employ kernel strats * ncm: Nintendo has 5 MiB of heap. Give ourselves 4 to be safe, pending analysis * ncm: refactor IDs, split types header into many headers * ams.mitm: use fs bindings instead of stdio * fs: SystemData uses SystemDataId * ncm: improve meta-db accuracy * ncm: inline getlatestkey * fs: improve UnsupportedOperation results * fs: modernize mount utils * ams: misc fixes for merge-errors * fs: improve unsupportedoperation results * git subrepo pull emummc subrepo: subdir: "emummc" merged: "d12dd546" upstream: origin: "https://github.com/m4xw/emuMMC" branch: "develop" commit: "d12dd546" git-subrepo: version: "0.4.1" origin: "???" commit: "???" * util: add boundedmap * ncm: minor style fixes * ncm: don't unmount if mounting fails * lr: bug fixes * ncm: implement ncm.for-initialize + ncm.for-safemode * lr: ncm::ProgramId::Invalid -> ncm::InvalidProgramId * ncm: fix open directory mode on 1.0.0 * ncm: fix fs use, implement more of < 4.0.0 for-initialize/safemode * ncm: implement packagedcontent -> content for building metadb * ncm: fix save data flag management * ncm: address some review suggestions (thanks @leoetlino!) * updater: use fs bindings * fs: implement MountCode * fs: prefer make_unique to operator new * ncm: implement remaining ContentMetaDatabaseBuilder functionality Co-authored-by: Michael Scire <SciresM@gmail.com>
2020-03-08 09:06:23 +01:00
g_program_id_hook = ncm::InvalidProgramId;
2019-06-29 11:20:36 +02:00
}
if (which & HookType_Application) {
g_application_hook = false;
}
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
/* Boot API. */
Result NotifyBootFinished() {
static bool g_has_boot_finished = false;
if (!g_has_boot_finished) {
2020-04-14 11:54:55 +02:00
/* Set program verification disabled, if we should. */
/* NOTE: Nintendo does not check the result of this. */
if (spl::IsDisabledProgramVerification()) {
if (hos::GetVersion() >= hos::Version_10_0_0) {
ldr::pm::SetEnabledProgramVerification(false);
} else {
fsprSetEnabledProgramVerification(false);
}
}
2019-10-19 06:06:40 +02:00
boot2::LaunchPreSdCardBootProgramsAndBoot2();
2019-06-29 11:20:36 +02:00
g_has_boot_finished = true;
2020-04-08 11:21:35 +02:00
os::SignalSystemEvent(std::addressof(g_boot_finished_event));
2019-06-29 11:20:36 +02:00
}
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
Result GetBootFinishedEventHandle(Handle *out) {
/* In 8.0.0, Nintendo added this command, which signals that the boot sysmodule has finished. */
/* Nintendo only signals it in safe mode FIRM, and this function aborts on normal FIRM. */
/* We will signal it always, but only allow this function to succeed on safe mode. */
2020-02-23 08:05:14 +01:00
AMS_ABORT_UNLESS(spl::IsRecoveryBoot());
2020-04-08 11:21:35 +02:00
*out = os::GetReadableHandleOfSystemEvent(std::addressof(g_boot_finished_event));
return ResultSuccess();
2019-06-29 11:20:36 +02:00
}
/* Resource Limit API. */
Result BoostSystemMemoryResourceLimit(u64 boost_size) {
return resource::BoostSystemMemoryResourceLimit(boost_size);
}
Result BoostApplicationThreadResourceLimit() {
return resource::BoostApplicationThreadResourceLimit();
2019-06-29 11:20:36 +02:00
}
Result AtmosphereGetCurrentLimitInfo(s64 *out_cur_val, s64 *out_lim_val, u32 group, u32 resource) {
return resource::GetResourceLimitValues(out_cur_val, out_lim_val, static_cast<ResourceLimitGroup>(group), static_cast<svc::LimitableResource>(resource));
2019-06-29 11:20:36 +02:00
}
}