diff --git a/libraries/libstratosphere/include/stratosphere/ams/ams_environment.hpp b/libraries/libstratosphere/include/stratosphere/ams/ams_environment.hpp index 4fdd8f167..d610bce34 100644 --- a/libraries/libstratosphere/include/stratosphere/ams/ams_environment.hpp +++ b/libraries/libstratosphere/include/stratosphere/ams/ams_environment.hpp @@ -22,4 +22,8 @@ namespace ams { /* Will be called by libstratosphere on crash. */ void CrashHandler(ThreadExceptionDump *ctx); + /* API for boot sysmodule. */ + void InitializeForBoot(); + void SetInitialRebootPayload(const void *src, size_t src_size); + } diff --git a/libraries/libstratosphere/source/ams/ams_bpc.c b/libraries/libstratosphere/source/ams/ams_bpc.c index d04a69b72..8a3ddee4b 100644 --- a/libraries/libstratosphere/source/ams/ams_bpc.c +++ b/libraries/libstratosphere/source/ams/ams_bpc.c @@ -24,6 +24,11 @@ NX_GENERATE_SERVICE_GUARD(amsBpc); Result _amsBpcInitialize(void) { Handle h; Result rc = svcConnectToNamedPort(&h, "bpc:ams"); /* TODO: ams:bpc */ + while (R_VALUE(rc) == KERNELRESULT(NotFound)) { + svcSleepThread(50000000ul); + rc = svcConnectToNamedPort(&h, "bpc:ams"); + } + if (R_SUCCEEDED(rc)) serviceCreate(&g_amsBpcSrv, h); return rc; } @@ -44,3 +49,11 @@ Result amsBpcRebootToFatalError(void *ctx) { .buffers = { { ctx, 0x450 } }, ); } + + +Result amsBpcSetInitialPayload(const void *src, size_t src_size) { + return serviceDispatch(&g_amsBpcSrv, 65001, + .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias }, + .buffers = { { src, src_size } }, + ); +} diff --git a/libraries/libstratosphere/source/ams/ams_bpc.h b/libraries/libstratosphere/source/ams/ams_bpc.h index 05983fa6c..d8a3a9ed2 100644 --- a/libraries/libstratosphere/source/ams/ams_bpc.h +++ b/libraries/libstratosphere/source/ams/ams_bpc.h @@ -28,6 +28,7 @@ void amsBpcExit(void); Service *amsBpcGetServiceSession(void); Result amsBpcRebootToFatalError(void *ctx); +Result amsBpcSetInitialPayload(const void *src, size_t src_size); #ifdef __cplusplus } diff --git a/libraries/libstratosphere/source/ams/ams_environment.cpp b/libraries/libstratosphere/source/ams/ams_environment.cpp index 0af5dc5b1..f4bc04199 100644 --- a/libraries/libstratosphere/source/ams/ams_environment.cpp +++ b/libraries/libstratosphere/source/ams/ams_environment.cpp @@ -36,6 +36,14 @@ namespace ams { extern ncm::ProgramId CurrentProgramId; + void InitializeForBoot() { + R_ABORT_UNLESS(amsBpcInitialize()); + } + + void SetInitialRebootPayload(const void *src, size_t src_size) { + R_ABORT_UNLESS(amsBpcSetInitialPayload(src, src_size)); + } + void WEAK_SYMBOL ExceptionHandler(FatalErrorContext *ctx) { R_ABORT_UNLESS(amsBpcInitialize()); R_ABORT_UNLESS(amsBpcRebootToFatalError(ctx)); diff --git a/stratosphere/ams_mitm/source/amsmitm_initialization.cpp b/stratosphere/ams_mitm/source/amsmitm_initialization.cpp index 7fa891f6c..f1c2cc8fc 100644 --- a/stratosphere/ams_mitm/source/amsmitm_initialization.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_initialization.cpp @@ -58,9 +58,6 @@ namespace ams::mitm { os::ThreadType g_initialize_thread; alignas(os::ThreadStackAlignment) u8 g_initialize_thread_stack[InitializeThreadStackSize]; - os::Mutex g_prodinfo_init_lock(false); - bool g_initialized_prodinfo; - /* Console-unique data backup and protection. */ FsFile g_bis_key_file; @@ -175,17 +172,14 @@ namespace ams::mitm { } - void EnsureProdInfoInitializedAndKickOffInit() { - std::scoped_lock lk(g_prodinfo_init_lock); - if (!g_initialized_prodinfo) { - mitm::InitializeProdInfoManagement(); + void StartInitialize() { + /* Initialize prodinfo. */ + mitm::InitializeProdInfoManagement(); - R_ABORT_UNLESS(os::CreateThread(std::addressof(g_initialize_thread), InitializeThreadFunc, nullptr, g_initialize_thread_stack, sizeof(g_initialize_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(mitm, InitializeThread))); - os::SetThreadNamePointer(std::addressof(g_initialize_thread), AMS_GET_SYSTEM_THREAD_NAME(mitm, InitializeThread)); - os::StartThread(std::addressof(g_initialize_thread)); - - g_initialized_prodinfo = true; - } + /* Launch initialize thread. */ + R_ABORT_UNLESS(os::CreateThread(std::addressof(g_initialize_thread), InitializeThreadFunc, nullptr, g_initialize_thread_stack, sizeof(g_initialize_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(mitm, InitializeThread))); + os::SetThreadNamePointer(std::addressof(g_initialize_thread), AMS_GET_SYSTEM_THREAD_NAME(mitm, InitializeThread)); + os::StartThread(std::addressof(g_initialize_thread)); } bool IsInitialized() { diff --git a/stratosphere/ams_mitm/source/amsmitm_initialization.hpp b/stratosphere/ams_mitm/source/amsmitm_initialization.hpp index 3cec344d1..1c9d15f2d 100644 --- a/stratosphere/ams_mitm/source/amsmitm_initialization.hpp +++ b/stratosphere/ams_mitm/source/amsmitm_initialization.hpp @@ -18,7 +18,7 @@ namespace ams::mitm { - void EnsureProdInfoInitializedAndKickOffInit(); + void StartInitialize(); bool IsInitialized(); void WaitInitialized(); diff --git a/stratosphere/ams_mitm/source/amsmitm_module_management.cpp b/stratosphere/ams_mitm/source/amsmitm_module_management.cpp index f27a72e7b..e139c557a 100644 --- a/stratosphere/ams_mitm/source/amsmitm_module_management.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_module_management.cpp @@ -20,6 +20,7 @@ #include "fs_mitm/fsmitm_module.hpp" #include "set_mitm/setmitm_module.hpp" #include "bpc_mitm/bpcmitm_module.hpp" +#include "bpc_mitm/bpc_ams_module.hpp" #include "ns_mitm/nsmitm_module.hpp" #include "hid_mitm/hidmitm_module.hpp" @@ -31,6 +32,7 @@ namespace ams::mitm { ModuleId_FsMitm, ModuleId_SetMitm, ModuleId_BpcMitm, + ModuleId_BpcAms, ModuleId_NsMitm, ModuleId_HidMitm, @@ -62,6 +64,7 @@ namespace ams::mitm { GetModuleDefinition(), GetModuleDefinition(), GetModuleDefinition(), + GetModuleDefinition(), GetModuleDefinition(), GetModuleDefinition(), }; diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_module.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_module.cpp new file mode 100644 index 000000000..9eb29bab5 --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_module.cpp @@ -0,0 +1,46 @@ +/* + * 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 . + */ +#include "../amsmitm_initialization.hpp" +#include "bpc_ams_module.hpp" +#include "bpc_ams_service.hpp" + +namespace ams::mitm::bpc_ams { + + namespace { + + constexpr sm::ServiceName AtmosphereServiceName = sm::ServiceName::Encode("bpc:ams"); + constexpr size_t AtmosphereMaxSessions = 4; + + constexpr size_t MaxServers = 1; + constexpr size_t MaxSessions = AtmosphereMaxSessions; + using ServerOptions = sf::hipc::DefaultServerManagerOptions; + sf::hipc::ServerManager g_server_manager; + + } + + void MitmModule::ThreadFunction(void *arg) { + /* Create bpc:ams. */ + { + Handle bpcams_h; + R_ABORT_UNLESS(svcManageNamedPort(&bpcams_h, AtmosphereServiceName.name, AtmosphereMaxSessions)); + g_server_manager.RegisterServer(bpcams_h); + } + + /* Loop forever, servicing our services. */ + g_server_manager.LoopProcess(); + } + +} diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_module.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_module.hpp new file mode 100644 index 000000000..259d5b046 --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_module.hpp @@ -0,0 +1,24 @@ +/* + * 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 . + */ +#pragma once +#include +#include "../amsmitm_module.hpp" + +namespace ams::mitm::bpc_ams { + + DEFINE_MITM_MODULE_CLASS(0x8000, AMS_GET_SYSTEM_THREAD_PRIORITY(bpc, IpcServer)); + +} diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp index 4802ab5b7..5ca66b265 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp @@ -97,6 +97,21 @@ namespace ams::mitm::bpc { DoRebootToPayload(ctx); } + void SetInitialRebootPayload(const void *payload, size_t payload_size) { + /* Clear payload buffer */ + std::memset(g_reboot_payload, 0xCC, sizeof(g_reboot_payload)); + + /* Ensure valid. */ + AMS_ABORT_UNLESS(payload != nullptr && payload_size <= sizeof(g_reboot_payload)); + + /* Copy in payload. */ + std::memcpy(g_reboot_payload, payload, payload_size); + + /* NOTE: Preferred reboot type will be parsed from settings later on. */ + g_reboot_type = RebootType::ToPayload; + + } + Result LoadRebootPayload() { /* Clear payload buffer */ std::memset(g_reboot_payload, 0xCC, sizeof(g_reboot_payload)); diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.hpp index 58847bdf5..0a2ae78bb 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.hpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.hpp @@ -24,6 +24,7 @@ namespace ams::mitm::bpc { void ShutdownSystem(); /* Atmosphere power utilities. */ + void SetInitialRebootPayload(const void *payload, size_t payload_size); Result LoadRebootPayload(); Result DetectPreferredRebootFunctionality(); void RebootForFatalError(const ams::FatalErrorContext *ctx); diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp index b1a656da8..bd4f63313 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp @@ -13,13 +13,32 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include "../amsmitm_initialization.hpp" #include "bpc_ams_service.hpp" #include "bpc_ams_power_utils.hpp" namespace ams::mitm::bpc { + namespace { + + bool g_set_initial_payload = false; + + } + void AtmosphereService::RebootToFatalError(const ams::FatalErrorContext &ctx) { bpc::RebootForFatalError(&ctx); } + void AtmosphereService::SetInitialRebootPayload(const ams::sf::InBuffer &payload) { + if (!g_set_initial_payload) { + g_set_initial_payload = true; + + /* Set the initial reboot payload. */ + bpc::SetInitialRebootPayload(payload.GetPointer(), payload.GetSize()); + + /* Start the initialization process. */ + ::ams::mitm::StartInitialize(); + } + } + } diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp index 775f2b177..794235691 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp @@ -22,13 +22,16 @@ namespace ams::mitm::bpc { class AtmosphereService final : public sf::IServiceObject { private: enum class CommandId { - RebootToFatalError = 65000, + RebootToFatalError = 65000, + SetInitialRebootPayload = 65001, }; private: void RebootToFatalError(const ams::FatalErrorContext &ctx); + void SetInitialRebootPayload(const ams::sf::InBuffer &payload); public: DEFINE_SERVICE_DISPATCH_TABLE { MAKE_SERVICE_COMMAND_META(RebootToFatalError), + MAKE_SERVICE_COMMAND_META(SetInitialRebootPayload), }; }; diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp index a2ac113b0..f3d757bd4 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_module.cpp @@ -16,8 +16,6 @@ #include "../amsmitm_initialization.hpp" #include "bpcmitm_module.hpp" #include "bpc_mitm_service.hpp" -#include "bpc_ams_service.hpp" -#include "bpc_ams_power_utils.hpp" namespace ams::mitm::bpc { @@ -27,11 +25,8 @@ namespace ams::mitm::bpc { constexpr sm::ServiceName DeprecatedMitmServiceName = sm::ServiceName::Encode("bpc:c"); constexpr size_t MitmServiceMaxSessions = 13; - constexpr sm::ServiceName AtmosphereServiceName = sm::ServiceName::Encode("bpc:ams"); - constexpr size_t AtmosphereMaxSessions = 3; - - constexpr size_t MaxServers = 2; - constexpr size_t MaxSessions = MitmServiceMaxSessions + AtmosphereMaxSessions; + constexpr size_t MaxServers = 1; + constexpr size_t MaxSessions = MitmServiceMaxSessions; using ServerOptions = sf::hipc::DefaultServerManagerOptions; sf::hipc::ServerManager g_server_manager; @@ -41,13 +36,6 @@ namespace ams::mitm::bpc { /* Wait until initialization is complete. */ mitm::WaitInitialized(); - /* Create bpc:ams. */ - { - Handle bpcams_h; - R_ABORT_UNLESS(svcManageNamedPort(&bpcams_h, AtmosphereServiceName.name, AtmosphereMaxSessions)); - g_server_manager.RegisterServer(bpcams_h); - } - /* Create bpc mitm. */ const sm::ServiceName service_name = (hos::GetVersion() >= hos::Version_2_0_0) ? MitmServiceName : DeprecatedMitmServiceName; R_ABORT_UNLESS(g_server_manager.RegisterMitmServer(service_name)); diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp b/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp index f897fb064..380f12748 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp @@ -266,7 +266,6 @@ namespace ams::mitm::fs { if (bis_partition_id == FsBisPartitionId_BootPartition1Root) { out.SetValue(std::make_shared(new Boot0Storage(bis_storage, this->client_info)), target_object_id); } else if (bis_partition_id == FsBisPartitionId_CalibrationBinary) { - mitm::EnsureProdInfoInitializedAndKickOffInit(); out.SetValue(std::make_shared(new CalibrationBinaryStorage(bis_storage, this->client_info)), target_object_id); } else { if (can_write_bis || can_write_bis_for_choi_support) { diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp index d9229c080..5a3713262 100644 --- a/stratosphere/boot/source/boot_main.cpp +++ b/stratosphere/boot/source/boot_main.cpp @@ -111,6 +111,12 @@ int main(int argc, char **argv) os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(boot, Main)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(boot, Main)); + /* Perform atmosphere-specific init. */ + ams::InitializeForBoot(); + + /* Set the reboot payload with ams.mitm. */ + boot::SetInitialRebootPayload(); + /* Change voltage from 3.3v to 1.8v for select devices. */ boot::ChangeGpioVoltageTo1_8v(); diff --git a/stratosphere/boot/source/boot_power_utils.cpp b/stratosphere/boot/source/boot_power_utils.cpp index 357579d2b..9c140421b 100644 --- a/stratosphere/boot/source/boot_power_utils.cpp +++ b/stratosphere/boot/source/boot_power_utils.cpp @@ -67,6 +67,10 @@ namespace ams::boot { DoRebootToPayload(nullptr); } + void SetInitialRebootPayload() { + ::ams::SetInitialRebootPayload(fusee_primary_bin, fusee_primary_bin_size); + } + void RebootForFatalError(ams::FatalErrorContext *ctx) { DoRebootToPayload(ctx); } diff --git a/stratosphere/boot/source/boot_power_utils.hpp b/stratosphere/boot/source/boot_power_utils.hpp index dfe2d339c..db8b49473 100644 --- a/stratosphere/boot/source/boot_power_utils.hpp +++ b/stratosphere/boot/source/boot_power_utils.hpp @@ -23,6 +23,7 @@ namespace ams::boot { void ShutdownSystem(); /* Atmosphere power utilities. */ + void SetInitialRebootPayload(); void RebootForFatalError(ams::FatalErrorContext *ctx); }