pm: address review comments.

This commit is contained in:
Michael Scire 2019-07-02 22:21:47 -07:00 committed by SciresM
parent 08ad48fbf3
commit a9f5b7728b
10 changed files with 135 additions and 145 deletions

@ -1 +1 @@
Subproject commit d7d7cba3d35e5aa029ace71891e317e0d5412131
Subproject commit 45700a12e80404e3c49e2bc4893412489fc72040

View file

@ -137,11 +137,6 @@ namespace sts::boot2 {
void LaunchTitle(u64 *out_process_id, const ncm::TitleLocation &loc, u32 launch_flags) {
u64 process_id = 0;
/* Don't launch a title twice during boot2. */
if (pm::info::HasLaunchedTitle(loc.title_id)) {
return;
}
switch (pm::shell::LaunchTitle(&process_id, loc, launch_flags)) {
case ResultKernelResourceExhausted:
/* Out of resource! */
@ -186,11 +181,9 @@ namespace sts::boot2 {
bool IsMaintenanceMode() {
/* Contact set:sys, retrieve boot!force_maintenance. */
DoWithSmSession([&]() {
R_ASSERT(setsysInitialize());
});
{
ON_SCOPE_EXIT { setsysExit(); };
auto set_sys_holder = sm::ScopedServiceHolder<setsysInitialize, setsysExit>();
R_ASSERT(set_sys_holder.GetResult());
u8 force_maintenance = 1;
setsysGetSettingsItemValue("boot", "force_maintenance", &force_maintenance, sizeof(force_maintenance));
@ -200,50 +193,36 @@ namespace sts::boot2 {
}
/* Contact GPIO, read plus/minus buttons. */
DoWithSmSession([&]() {
R_ASSERT(gpioInitialize());
});
{
ON_SCOPE_EXIT { gpioExit(); };
auto gpio_holder = sm::ScopedServiceHolder<gpioInitialize, gpioExit>();
R_ASSERT(gpio_holder.GetResult());
return GetGpioPadLow(GpioPadName_ButtonVolUp) && GetGpioPadLow(GpioPadName_ButtonVolDown);
}
}
void WaitForMitm(const char *service) {
const auto name = sts::sm::ServiceName::Encode(service);
while (true) {
bool mitm_installed = false;
R_ASSERT(sts::sm::mitm::HasMitm(&mitm_installed, name));
if (mitm_installed) {
break;
}
svcSleepThread(1'000'000ull);
}
}
void LaunchFlaggedProgramsFromSdCard() {
/* Allow for user-customizable programs. */
DIR *titles_dir = opendir("sdmc:/atmosphere/titles");
struct dirent *ent;
if (titles_dir != NULL) {
while ((ent = readdir(titles_dir)) != NULL) {
if (titles_dir != nullptr) {
ON_SCOPE_EXIT { closedir(titles_dir); };
while ((ent = readdir(titles_dir)) != nullptr) {
if (strlen(ent->d_name) == 2 * sizeof(u64) && IsHexadecimal(ent->d_name)) {
ncm::TitleId title_id{strtoul(ent->d_name, NULL, 16)};
ncm::TitleId title_id{strtoul(ent->d_name, nullptr, 16)};
if (pm::info::HasLaunchedTitle(title_id)) {
return;
}
char title_path[FS_MAX_PATH];
std::snprintf(title_path, sizeof(title_path), "sdmc:/atmosphere/titles/%s/flags/boot2.flag", ent->d_name);
FILE *f_flag = fopen(title_path, "rb");
if (f_flag != NULL) {
if (f_flag != nullptr) {
fclose(f_flag);
LaunchTitle(nullptr, ncm::TitleLocation::Make(title_id, ncm::StorageId::None), 0);
}
}
}
closedir(titles_dir);
}
}
@ -252,7 +231,7 @@ namespace sts::boot2 {
/* Boot2 API. */
void LaunchBootPrograms() {
/* Wait until fs.mitm has installed itself. We want this to happen as early as possible. */
WaitForMitm("fsp-srv");
R_ASSERT(sm::mitm::WaitMitm(sm::ServiceName::Encode("fsp-srv")));
/* Launch programs required to mount the SD card. */
LaunchList(PreSdCardLaunchPrograms, NumPreSdCardLaunchPrograms);
@ -268,10 +247,11 @@ namespace sts::boot2 {
}
/* Wait for other atmosphere mitm modules to initialize. */
R_ASSERT(sm::mitm::WaitMitm(sm::ServiceName::Encode("set:sys")));
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) {
WaitForMitm("bpc");
R_ASSERT(sm::mitm::WaitMitm(sm::ServiceName::Encode("bpc")));
} else {
WaitForMitm("bpc:c");
R_ASSERT(sm::mitm::WaitMitm(sm::ServiceName::Encode("bpc:c")));
}
/* Launch Atmosphere dmnt, using FsStorageId_None to force SD card boot. */

View file

@ -86,63 +86,6 @@ namespace sts::pm::impl {
this->state = state;
}
void SetSignalOnExit() {
this->SetFlag(Flag_SignalOnExit);
}
void SetExceptionOccurred() {
this->SetFlag(Flag_ExceptionOccurred);
this->SetFlag(Flag_ExceptionWaitingAttach);
}
void ClearExceptionOccurred() {
this->ClearFlag(Flag_ExceptionOccurred);
}
void ClearExceptionWaitingAttach() {
this->ClearFlag(Flag_ExceptionWaitingAttach);
}
void SetSignalOnDebugEvent() {
this->SetFlag(Flag_SignalOnDebugEvent);
}
void SetSuspendedStateChanged() {
this->SetFlag(Flag_SuspendedStateChanged);
}
void ClearSuspendedStateChanged() {
this->ClearFlag(Flag_SuspendedStateChanged);
}
void SetSuspended() {
this->SetFlag(Flag_Suspended);
}
void ClearSuspended() {
this->ClearFlag(Flag_Suspended);
}
void SetApplication() {
this->SetFlag(Flag_Application);
}
void SetSignalOnStart() {
this->SetFlag(Flag_SignalOnStart);
}
void ClearSignalOnStart() {
this->ClearFlag(Flag_SignalOnStart);
}
void SetStartedStateChanged() {
this->SetFlag(Flag_StartedStateChanged);
}
void ClearStartedStateChanged() {
this->ClearFlag(Flag_StartedStateChanged);
}
bool HasStarted() const {
return this->state != ProcessState_Created && this->state != ProcessState_CreatedAttached;
}
@ -151,41 +94,60 @@ namespace sts::pm::impl {
return this->state == ProcessState_Exited;
}
bool ShouldSignalOnExit() const {
return this->HasFlag(Flag_SignalOnExit);
#define DEFINE_FLAG_SET(flag) \
void Set##flag() { \
this->SetFlag(Flag_##flag); \
}
bool HasExceptionOccurred() const {
return this->HasFlag(Flag_ExceptionOccurred);
#define DEFINE_FLAG_GET(get, flag) \
bool get##flag() const { \
return this->HasFlag(Flag_##flag); \
}
bool HasExceptionWaitingAttach() const {
return this->HasFlag(Flag_ExceptionWaitingAttach);
#define DEFINE_FLAG_CLEAR(flag) \
void Clear##flag() { \
this->ClearFlag(Flag_##flag); \
}
bool ShouldSignalOnDebugEvent() const {
return this->HasFlag(Flag_SignalOnDebugEvent);
DEFINE_FLAG_SET(SignalOnExit)
DEFINE_FLAG_GET(Should, SignalOnExit)
/* This needs a manual setter, because it sets two flags. */
void SetExceptionOccurred() {
this->SetFlag(Flag_ExceptionOccurred);
this->SetFlag(Flag_ExceptionWaitingAttach);
}
bool ShouldSignalOnStart() const {
return this->HasFlag(Flag_SignalOnStart);
}
DEFINE_FLAG_GET(Has, ExceptionOccurred)
DEFINE_FLAG_GET(Has, ExceptionWaitingAttach)
DEFINE_FLAG_CLEAR(ExceptionOccurred)
DEFINE_FLAG_CLEAR(ExceptionWaitingAttach)
bool HasSuspendedStateChanged() const {
return this->HasFlag(Flag_SuspendedStateChanged);
}
DEFINE_FLAG_SET(SignalOnDebugEvent)
DEFINE_FLAG_GET(Should, SignalOnDebugEvent)
bool IsSuspended() const {
return this->HasFlag(Flag_Suspended);
}
DEFINE_FLAG_SET(SuspendedStateChanged)
DEFINE_FLAG_GET(Has, SuspendedStateChanged)
DEFINE_FLAG_CLEAR(SuspendedStateChanged)
bool IsApplication() const {
return this->HasFlag(Flag_Application);
}
DEFINE_FLAG_SET(Suspended)
DEFINE_FLAG_GET(Is, Suspended)
DEFINE_FLAG_CLEAR(Suspended)
bool HasStartedStateChanged() const {
return this->HasFlag(Flag_StartedStateChanged);
}
DEFINE_FLAG_SET(Application)
DEFINE_FLAG_GET(Is, Application)
DEFINE_FLAG_SET(SignalOnStart)
DEFINE_FLAG_GET(Should, SignalOnStart)
DEFINE_FLAG_CLEAR(SignalOnStart)
DEFINE_FLAG_SET(StartedStateChanged)
DEFINE_FLAG_GET(Has, StartedStateChanged)
DEFINE_FLAG_CLEAR(StartedStateChanged)
#undef DEFINE_FLAG_SET
#undef DEFINE_FLAG_GET
#undef DEFINE_FLAG_CLEAR
};
@ -195,7 +157,7 @@ namespace sts::pm::impl {
private:
std::shared_ptr<ProcessInfo> process_info;
public:
ProcessInfoWaiter(std::shared_ptr<ProcessInfo> p) : process_info(p) { /* ... */ }
ProcessInfoWaiter(std::shared_ptr<ProcessInfo> p) : process_info(std::move(p)) { /* ... */ }
/* IWaitable */
Handle GetHandle() override {
@ -235,27 +197,27 @@ namespace sts::pm::impl {
}
void Remove(u64 process_id) {
for (size_t i = 0; i < this->processes.size(); i++) {
if (this->processes[i]->GetProcessId() == process_id) {
this->processes.erase(this->processes.begin() + i);
for (auto it = this->processes.begin(); it != this->processes.end(); it++) {
if ((*it)->GetProcessId() == process_id) {
this->processes.erase(it);
break;
}
}
}
std::shared_ptr<ProcessInfo> Find(u64 process_id) {
for (size_t i = 0; i < this->processes.size(); i++) {
if (this->processes[i]->GetProcessId() == process_id) {
return this->processes[i];
for (auto it = this->processes.begin(); it != this->processes.end(); it++) {
if ((*it)->GetProcessId() == process_id) {
return *it;
}
}
return nullptr;
}
std::shared_ptr<ProcessInfo> Find(ncm::TitleId title_id) {
for (size_t i = 0; i < this->processes.size(); i++) {
if (this->processes[i]->GetTitleLocation().title_id == title_id) {
return this->processes[i];
for (auto it = this->processes.begin(); it != this->processes.end(); it++) {
if ((*it)->GetTitleLocation().title_id == title_id) {
return *it;
}
}
return nullptr;

View file

@ -141,20 +141,20 @@ namespace sts::pm::impl {
/* Process Tracking globals. */
HosThread g_process_track_thread;
SessionManagerBase *g_process_waitable_manager = nullptr;
auto g_process_waitable_manager = WaitableManager(1);
/* Process lists. */
ProcessList g_process_list;
ProcessList g_dead_process_list;
/* Global events. */
IEvent *g_process_event = nullptr;
IEvent *g_hook_to_create_process_event = nullptr;
IEvent *g_hook_to_create_application_process_event = nullptr;
IEvent *g_boot_finished_event = nullptr;
IEvent *g_process_event = CreateWriteOnlySystemEvent();
IEvent *g_hook_to_create_process_event = CreateWriteOnlySystemEvent();
IEvent *g_hook_to_create_application_process_event = CreateWriteOnlySystemEvent();
IEvent *g_boot_finished_event = CreateWriteOnlySystemEvent();
/* Process Launch synchronization globals. */
IEvent *g_process_launch_start_event = nullptr;
IEvent *g_process_launch_start_event = CreateWriteOnlySystemEvent();
HosSignal g_process_launch_finish_signal;
Result g_process_launch_result = ResultSuccess;
LaunchProcessArgs g_process_launch_args = {};
@ -167,13 +167,9 @@ namespace sts::pm::impl {
void ProcessTrackingMain(void *arg) {
/* This is the main loop of the process tracking thread. */
/* Create waitable manager. */
static auto s_process_waiter = WaitableManager(1);
g_process_waitable_manager = &s_process_waiter;
/* Service processes. */
g_process_waitable_manager->AddWaitable(g_process_launch_start_event);
g_process_waitable_manager->Process();
g_process_waitable_manager.AddWaitable(g_process_launch_start_event);
g_process_waitable_manager.Process();
}
inline u32 GetLoaderCreateProcessFlags(u32 launch_flags) {
@ -189,6 +185,18 @@ namespace sts::pm::impl {
return ldr_flags;
}
bool HasApplicationProcess() {
ProcessListAccessor list(g_process_list);
for (size_t i = 0; i < list->GetSize(); i++) {
if (list[i]->IsApplication()) {
return true;
}
}
return false;
}
Result StartProcess(std::shared_ptr<ProcessInfo> process_info, const ldr::ProgramInfo *program_info) {
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(ProcessState_Running);
@ -203,7 +211,7 @@ namespace sts::pm::impl {
const bool allow_debug = (program_info.flags & ldr::ProgramInfoFlag_AllowDebug) || GetRuntimeFirmwareVersion() < FirmwareVersion_200;
/* Ensure we only try to run one application. */
if (is_application) {
if (is_application && HasApplicationProcess()) {
return ResultPmApplicationRunning;
}
@ -268,7 +276,7 @@ namespace sts::pm::impl {
{
ProcessListAccessor list(g_process_list);
list->Add(process_info);
g_process_waitable_manager->AddWaitable(new ProcessInfoWaiter(process_info));
g_process_waitable_manager.AddWaitable(new ProcessInfoWaiter(process_info));
}
*args->out_process_id = process_id;
@ -395,7 +403,7 @@ namespace sts::pm::impl {
Result LaunchTitle(u64 *out_process_id, const ncm::TitleLocation &loc, u32 flags) {
/* Ensure we only try to launch one title at a time. */
static HosMutex s_lock;
std::scoped_lock<HosMutex> lk(s_lock);
std::scoped_lock lk(s_lock);
/* Set global arguments, signal, wait. */
g_process_launch_args = {

View file

@ -72,9 +72,9 @@ void __libnx_initheap(void) {
namespace {
static constexpr u32 PrivilegedFileAccessHeader[0x1C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
static constexpr u32 PrivilegedFileAccessControl[0x2C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
static constexpr size_t ProcessCountMax = 0x40;
constexpr u32 PrivilegedFileAccessHeader[0x1C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
constexpr u32 PrivilegedFileAccessControl[0x2C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
constexpr size_t ProcessCountMax = 0x40;
/* This works around a bug fixed by FS in 4.0.0. */
/* Not doing so will cause KIPs with higher process IDs than 7 to be unable to use filesystem services. */

View file

@ -459,6 +459,17 @@ namespace sts::sm::impl {
return ResultSuccess;
}
Result WaitService(ServiceName service) {
bool has_service = false;
R_TRY(impl::HasService(&has_service, service));
/* Wait until we have the service. */
if (!has_service) {
return ResultServiceFrameworkRequestDeferredByUser;
}
return ResultSuccess;
}
Result GetServiceHandle(Handle *out, u64 pid, ServiceName service) {
/* Validate service name. */
R_TRY(ValidateServiceName(service));
@ -564,6 +575,17 @@ namespace sts::sm::impl {
return ResultSuccess;
}
Result WaitMitm(ServiceName service) {
bool has_mitm = false;
R_TRY(impl::HasMitm(&has_mitm, service));
/* Wait until we have the mitm. */
if (!has_mitm) {
return ResultServiceFrameworkRequestDeferredByUser;
}
return ResultSuccess;
}
Result InstallMitm(Handle *out, Handle *out_query, u64 pid, ServiceName service) {
/* Validate service name. */
R_TRY(ValidateServiceName(service));

View file

@ -26,6 +26,7 @@ namespace sts::sm::impl {
/* Service management. */
Result HasService(bool *out, ServiceName service);
Result WaitService(ServiceName service);
Result GetServiceHandle(Handle *out, u64 pid, ServiceName service);
Result RegisterService(Handle *out, u64 pid, ServiceName service, size_t max_sessions, bool is_light);
Result RegisterServiceForSelf(Handle *out, ServiceName service, size_t max_sessions);
@ -33,6 +34,7 @@ namespace sts::sm::impl {
/* Mitm extensions. */
Result HasMitm(bool *out, ServiceName service);
Result WaitMitm(ServiceName service);
Result InstallMitm(Handle *out, Handle *out_query, u64 pid, ServiceName service);
Result UninstallMitm(u64 pid, ServiceName service);
Result AcknowledgeMitmSession(u64 *out_pid, Handle *out_hnd, u64 pid, ServiceName service);

View file

@ -75,9 +75,19 @@ namespace sts::sm {
return impl::HasMitm(out.GetPointer(), service);
}
Result UserService::AtmosphereWaitMitm(ServiceName service) {
R_TRY(this->EnsureInitialized());
return impl::WaitMitm(service);
}
Result UserService::AtmosphereHasService(Out<bool> out, ServiceName service) {
R_TRY(this->EnsureInitialized());
return impl::HasService(out.GetPointer(), service);
}
Result UserService::AtmosphereWaitService(ServiceName service) {
R_TRY(this->EnsureInitialized());
return impl::WaitService(service);
}
}

View file

@ -36,8 +36,10 @@ namespace sts::sm {
AtmosphereAssociatePidTidForMitm = 65002,
AtmosphereAcknowledgeMitmSession = 65003,
AtmosphereHasMitm = 65004,
AtmosphereWaitMitm = 65005,
AtmosphereHasService = 65100,
AtmosphereWaitService = 65101,
};
private:
u64 pid = InvalidProcessId;
@ -57,8 +59,10 @@ namespace sts::sm {
virtual Result AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid);
virtual Result AtmosphereAcknowledgeMitmSession(Out<u64> client_pid, Out<MovedHandle> fwd_h, ServiceName service);
virtual Result AtmosphereHasMitm(Out<bool> out, ServiceName service);
virtual Result AtmosphereWaitMitm(ServiceName service);
virtual Result AtmosphereHasService(Out<bool> out, ServiceName service);
virtual Result AtmosphereWaitService(ServiceName service);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(UserService, Initialize),
@ -71,8 +75,10 @@ namespace sts::sm {
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereAssociatePidTidForMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereAcknowledgeMitmSession),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereHasMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereWaitMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereHasService),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereWaitService),
};
};