From 985e97cf780f618c6c2c2074ec778de83b94aa63 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 20 May 2020 04:42:42 -0700 Subject: [PATCH] exo2: implement SmcGetEmummcConfig --- exosphere2/program/source/secmon_map.cpp | 4 +- .../program/source/smc/secmon_smc_handler.cpp | 4 +- .../program/source/smc/secmon_smc_info.cpp | 55 ++++++++++++++++++- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/exosphere2/program/source/secmon_map.cpp b/exosphere2/program/source/secmon_map.cpp index 3f6c5b4e0..92100ad2f 100644 --- a/exosphere2/program/source/secmon_map.cpp +++ b/exosphere2/program/source/secmon_map.cpp @@ -209,7 +209,7 @@ namespace ams::secmon { /* Hold the lock. */ lock_guard.Cancel(); - return true; + return MemoryRegionVirtualAtmosphereIramPage.GetAddress(); } void UnmapAtmosphereIramPage() { @@ -260,7 +260,7 @@ namespace ams::secmon { /* Hold the lock. */ lock_guard.Cancel(); - return true; + return MemoryRegionVirtualAtmosphereUserPage.GetAddress(); } void UnmapAtmosphereUserPage() { diff --git a/exosphere2/program/source/smc/secmon_smc_handler.cpp b/exosphere2/program/source/smc/secmon_smc_handler.cpp index f1cd4b37a..8abe3a71a 100644 --- a/exosphere2/program/source/smc/secmon_smc_handler.cpp +++ b/exosphere2/program/source/smc/secmon_smc_handler.cpp @@ -233,8 +233,8 @@ namespace ams::secmon::smc { constinit std::atomic g_logged = 0; - constexpr int LogMin = 0x200; - constexpr int LogMax = 0x400; + constexpr int LogMin = 0x4000; + constexpr int LogMax = 0x4200; constexpr size_t LogBufSize = 0x5000; diff --git a/exosphere2/program/source/smc/secmon_smc_info.cpp b/exosphere2/program/source/smc/secmon_smc_info.cpp index ae6f0ccc3..c94bd7d1d 100644 --- a/exosphere2/program/source/smc/secmon_smc_info.cpp +++ b/exosphere2/program/source/smc/secmon_smc_info.cpp @@ -16,6 +16,7 @@ #include #include "../secmon_error.hpp" #include "../secmon_misc.hpp" +#include "secmon_page_mapper.hpp" #include "secmon_smc_info.hpp" #include "secmon_smc_power_management.hpp" @@ -284,8 +285,58 @@ namespace ams::secmon::smc { /* This is an atmosphere extension smc. */ SmcResult SmcGetEmummcConfig(SmcArguments &args) { - /* TODO */ - return SmcResult::NotImplemented; + /* Decode arguments. */ + const auto mmc = static_cast(args.r[1]); + const uintptr_t user_address = args.r[2]; + const uintptr_t user_offset = user_address % 4_KB; + + /* Validate arguments. */ + /* NOTE: In the future, configuration for non-NAND storage may be implemented. */ + SMC_R_UNLESS(mmc == EmummcMmc_Nand, NotImplemented); + SMC_R_UNLESS(user_offset + 2 * sizeof(EmummcFilePath) <= 4_KB, InvalidArgument); + + /* Get the emummc config. */ + const auto &cfg = GetEmummcConfiguration(); + static_assert(sizeof(cfg.file_cfg) == sizeof(EmummcFilePath)); + static_assert(sizeof(cfg.emu_dir_path) == sizeof(EmummcFilePath)); + + /* Clear the output. */ + constexpr size_t InlineOutputSize = sizeof(args) - sizeof(args.r[0]); + u8 * const inline_output = static_cast(static_cast(std::addressof(args.r[1]))); + std::memset(inline_output, 0, InlineOutputSize); + + /* Copy out the configuration. */ + { + /* Map the user output page. */ + AtmosphereUserPageMapper mapper(user_address); + SMC_R_UNLESS(mapper.Map(), InvalidArgument); + + /* Copy the base configuration. */ + static_assert(sizeof(cfg.base_cfg) <= InlineOutputSize); + std::memcpy(inline_output, std::addressof(cfg.base_cfg), sizeof(cfg.base_cfg)); + + /* Copy out type-specific data. */ + switch (cfg.base_cfg.type) { + case EmummcType_None: + /* No additional configuration needs to be copied. */ + break; + case EmummcType_Partition: + /* Copy the partition config. */ + static_assert(sizeof(cfg.base_cfg) + sizeof(cfg.partition_cfg) <= InlineOutputSize); + std::memcpy(inline_output + sizeof(cfg.base_cfg), std::addressof(cfg.partition_cfg), sizeof(cfg.partition_cfg)); + break; + case EmummcType_File: + /* Copy the file config. */ + SMC_R_UNLESS(mapper.CopyToUser(user_address, std::addressof(cfg.file_cfg), sizeof(cfg.file_cfg)), InvalidArgument); + break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + + /* Copy the redirection directory path to the user page. */ + SMC_R_UNLESS(mapper.CopyToUser(user_address + sizeof(EmummcFilePath), std::addressof(cfg.emu_dir_path), sizeof(cfg.emu_dir_path)), InvalidArgument); + } + + return SmcResult::Success; } /* For exosphere's usage. */