// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include #include #include #include #include #include "common/assert.h" #include "common/common_types.h" #include "common/hex_util.h" #include "common/logging/log.h" #include "common/settings.h" #include "common/string_util.h" #include "core/core.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/errors.h" #include "core/file_sys/fs_directory.h" #include "core/file_sys/fs_filesystem.h" #include "core/file_sys/nca_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/romfs.h" #include "core/file_sys/romfs_factory.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/system_archive/system_archive.h" #include "core/file_sys/vfs/vfs.h" #include "core/hle/result.h" #include "core/hle/service/cmif_serialization.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp/fs_i_filesystem.h" #include "core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.h" #include "core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h" #include "core/hle/service/filesystem/fsp/fs_i_storage.h" #include "core/hle/service/filesystem/fsp/fsp_srv.h" #include "core/hle/service/filesystem/romfs_controller.h" #include "core/hle/service/filesystem/save_data_controller.h" #include "core/hle/service/hle_ipc.h" #include "core/hle/service/ipc_helpers.h" #include "core/loader/loader.h" #include "core/reporter.h" namespace Service::FileSystem { FSP_SRV::FSP_SRV(Core::System& system_) : ServiceFramework{system_, "fsp-srv"}, fsc{system.GetFileSystemController()}, content_provider{system.GetContentProvider()}, reporter{system.GetReporter()} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenFileSystem"}, {1, D<&FSP_SRV::SetCurrentProcess>, "SetCurrentProcess"}, {2, nullptr, "OpenDataFileSystemByCurrentProcess"}, {7, D<&FSP_SRV::OpenFileSystemWithPatch>, "OpenFileSystemWithPatch"}, {8, nullptr, "OpenFileSystemWithId"}, {9, nullptr, "OpenDataFileSystemByApplicationId"}, {11, nullptr, "OpenBisFileSystem"}, {12, nullptr, "OpenBisStorage"}, {13, nullptr, "InvalidateBisCache"}, {17, nullptr, "OpenHostFileSystem"}, {18, D<&FSP_SRV::OpenSdCardFileSystem>, "OpenSdCardFileSystem"}, {19, nullptr, "FormatSdCardFileSystem"}, {21, nullptr, "DeleteSaveDataFileSystem"}, {22, D<&FSP_SRV::CreateSaveDataFileSystem>, "CreateSaveDataFileSystem"}, {23, D<&FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId>, "CreateSaveDataFileSystemBySystemSaveDataId"}, {24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"}, {25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"}, {26, nullptr, "FormatSdCardDryRun"}, {27, nullptr, "IsExFatSupported"}, {28, nullptr, "DeleteSaveDataFileSystemBySaveDataAttribute"}, {30, nullptr, "OpenGameCardStorage"}, {31, nullptr, "OpenGameCardFileSystem"}, {32, nullptr, "ExtendSaveDataFileSystem"}, {33, nullptr, "DeleteCacheStorage"}, {34, D<&FSP_SRV::GetCacheStorageSize>, "GetCacheStorageSize"}, {35, nullptr, "CreateSaveDataFileSystemByHashSalt"}, {36, nullptr, "OpenHostFileSystemWithOption"}, {51, D<&FSP_SRV::OpenSaveDataFileSystem>, "OpenSaveDataFileSystem"}, {52, D<&FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId>, "OpenSaveDataFileSystemBySystemSaveDataId"}, {53, D<&FSP_SRV::OpenReadOnlySaveDataFileSystem>, "OpenReadOnlySaveDataFileSystem"}, {57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"}, {58, nullptr, "ReadSaveDataFileSystemExtraData"}, {59, nullptr, "WriteSaveDataFileSystemExtraData"}, {60, nullptr, "OpenSaveDataInfoReader"}, {61, D<&FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId>, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, {62, D<&FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage>, "OpenSaveDataInfoReaderOnlyCacheStorage"}, {64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, {65, nullptr, "UpdateSaveDataMacForDebug"}, {66, nullptr, "WriteSaveDataFileSystemExtraData2"}, {67, nullptr, "FindSaveDataWithFilter"}, {68, nullptr, "OpenSaveDataInfoReaderBySaveDataFilter"}, {69, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataAttribute"}, {70, D<&FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute>, "WriteSaveDataFileSystemExtraDataBySaveDataAttribute"}, {71, D<&FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute>, "ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"}, {80, nullptr, "OpenSaveDataMetaFile"}, {81, nullptr, "OpenSaveDataTransferManager"}, {82, nullptr, "OpenSaveDataTransferManagerVersion2"}, {83, nullptr, "OpenSaveDataTransferProhibiterForCloudBackUp"}, {84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"}, {85, nullptr, "OpenSaveDataTransferManagerForSaveDataRepair"}, {86, nullptr, "OpenSaveDataMover"}, {87, nullptr, "OpenSaveDataTransferManagerForRepair"}, {100, nullptr, "OpenImageDirectoryFileSystem"}, {101, nullptr, "OpenBaseFileSystem"}, {102, nullptr, "FormatBaseFileSystem"}, {110, nullptr, "OpenContentStorageFileSystem"}, {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"}, {130, nullptr, "OpenCustomStorageFileSystem"}, {200, D<&FSP_SRV::OpenDataStorageByCurrentProcess>, "OpenDataStorageByCurrentProcess"}, {201, nullptr, "OpenDataStorageByProgramId"}, {202, D<&FSP_SRV::OpenDataStorageByDataId>, "OpenDataStorageByDataId"}, {203, D<&FSP_SRV::OpenPatchDataStorageByCurrentProcess>, "OpenPatchDataStorageByCurrentProcess"}, {204, nullptr, "OpenDataFileSystemByProgramIndex"}, {205, D<&FSP_SRV::OpenDataStorageWithProgramIndex>, "OpenDataStorageWithProgramIndex"}, {206, nullptr, "OpenDataStorageByPath"}, {400, nullptr, "OpenDeviceOperator"}, {500, nullptr, "OpenSdCardDetectionEventNotifier"}, {501, nullptr, "OpenGameCardDetectionEventNotifier"}, {510, nullptr, "OpenSystemDataUpdateEventNotifier"}, {511, nullptr, "NotifySystemDataUpdateEvent"}, {520, nullptr, "SimulateGameCardDetectionEvent"}, {600, nullptr, "SetCurrentPosixTime"}, {601, nullptr, "QuerySaveDataTotalSize"}, {602, nullptr, "VerifySaveDataFileSystem"}, {603, nullptr, "CorruptSaveDataFileSystem"}, {604, nullptr, "CreatePaddingFile"}, {605, nullptr, "DeleteAllPaddingFiles"}, {606, nullptr, "GetRightsId"}, {607, nullptr, "RegisterExternalKey"}, {608, nullptr, "UnregisterAllExternalKey"}, {609, nullptr, "GetRightsIdByPath"}, {610, nullptr, "GetRightsIdAndKeyGenerationByPath"}, {611, nullptr, "SetCurrentPosixTimeWithTimeDifference"}, {612, nullptr, "GetFreeSpaceSizeForSaveData"}, {613, nullptr, "VerifySaveDataFileSystemBySaveDataSpaceId"}, {614, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId"}, {615, nullptr, "QuerySaveDataInternalStorageTotalSize"}, {616, nullptr, "GetSaveDataCommitId"}, {617, nullptr, "UnregisterExternalKey"}, {620, nullptr, "SetSdCardEncryptionSeed"}, {630, nullptr, "SetSdCardAccessibility"}, {631, nullptr, "IsSdCardAccessible"}, {640, nullptr, "IsSignedSystemPartitionOnSdCardValid"}, {700, nullptr, "OpenAccessFailureResolver"}, {701, nullptr, "GetAccessFailureDetectionEvent"}, {702, nullptr, "IsAccessFailureDetected"}, {710, nullptr, "ResolveAccessFailure"}, {720, nullptr, "AbandonAccessFailure"}, {800, nullptr, "GetAndClearFileSystemProxyErrorInfo"}, {810, nullptr, "RegisterProgramIndexMapInfo"}, {1000, nullptr, "SetBisRootForHost"}, {1001, nullptr, "SetSaveDataSize"}, {1002, nullptr, "SetSaveDataRootPath"}, {1003, D<&FSP_SRV::DisableAutoSaveDataCreation>, "DisableAutoSaveDataCreation"}, {1004, D<&FSP_SRV::SetGlobalAccessLogMode>, "SetGlobalAccessLogMode"}, {1005, D<&FSP_SRV::GetGlobalAccessLogMode>, "GetGlobalAccessLogMode"}, {1006, D<&FSP_SRV::OutputAccessLogToSdCard>, "OutputAccessLogToSdCard"}, {1007, nullptr, "RegisterUpdatePartition"}, {1008, nullptr, "OpenRegisteredUpdatePartition"}, {1009, nullptr, "GetAndClearMemoryReportInfo"}, {1010, nullptr, "SetDataStorageRedirectTarget"}, {1011, D<&FSP_SRV::GetProgramIndexForAccessLog>, "GetProgramIndexForAccessLog"}, {1012, nullptr, "GetFsStackUsage"}, {1013, nullptr, "UnsetSaveDataRootPath"}, {1014, nullptr, "OutputMultiProgramTagAccessLog"}, {1016, D<&FSP_SRV::FlushAccessLogOnSdCard>, "FlushAccessLogOnSdCard"}, {1017, nullptr, "OutputApplicationInfoAccessLog"}, {1018, nullptr, "SetDebugOption"}, {1019, nullptr, "UnsetDebugOption"}, {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, {1200, D<&FSP_SRV::OpenMultiCommitManager>, "OpenMultiCommitManager"}, {1300, nullptr, "OpenBisWiper"}, }; // clang-format on RegisterHandlers(functions); if (Settings::values.enable_fs_access_log) { access_log_mode = AccessLogMode::SdCard; } } FSP_SRV::~FSP_SRV() = default; Result FSP_SRV::SetCurrentProcess(ClientProcessId pid) { current_process_id = *pid; LOG_DEBUG(Service_FS, "called. current_process_id=0x{:016X}", current_process_id); R_RETURN( fsc.OpenProcess(&program_id, &save_data_controller, &romfs_controller, current_process_id)); } Result FSP_SRV::OpenFileSystemWithPatch(OutInterface out_interface, FileSystemProxyType type, u64 open_program_id) { LOG_ERROR(Service_FS, "(STUBBED) called with type={}, program_id={:016X}", type, open_program_id); // FIXME: many issues with this ASSERT(type == FileSystemProxyType::Manual); const auto manual_romfs = romfs_controller->OpenPatchedRomFS( open_program_id, FileSys::ContentRecordType::HtmlDocument); ASSERT(manual_romfs != nullptr); const auto extracted_romfs = FileSys::ExtractRomFS(manual_romfs); ASSERT(extracted_romfs != nullptr); *out_interface = std::make_shared( system, extracted_romfs, SizeGetter::FromStorageId(fsc, FileSys::StorageId::NandUser)); R_SUCCEED(); } Result FSP_SRV::OpenSdCardFileSystem(OutInterface out_interface) { LOG_DEBUG(Service_FS, "called"); FileSys::VirtualDir sdmc_dir{}; fsc.OpenSDMC(&sdmc_dir); *out_interface = std::make_shared( system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); R_SUCCEED(); } Result FSP_SRV::CreateSaveDataFileSystem(FileSys::SaveDataCreationInfo save_create_struct, FileSys::SaveDataAttribute save_struct, u128 uid) { LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(), uid[1], uid[0]); FileSys::VirtualDir save_data_dir{}; R_RETURN(save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::User, save_struct)); } Result FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId( FileSys::SaveDataAttribute save_struct, FileSys::SaveDataCreationInfo save_create_struct) { LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo()); FileSys::VirtualDir save_data_dir{}; R_RETURN(save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::System, save_struct)); } Result FSP_SRV::OpenSaveDataFileSystem(OutInterface out_interface, FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute) { LOG_INFO(Service_FS, "called."); FileSys::VirtualDir dir{}; R_TRY(save_data_controller->OpenSaveData(&dir, space_id, attribute)); FileSys::StorageId id{}; switch (space_id) { case FileSys::SaveDataSpaceId::User: id = FileSys::StorageId::NandUser; break; case FileSys::SaveDataSpaceId::SdSystem: case FileSys::SaveDataSpaceId::SdUser: id = FileSys::StorageId::SdCard; break; case FileSys::SaveDataSpaceId::System: id = FileSys::StorageId::NandSystem; break; case FileSys::SaveDataSpaceId::Temporary: case FileSys::SaveDataSpaceId::ProperSystem: case FileSys::SaveDataSpaceId::SafeMode: ASSERT(false); } *out_interface = std::make_shared(system, std::move(dir), SizeGetter::FromStorageId(fsc, id)); R_SUCCEED(); } Result FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(OutInterface out_interface, FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute) { LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem"); R_RETURN(OpenSaveDataFileSystem(out_interface, space_id, attribute)); } Result FSP_SRV::OpenReadOnlySaveDataFileSystem(OutInterface out_interface, FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute) { LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem"); R_RETURN(OpenSaveDataFileSystem(out_interface, space_id, attribute)); } Result FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId( OutInterface out_interface, FileSys::SaveDataSpaceId space) { LOG_INFO(Service_FS, "called, space={}", space); *out_interface = std::make_shared(system, save_data_controller, space); R_SUCCEED(); } Result FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage( OutInterface out_interface) { LOG_WARNING(Service_FS, "(STUBBED) called"); *out_interface = std::make_shared(system, save_data_controller, FileSys::SaveDataSpaceId::Temporary); R_SUCCEED(); } Result FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute() { LOG_WARNING(Service_FS, "(STUBBED) called."); R_SUCCEED(); } Result FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute, InBuffer mask_buffer, OutBuffer out_buffer) { // Stub this to None for now, backend needs an impl to read/write the SaveDataExtraData // In an earlier version of the code, this was returned as an out argument, but this is not // correct [[maybe_unused]] constexpr auto flags = static_cast(FileSys::SaveDataFlags::None); LOG_WARNING(Service_FS, "(STUBBED) called, flags={}, space_id={}, attribute.program_id={:016X}\n" "attribute.user_id={:016X}{:016X}, attribute.save_id={:016X}\n" "attribute.type={}, attribute.rank={}, attribute.index={}", flags, space_id, attribute.program_id, attribute.user_id[1], attribute.user_id[0], attribute.system_save_data_id, attribute.type, attribute.rank, attribute.index); R_SUCCEED(); } Result FSP_SRV::OpenDataStorageByCurrentProcess(OutInterface out_interface) { LOG_DEBUG(Service_FS, "called"); if (!romfs) { auto current_romfs = romfs_controller->OpenRomFSCurrentProcess(); if (!current_romfs) { // TODO (bunnei): Find the right error code to use here LOG_CRITICAL(Service_FS, "No file system interface available!"); R_RETURN(ResultUnknown); } romfs = current_romfs; } *out_interface = std::make_shared(system, romfs); R_SUCCEED(); } Result FSP_SRV::OpenDataStorageByDataId(OutInterface out_interface, FileSys::StorageId storage_id, u32 unknown, u64 title_id) { LOG_DEBUG(Service_FS, "called with storage_id={:02X}, unknown={:08X}, title_id={:016X}", storage_id, unknown, title_id); auto data = romfs_controller->OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); if (!data) { const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); if (archive != nullptr) { *out_interface = std::make_shared(system, archive); R_SUCCEED(); } // TODO(DarkLordZach): Find the right error code to use here LOG_ERROR(Service_FS, "Could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, storage_id); R_RETURN(ResultUnknown); } const FileSys::PatchManager pm{title_id, fsc, content_provider}; auto base = romfs_controller->OpenBaseNca(title_id, storage_id, FileSys::ContentRecordType::Data); auto storage = std::make_shared( system, pm.PatchRomFS(base.get(), std::move(data), FileSys::ContentRecordType::Data)); *out_interface = std::move(storage); R_SUCCEED(); } Result FSP_SRV::OpenPatchDataStorageByCurrentProcess(OutInterface out_interface, FileSys::StorageId storage_id, u64 title_id) { LOG_WARNING(Service_FS, "(STUBBED) called with storage_id={:02X}, title_id={:016X}", storage_id, title_id); R_RETURN(FileSys::ResultTargetNotFound); } Result FSP_SRV::OpenDataStorageWithProgramIndex(OutInterface out_interface, u8 program_index) { LOG_DEBUG(Service_FS, "called, program_index={}", program_index); auto patched_romfs = romfs_controller->OpenPatchedRomFSWithProgramIndex( program_id, program_index, FileSys::ContentRecordType::Program); if (!patched_romfs) { // TODO: Find the right error code to use here LOG_ERROR(Service_FS, "Could not open storage with program_index={}", program_index); R_RETURN(ResultUnknown); } *out_interface = std::make_shared(system, std::move(patched_romfs)); R_SUCCEED(); } Result FSP_SRV::DisableAutoSaveDataCreation() { LOG_DEBUG(Service_FS, "called"); save_data_controller->SetAutoCreate(false); R_SUCCEED(); } Result FSP_SRV::SetGlobalAccessLogMode(AccessLogMode access_log_mode_) { LOG_DEBUG(Service_FS, "called, access_log_mode={}", access_log_mode_); access_log_mode = access_log_mode_; R_SUCCEED(); } Result FSP_SRV::GetGlobalAccessLogMode(Out out_access_log_mode) { LOG_DEBUG(Service_FS, "called"); *out_access_log_mode = access_log_mode; R_SUCCEED(); } Result FSP_SRV::OutputAccessLogToSdCard(InBuffer log_message_buffer) { LOG_DEBUG(Service_FS, "called"); auto log = Common::StringFromFixedZeroTerminatedBuffer( reinterpret_cast(log_message_buffer.data()), log_message_buffer.size()); reporter.SaveFSAccessLog(log); R_SUCCEED(); } Result FSP_SRV::GetProgramIndexForAccessLog(Out out_access_log_version, Out out_access_log_program_index) { LOG_DEBUG(Service_FS, "(STUBBED) called"); *out_access_log_version = AccessLogVersion::Latest; *out_access_log_program_index = access_log_program_index; R_SUCCEED(); } Result FSP_SRV::FlushAccessLogOnSdCard() { LOG_DEBUG(Service_FS, "(STUBBED) called"); R_SUCCEED(); } Result FSP_SRV::GetCacheStorageSize(s32 index, Out out_data_size, Out out_journal_size) { LOG_WARNING(Service_FS, "(STUBBED) called with index={}", index); *out_data_size = 0; *out_journal_size = 0; R_SUCCEED(); } Result FSP_SRV::OpenMultiCommitManager(OutInterface out_interface) { LOG_DEBUG(Service_FS, "called"); *out_interface = std::make_shared(system); R_SUCCEED(); } } // namespace Service::FileSystem