From fa384fd920e7cdd2946517915e803d03f9e02536 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 25 Oct 2023 04:45:41 -0700 Subject: [PATCH] erpt: begin SubmitFsinfo (SubmitMmcDetailInfo) --- libraries/config/templates/stratosphere.mk | 2 +- .../include/stratosphere/fs.hpp | 1 + .../include/stratosphere/fs/fs_mmc.hpp | 57 ++++++ .../fssrv/sf/fssrv_sf_i_device_operator.hpp | 10 +- .../source/erpt/srv/erpt_srv_fs_info.hpp | 23 +++ .../erpt/srv/erpt_srv_fs_info.os.horizon.cpp | 183 ++++++++++++++++++ .../source/erpt/srv/erpt_srv_reporter.cpp | 10 +- .../libstratosphere/source/fs/fs_mmc.cpp | 89 +++++++++ .../fs/impl/fs_remote_device_operator.hpp | 16 ++ 9 files changed, 385 insertions(+), 6 deletions(-) create mode 100644 libraries/libstratosphere/include/stratosphere/fs/fs_mmc.hpp create mode 100644 libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.hpp create mode 100644 libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp create mode 100644 libraries/libstratosphere/source/fs/fs_mmc.cpp diff --git a/libraries/config/templates/stratosphere.mk b/libraries/config/templates/stratosphere.mk index d0bbf3f85..06fb362c9 100644 --- a/libraries/config/templates/stratosphere.mk +++ b/libraries/config/templates/stratosphere.mk @@ -66,7 +66,7 @@ endif ifeq ($(ATMOSPHERE_BOARD),nx-hac-001) -export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map) +export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now else ifeq ($(ATMOSPHERE_OS_NAME),macos) export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-map,$(notdir $@.map) else diff --git a/libraries/libstratosphere/include/stratosphere/fs.hpp b/libraries/libstratosphere/include/stratosphere/fs.hpp index 13b7603d1..5e3da8c2c 100644 --- a/libraries/libstratosphere/include/stratosphere/fs.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs.hpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_mmc.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_mmc.hpp new file mode 100644 index 000000000..b954378be --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_mmc.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 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 + +namespace ams::fs { + + constexpr inline size_t MmcCidSize = 0x10; + + constexpr inline size_t MmcExtendedCsdSize = 0x200; + + constexpr inline int MmcExtendedCsdOffsetReEolInfo = 267; + constexpr inline int MmcExtendedCsdOffsetDeviceLifeTimeEstTypA = 268; + constexpr inline int MmcExtendedCsdOffsetDeviceLifeTimeEstTypB = 269; + + enum MmcSpeedMode { + MmcSpeedMode_Identification = 0, + MmcSpeedMode_LegacySpeed = 1, + MmcSpeedMode_HighSpeed = 2, + MmcSpeedMode_Hs200 = 3, + MmcSpeedMode_Hs400 = 4, + MmcSpeedMode_Unknown = 5, + }; + + enum class MmcPartition { + UserData = 0, + BootPartition1 = 1, + BootPartition2 = 2, + }; + + Result GetMmcCid(void *dst, size_t size); + + inline void ClearMmcCidSerialNumber(u8 *cid) { + /* Clear the serial number from the cid. */ + std::memset(cid + 1, 0, 4); + } + + Result GetMmcSpeedMode(MmcSpeedMode *out); + + Result GetMmcPatrolCount(u32 *out); + + Result GetMmcExtendedCsd(void *dst, size_t size); + +} diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_device_operator.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_device_operator.hpp index 7334ff861..e81b31cfb 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_device_operator.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_device_operator.hpp @@ -20,8 +20,12 @@ /* TODO */ /* ACCURATE_TO_VERSION: 13.4.0.0 */ #define AMS_FSSRV_I_DEVICE_OPERATOR_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, IsSdCardInserted, (ams::sf::Out out), (out)) \ - AMS_SF_METHOD_INFO(C, H, 200, Result, IsGameCardInserted, (ams::sf::Out out), (out)) \ - AMS_SF_METHOD_INFO(C, H, 202, Result, GetGameCardHandle, (ams::sf::Out out), (out)) + AMS_SF_METHOD_INFO(C, H, 0, Result, IsSdCardInserted, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 100, Result, GetMmcCid, (ams::sf::OutBuffer out, s64 size), (out, size)) \ + AMS_SF_METHOD_INFO(C, H, 101, Result, GetMmcSpeedMode, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 112, Result, GetMmcPatrolCount, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 114, Result, GetMmcExtendedCsd, (ams::sf::OutBuffer out, s64 size), (out, size)) \ + AMS_SF_METHOD_INFO(C, H, 200, Result, IsGameCardInserted, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 202, Result, GetGameCardHandle, (ams::sf::Out out), (out)) AMS_SF_DEFINE_INTERFACE(ams::fssrv::sf, IDeviceOperator, AMS_FSSRV_I_DEVICE_OPERATOR_INTERFACE_INFO, 0x1484E21C) diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.hpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.hpp new file mode 100644 index 000000000..5d9d7ad17 --- /dev/null +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 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 + +namespace ams::erpt::srv { + + Result SubmitFsInfo(); + +} diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp new file mode 100644 index 000000000..3c8957104 --- /dev/null +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 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 +#include "erpt_srv_fs_info.hpp" +#include "erpt_srv_context_record.hpp" +#include "erpt_srv_context.hpp" + +namespace ams::erpt::srv { + + namespace { + + Result SubmitMmcDetailInfo() { + /* Submit the mmc cid. */ + { + u8 mmc_cid[fs::MmcCidSize] = {}; + if (R_SUCCEEDED(fs::GetMmcCid(mmc_cid, sizeof(mmc_cid)))) { + /* Clear the serial number from the cid. */ + fs::ClearMmcCidSerialNumber(mmc_cid); + + /* Create a record. */ + auto record = std::make_unique(CategoryId_NANDTypeInfo, sizeof(mmc_cid)); + R_UNLESS(record != nullptr, erpt::ResultOutOfMemory()); + + /* Add the cid. */ + R_ABORT_UNLESS(record->Add(FieldId_NANDType, mmc_cid, sizeof(mmc_cid))); + + /* Submit the record. */ + R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record))); + } + } + + /* Submit the mmc speed mode. */ + { + /* Create a record. */ + auto record = std::make_unique(CategoryId_NANDSpeedModeInfo, 0x20); + R_UNLESS(record != nullptr, erpt::ResultOutOfMemory()); + + /* Get the speed mode. */ + fs::MmcSpeedMode speed_mode{}; + const auto res = fs::GetMmcSpeedMode(std::addressof(speed_mode)); + if (R_SUCCEEDED(res)) { + const char *speed_mode_name = "None"; + switch (speed_mode) { + case fs::MmcSpeedMode_Identification: + speed_mode_name = "Identification"; + break; + case fs::MmcSpeedMode_LegacySpeed: + speed_mode_name = "LegacySpeed"; + break; + case fs::MmcSpeedMode_HighSpeed: + speed_mode_name = "HighSpeed"; + break; + case fs::MmcSpeedMode_Hs200: + speed_mode_name = "Hs200"; + break; + case fs::MmcSpeedMode_Hs400: + speed_mode_name = "Hs400"; + break; + case fs::MmcSpeedMode_Unknown: + speed_mode_name = "Unknown"; + break; + default: + speed_mode_name = "UnDefined"; + break; + } + + R_ABORT_UNLESS(record->Add(FieldId_NANDSpeedMode, speed_mode_name, std::strlen(speed_mode_name))); + } else { + /* Getting speed mode failed, so add the result. */ + char res_str[0x20]; + util::SNPrintf(res_str, sizeof(res_str), "0x%08X", res.GetValue()); + R_ABORT_UNLESS(record->Add(FieldId_NANDSpeedMode, res_str, std::strlen(res_str))); + } + + /* Submit the record. */ + R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record))); + } + + /* Submit the mmc extended csd. */ + { + u8 mmc_csd[fs::MmcExtendedCsdSize] = {}; + if (R_SUCCEEDED(fs::GetMmcExtendedCsd(mmc_csd, sizeof(mmc_csd)))) { + /* Create a record. */ + auto record = std::make_unique(CategoryId_NANDExtendedCsd, 0); + R_UNLESS(record != nullptr, erpt::ResultOutOfMemory()); + + /* Add fields from the csd. */ + R_ABORT_UNLESS(record->Add(FieldId_NANDPreEolInfo, static_cast(mmc_csd[fs::MmcExtendedCsdOffsetReEolInfo]))); + R_ABORT_UNLESS(record->Add(FieldId_NANDDeviceLifeTimeEstTypA, static_cast(mmc_csd[fs::MmcExtendedCsdOffsetDeviceLifeTimeEstTypA]))); + R_ABORT_UNLESS(record->Add(FieldId_NANDDeviceLifeTimeEstTypB, static_cast(mmc_csd[fs::MmcExtendedCsdOffsetDeviceLifeTimeEstTypB]))); + + /* Submit the record. */ + R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record))); + } + } + + /* Submit the mmc patrol count. */ + { + u32 count = 0; + if (R_SUCCEEDED(fs::GetMmcPatrolCount(std::addressof(count)))) { + /* Create a record. */ + auto record = std::make_unique(CategoryId_NANDPatrolInfo, 0); + R_UNLESS(record != nullptr, erpt::ResultOutOfMemory()); + + /* Add the count. */ + R_ABORT_UNLESS(record->Add(FieldId_NANDPatrolCount, count)); + + /* Submit the record. */ + R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record))); + } + } + + R_SUCCEED(); + } + + Result SubmitMmcErrorInfo() { + /* TODO */ + R_SUCCEED(); + } + + Result SubmitSdCardDetailInfo() { + /* TODO */ + R_SUCCEED(); + } + + Result SubmitSdCardErrorInfo() { + /* TODO */ + R_SUCCEED(); + } + + Result SubmitGameCardDetailInfo() { + /* TODO */ + R_SUCCEED(); + } + + Result SubmitGameCardErrorInfo() { + /* TODO */ + R_SUCCEED(); + } + + Result SubmitFileSystemErrorInfo() { + /* TODO */ + R_SUCCEED(); + } + + Result SubmitMemoryReportInfo() { + /* TODO */ + R_SUCCEED(); + } + + } + + Result SubmitFsInfo() { + /* Temporarily disable auto-abort. */ + fs::ScopedAutoAbortDisabler aad; + + /* Submit various FS info. */ + R_TRY(SubmitMmcDetailInfo()); + R_TRY(SubmitMmcErrorInfo()); + R_TRY(SubmitSdCardDetailInfo()); + R_TRY(SubmitSdCardErrorInfo()); + R_TRY(SubmitGameCardDetailInfo()); + R_TRY(SubmitGameCardErrorInfo()); + R_TRY(SubmitFileSystemErrorInfo()); + R_TRY(SubmitMemoryReportInfo()); + + R_SUCCEED(); + } + +} diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp index ae0429a6d..afe0ce1fa 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp @@ -19,6 +19,7 @@ #include "erpt_srv_journal.hpp" #include "erpt_srv_context_record.hpp" #include "erpt_srv_context.hpp" +#include "erpt_srv_fs_info.hpp" namespace ams::erpt::srv { @@ -530,9 +531,14 @@ namespace ams::erpt::srv { SubmitResourceLimitContexts(); #endif - if (flags.Test()) { - /* TODO: 17.0.0 SubmitFsInfo() */ + /* If we should, submit fs info. */ + #if defined(ATMOSPHERE_OS_HORIZON) + if (hos::GetVersion() >= hos::Version_17_0_0 && flags.Test()) { + /* NOTE: Nintendo ignores the result of this call. */ + SubmitFsInfo(); } + #endif + R_SUCCEED(); } diff --git a/libraries/libstratosphere/source/fs/fs_mmc.cpp b/libraries/libstratosphere/source/fs/fs_mmc.cpp new file mode 100644 index 000000000..f0f8d6587 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fs_mmc.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 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 +#include "fsa/fs_mount_utils.hpp" +#include "impl/fs_file_system_proxy_service_object.hpp" +#include "impl/fs_file_system_service_object_adapter.hpp" + +namespace ams::fs { + + Result GetMmcCid(void *dst, size_t size) { + /* Check pre-conditions. */ + AMS_FS_R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); + + auto fsp = impl::GetFileSystemProxyServiceObject(); + + /* Open a device operator. */ + sf::SharedPointer device_operator; + AMS_FS_R_TRY(fsp->OpenDeviceOperator(std::addressof(device_operator))); + + /* Get the cid. */ + AMS_FS_R_TRY(device_operator->GetMmcCid(sf::OutBuffer(dst, size), static_cast(size))); + + R_SUCCEED(); + } + + Result GetMmcSpeedMode(MmcSpeedMode *out) { + /* Check pre-conditions. */ + AMS_FS_R_UNLESS(out != nullptr, fs::ResultNullptrArgument()); + + auto fsp = impl::GetFileSystemProxyServiceObject(); + + /* Open a device operator. */ + sf::SharedPointer device_operator; + AMS_FS_R_TRY(fsp->OpenDeviceOperator(std::addressof(device_operator))); + + /* Get the speed mode. */ + s64 speed_mode = 0; + AMS_FS_R_TRY(device_operator->GetMmcSpeedMode(std::addressof(speed_mode))); + + *out = static_cast(speed_mode); + R_SUCCEED(); + } + + Result GetMmcPatrolCount(u32 *out) { + /* Check pre-conditions. */ + AMS_FS_R_UNLESS(out != nullptr, fs::ResultNullptrArgument()); + + auto fsp = impl::GetFileSystemProxyServiceObject(); + + /* Open a device operator. */ + sf::SharedPointer device_operator; + AMS_FS_R_TRY(fsp->OpenDeviceOperator(std::addressof(device_operator))); + + /* Get the patrol count. */ + AMS_FS_R_TRY(device_operator->GetMmcPatrolCount(out)); + + R_SUCCEED(); + } + + Result GetMmcExtendedCsd(void *dst, size_t size) { + /* Check pre-conditions. */ + AMS_FS_R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); + + auto fsp = impl::GetFileSystemProxyServiceObject(); + + /* Open a device operator. */ + sf::SharedPointer device_operator; + AMS_FS_R_TRY(fsp->OpenDeviceOperator(std::addressof(device_operator))); + + /* Get the csd. */ + AMS_FS_R_TRY(device_operator->GetMmcExtendedCsd(sf::OutBuffer(dst, size), static_cast(size))); + + R_SUCCEED(); + } + +} diff --git a/libraries/libstratosphere/source/fs/impl/fs_remote_device_operator.hpp b/libraries/libstratosphere/source/fs/impl/fs_remote_device_operator.hpp index c6e674660..6b5c109ab 100644 --- a/libraries/libstratosphere/source/fs/impl/fs_remote_device_operator.hpp +++ b/libraries/libstratosphere/source/fs/impl/fs_remote_device_operator.hpp @@ -33,6 +33,22 @@ namespace ams::fs::impl { R_RETURN(fsDeviceOperatorIsSdCardInserted(std::addressof(m_operator), out.GetPointer())); } + Result GetMmcCid(ams::sf::OutBuffer out, s64 size) { + R_RETURN(fsDeviceOperatorGetMmcCid(std::addressof(m_operator), out.GetPointer(), out.GetSize(), size)); + } + + Result GetMmcSpeedMode(ams::sf::Out out) { + R_RETURN(fsDeviceOperatorGetMmcSpeedMode(std::addressof(m_operator), out.GetPointer())); + } + + Result GetMmcPatrolCount(ams::sf::Out out) { + R_RETURN(fsDeviceOperatorGetMmcPatrolCount(std::addressof(m_operator), out.GetPointer())); + } + + Result GetMmcExtendedCsd(ams::sf::OutBuffer out, s64 size) { + R_RETURN(fsDeviceOperatorGetMmcExtendedCsd(std::addressof(m_operator), out.GetPointer(), out.GetSize(), size)); + } + Result IsGameCardInserted(ams::sf::Out out) { R_RETURN(fsDeviceOperatorIsGameCardInserted(std::addressof(m_operator), out.GetPointer())); }