Merge pull request #2642 from DarkLordZach/fsp-log-2
fsp-srv: Implement Access Logging Functionality
This commit is contained in:
		| @@ -143,7 +143,7 @@ struct System::Impl { | ||||
|         telemetry_session = std::make_unique<Core::TelemetrySession>(); | ||||
|         service_manager = std::make_shared<Service::SM::ServiceManager>(); | ||||
|  | ||||
|         Service::Init(service_manager, system, *virtual_filesystem); | ||||
|         Service::Init(service_manager, system); | ||||
|         GDBStub::Init(); | ||||
|  | ||||
|         renderer = VideoCore::CreateRenderer(emu_window, system); | ||||
|   | ||||
| @@ -472,12 +472,12 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) { | ||||
| void InstallInterfaces(Core::System& system) { | ||||
|     romfs_factory = nullptr; | ||||
|     CreateFactories(vfs, false); | ||||
|     std::make_shared<FSP_LDR>()->InstallAsService(service_manager); | ||||
|     std::make_shared<FSP_PR>()->InstallAsService(service_manager); | ||||
|     std::make_shared<FSP_SRV>()->InstallAsService(service_manager); | ||||
|     CreateFactories(*system.GetFilesystem(), false); | ||||
|     std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager()); | ||||
|     std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager()); | ||||
|     std::make_shared<FSP_SRV>(system.GetReporter())->InstallAsService(system.ServiceManager()); | ||||
| } | ||||
|  | ||||
| } // namespace Service::FileSystem | ||||
|   | ||||
| @@ -65,7 +65,7 @@ FileSys::VirtualDir GetModificationDumpRoot(u64 title_id); | ||||
| // above is called. | ||||
| void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true); | ||||
|  | ||||
| void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs); | ||||
| void InstallInterfaces(Core::System& system); | ||||
|  | ||||
| // A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of | ||||
| // pointers and booleans. This makes using a VfsDirectory with switch services much easier and | ||||
|   | ||||
| @@ -26,6 +26,7 @@ | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/service/filesystem/filesystem.h" | ||||
| #include "core/hle/service/filesystem/fsp_srv.h" | ||||
| #include "core/reporter.h" | ||||
|  | ||||
| namespace Service::FileSystem { | ||||
|  | ||||
| @@ -613,7 +614,7 @@ private: | ||||
|     u64 next_entry_index = 0; | ||||
| }; | ||||
|  | ||||
| FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | ||||
| FSP_SRV::FSP_SRV(const Core::Reporter& reporter) : ServiceFramework("fsp-srv"), reporter(reporter) { | ||||
|     // clang-format off | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, nullptr, "OpenFileSystem"}, | ||||
| @@ -710,14 +711,14 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | ||||
|         {1001, nullptr, "SetSaveDataSize"}, | ||||
|         {1002, nullptr, "SetSaveDataRootPath"}, | ||||
|         {1003, nullptr, "DisableAutoSaveDataCreation"}, | ||||
|         {1004, nullptr, "SetGlobalAccessLogMode"}, | ||||
|         {1004, &FSP_SRV::SetGlobalAccessLogMode, "SetGlobalAccessLogMode"}, | ||||
|         {1005, &FSP_SRV::GetGlobalAccessLogMode, "GetGlobalAccessLogMode"}, | ||||
|         {1006, nullptr, "OutputAccessLogToSdCard"}, | ||||
|         {1006, &FSP_SRV::OutputAccessLogToSdCard, "OutputAccessLogToSdCard"}, | ||||
|         {1007, nullptr, "RegisterUpdatePartition"}, | ||||
|         {1008, nullptr, "OpenRegisteredUpdatePartition"}, | ||||
|         {1009, nullptr, "GetAndClearMemoryReportInfo"}, | ||||
|         {1010, nullptr, "SetDataStorageRedirectTarget"}, | ||||
|         {1011, nullptr, "OutputAccessLogToSdCard2"}, | ||||
|         {1011, &FSP_SRV::GetAccessLogVersionInfo, "GetAccessLogVersionInfo"}, | ||||
|         {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, | ||||
|         {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, | ||||
|         {1200, nullptr, "OpenMultiCommitManager"}, | ||||
| @@ -814,21 +815,22 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& | ||||
|     rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space)); | ||||
| } | ||||
|  | ||||
| void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     log_mode = rp.PopEnum<LogMode>(); | ||||
|  | ||||
|     LOG_DEBUG(Service_FS, "called, log_mode={:08X}", static_cast<u32>(log_mode)); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| } | ||||
|  | ||||
| void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_FS, "(STUBBED) called"); | ||||
|     LOG_DEBUG(Service_FS, "called"); | ||||
|  | ||||
|     enum class LogMode : u32 { | ||||
|         Off, | ||||
|         Log, | ||||
|         RedirectToSdCard, | ||||
|         LogToSdCard = Log | RedirectToSdCard, | ||||
|     }; | ||||
|  | ||||
|     // Given we always want to receive logging information, | ||||
|     // we always specify logging as enabled. | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushEnum(LogMode::Log); | ||||
|     rb.PushEnum(log_mode); | ||||
| } | ||||
|  | ||||
| void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | ||||
| @@ -902,4 +904,26 @@ void FSP_SRV::OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ct | ||||
|     rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); | ||||
| } | ||||
|  | ||||
| void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { | ||||
|     const auto raw = ctx.ReadBuffer(); | ||||
|     auto log = Common::StringFromFixedZeroTerminatedBuffer( | ||||
|         reinterpret_cast<const char*>(raw.data()), raw.size()); | ||||
|  | ||||
|     LOG_DEBUG(Service_FS, "called, log='{}'", log); | ||||
|  | ||||
|     reporter.SaveFilesystemAccessReport(log_mode, std::move(log)); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| } | ||||
|  | ||||
| void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_FS, "called"); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushEnum(AccessLogVersion::Latest); | ||||
|     rb.Push(access_log_program_index); | ||||
| } | ||||
|  | ||||
| } // namespace Service::FileSystem | ||||
|   | ||||
| @@ -7,15 +7,32 @@ | ||||
| #include <memory> | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Core { | ||||
| class Reporter; | ||||
| } | ||||
|  | ||||
| namespace FileSys { | ||||
| class FileSystemBackend; | ||||
| } | ||||
|  | ||||
| namespace Service::FileSystem { | ||||
|  | ||||
| enum class AccessLogVersion : u32 { | ||||
|     V7_0_0 = 2, | ||||
|  | ||||
|     Latest = V7_0_0, | ||||
| }; | ||||
|  | ||||
| enum class LogMode : u32 { | ||||
|     Off, | ||||
|     Log, | ||||
|     RedirectToSdCard, | ||||
|     LogToSdCard = Log | RedirectToSdCard, | ||||
| }; | ||||
|  | ||||
| class FSP_SRV final : public ServiceFramework<FSP_SRV> { | ||||
| public: | ||||
|     explicit FSP_SRV(); | ||||
|     explicit FSP_SRV(const Core::Reporter& reporter); | ||||
|     ~FSP_SRV() override; | ||||
|  | ||||
| private: | ||||
| @@ -26,13 +43,20 @@ private: | ||||
|     void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx); | ||||
|     void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); | ||||
|     void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); | ||||
|     void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | ||||
|     void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | ||||
|     void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); | ||||
|     void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); | ||||
|     void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); | ||||
|     void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); | ||||
|     void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx); | ||||
|  | ||||
|     FileSys::VirtualFile romfs; | ||||
|     u64 current_process_id = 0; | ||||
|     u32 access_log_program_index = 0; | ||||
|     LogMode log_mode = LogMode::LogToSdCard; | ||||
|  | ||||
|     const Core::Reporter& reporter; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::FileSystem | ||||
|   | ||||
| @@ -195,8 +195,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co | ||||
| // Module interface | ||||
|  | ||||
| /// Initialize ServiceManager | ||||
| void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | ||||
|           FileSys::VfsFilesystem& vfs) { | ||||
| void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) { | ||||
|     // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it | ||||
|     // here and pass it into the respective InstallInterfaces functions. | ||||
|     auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(system.CoreTiming()); | ||||
| @@ -218,7 +217,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | ||||
|     EUPLD::InstallInterfaces(*sm); | ||||
|     Fatal::InstallInterfaces(*sm); | ||||
|     FGM::InstallInterfaces(*sm); | ||||
|     FileSystem::InstallInterfaces(*sm, vfs); | ||||
|     FileSystem::InstallInterfaces(system); | ||||
|     Friend::InstallInterfaces(*sm); | ||||
|     Glue::InstallInterfaces(system); | ||||
|     GRC::InstallInterfaces(*sm); | ||||
|   | ||||
| @@ -182,8 +182,7 @@ private: | ||||
| }; | ||||
|  | ||||
| /// Initialize ServiceManager | ||||
| void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | ||||
|           FileSys::VfsFilesystem& vfs); | ||||
| void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); | ||||
|  | ||||
| /// Shutdown ServiceManager | ||||
| void Shutdown(); | ||||
|   | ||||
| @@ -350,6 +350,24 @@ void Reporter::SaveErrorReport(u64 title_id, ResultCode result, | ||||
|     SaveToFile(std::move(out), GetPath("error_report", title_id, timestamp)); | ||||
| } | ||||
|  | ||||
| void Reporter::SaveFilesystemAccessReport(Service::FileSystem::LogMode log_mode, | ||||
|                                           std::string log_message) const { | ||||
|     if (!IsReportingEnabled()) | ||||
|         return; | ||||
|  | ||||
|     const auto timestamp = GetTimestamp(); | ||||
|     const auto title_id = system.CurrentProcess()->GetTitleID(); | ||||
|     json out; | ||||
|  | ||||
|     out["yuzu_version"] = GetYuzuVersionData(); | ||||
|     out["report_common"] = GetReportCommonData(title_id, RESULT_SUCCESS, timestamp); | ||||
|  | ||||
|     out["log_mode"] = fmt::format("{:08X}", static_cast<u32>(log_mode)); | ||||
|     out["log_message"] = std::move(log_message); | ||||
|  | ||||
|     SaveToFile(std::move(out), GetPath("filesystem_access_report", title_id, timestamp)); | ||||
| } | ||||
|  | ||||
| void Reporter::SaveUserReport() const { | ||||
|     if (!IsReportingEnabled()) { | ||||
|         return; | ||||
|   | ||||
| @@ -16,6 +16,10 @@ namespace Kernel { | ||||
| class HLERequestContext; | ||||
| } // namespace Kernel | ||||
|  | ||||
| namespace Service::FileSystem { | ||||
| enum class LogMode : u32; | ||||
| } | ||||
|  | ||||
| namespace Core { | ||||
|  | ||||
| class System; | ||||
| @@ -49,6 +53,9 @@ public: | ||||
|                          std::optional<std::string> custom_text_main = {}, | ||||
|                          std::optional<std::string> custom_text_detail = {}) const; | ||||
|  | ||||
|     void SaveFilesystemAccessReport(Service::FileSystem::LogMode log_mode, | ||||
|                                     std::string log_message) const; | ||||
|  | ||||
|     void SaveUserReport() const; | ||||
|  | ||||
| private: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user