summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/filesystem
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp335
-rw-r--r--src/core/hle/service/filesystem/filesystem.h118
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp132
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h28
4 files changed, 502 insertions, 111 deletions
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 1ebfeb4bf..14cd0e322 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -8,6 +8,7 @@
#include "common/file_util.h"
#include "core/core.h"
#include "core/file_sys/bis_factory.h"
+#include "core/file_sys/card_image.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/mode.h"
@@ -25,14 +26,10 @@
#include "core/hle/service/filesystem/fsp_pr.h"
#include "core/hle/service/filesystem/fsp_srv.h"
#include "core/loader/loader.h"
+#include "core/settings.h"
namespace Service::FileSystem {
-// Size of emulated sd card free space, reported in bytes.
-// Just using 32GB because thats reasonable
-// TODO(DarkLordZach): Eventually make this configurable in settings.
-constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
-
// A default size for normal/journal save data size if application control metadata cannot be found.
// This should be large enough to satisfy even the most extreme requirements (~4.2GB)
constexpr u64 SUFFICIENT_SAVE_DATA_SIZE = 0xF0000000;
@@ -226,13 +223,6 @@ ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const s
return MakeResult(dir);
}
-u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const {
- if (backing->IsWritable())
- return EMULATED_SD_REPORTED_SIZE;
-
- return 0;
-}
-
ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
const std::string& path_) const {
std::string path(FileUtil::SanitizePath(path_));
@@ -251,44 +241,39 @@ ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
return FileSys::ERROR_PATH_NOT_FOUND;
}
-/**
- * Map of registered file systems, identified by type. Once an file system is registered here, it
- * is never removed until UnregisterFileSystems is called.
- */
-static std::unique_ptr<FileSys::RomFSFactory> romfs_factory;
-static std::unique_ptr<FileSys::SaveDataFactory> save_data_factory;
-static std::unique_ptr<FileSys::SDMCFactory> sdmc_factory;
-static std::unique_ptr<FileSys::BISFactory> bis_factory;
+FileSystemController::FileSystemController() = default;
+
+FileSystemController::~FileSystemController() = default;
-ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory) {
- ASSERT_MSG(romfs_factory == nullptr, "Tried to register a second RomFS");
+ResultCode FileSystemController::RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory) {
romfs_factory = std::move(factory);
LOG_DEBUG(Service_FS, "Registered RomFS");
return RESULT_SUCCESS;
}
-ResultCode RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory) {
- ASSERT_MSG(romfs_factory == nullptr, "Tried to register a second save data");
+ResultCode FileSystemController::RegisterSaveData(
+ std::unique_ptr<FileSys::SaveDataFactory>&& factory) {
+ ASSERT_MSG(save_data_factory == nullptr, "Tried to register a second save data");
save_data_factory = std::move(factory);
LOG_DEBUG(Service_FS, "Registered save data");
return RESULT_SUCCESS;
}
-ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory) {
+ResultCode FileSystemController::RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory) {
ASSERT_MSG(sdmc_factory == nullptr, "Tried to register a second SDMC");
sdmc_factory = std::move(factory);
LOG_DEBUG(Service_FS, "Registered SDMC");
return RESULT_SUCCESS;
}
-ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) {
+ResultCode FileSystemController::RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) {
ASSERT_MSG(bis_factory == nullptr, "Tried to register a second BIS");
bis_factory = std::move(factory);
LOG_DEBUG(Service_FS, "Registered BIS");
return RESULT_SUCCESS;
}
-void SetPackedUpdate(FileSys::VirtualFile update_raw) {
+void FileSystemController::SetPackedUpdate(FileSys::VirtualFile update_raw) {
LOG_TRACE(Service_FS, "Setting packed update for romfs");
if (romfs_factory == nullptr)
@@ -297,7 +282,7 @@ void SetPackedUpdate(FileSys::VirtualFile update_raw) {
romfs_factory->SetPackedUpdate(std::move(update_raw));
}
-ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() {
+ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess() const {
LOG_TRACE(Service_FS, "Opening RomFS for current process");
if (romfs_factory == nullptr) {
@@ -308,8 +293,8 @@ ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() {
return romfs_factory->OpenCurrentProcess();
}
-ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
- FileSys::ContentRecordType type) {
+ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS(
+ u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const {
LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}",
title_id, static_cast<u8>(storage_id), static_cast<u8>(type));
@@ -321,8 +306,20 @@ ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId stora
return romfs_factory->Open(title_id, storage_id, type);
}
-ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
- const FileSys::SaveDataDescriptor& descriptor) {
+ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData(
+ FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& save_struct) const {
+ LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}",
+ static_cast<u8>(space), save_struct.DebugInfo());
+
+ if (save_data_factory == nullptr) {
+ return FileSys::ERROR_ENTITY_NOT_FOUND;
+ }
+
+ return save_data_factory->Create(space, save_struct);
+}
+
+ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData(
+ FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& descriptor) const {
LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}",
static_cast<u8>(space), descriptor.DebugInfo());
@@ -333,7 +330,8 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
return save_data_factory->Open(space, descriptor);
}
-ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) {
+ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace(
+ FileSys::SaveDataSpaceId space) const {
LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", static_cast<u8>(space));
if (save_data_factory == nullptr) {
@@ -343,7 +341,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space)
return MakeResult(save_data_factory->GetSaveDataSpaceDirectory(space));
}
-ResultVal<FileSys::VirtualDir> OpenSDMC() {
+ResultVal<FileSys::VirtualDir> FileSystemController::OpenSDMC() const {
LOG_TRACE(Service_FS, "Opening SDMC");
if (sdmc_factory == nullptr) {
@@ -353,7 +351,92 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
return sdmc_factory->Open();
}
-FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id) {
+ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition(
+ FileSys::BisPartitionId id) const {
+ LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", static_cast<u32>(id));
+
+ if (bis_factory == nullptr) {
+ return FileSys::ERROR_ENTITY_NOT_FOUND;
+ }
+
+ auto part = bis_factory->OpenPartition(id);
+ if (part == nullptr) {
+ return FileSys::ERROR_INVALID_ARGUMENT;
+ }
+
+ return MakeResult<FileSys::VirtualDir>(std::move(part));
+}
+
+ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage(
+ FileSys::BisPartitionId id) const {
+ LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", static_cast<u32>(id));
+
+ if (bis_factory == nullptr) {
+ return FileSys::ERROR_ENTITY_NOT_FOUND;
+ }
+
+ auto part = bis_factory->OpenPartitionStorage(id);
+ if (part == nullptr) {
+ return FileSys::ERROR_INVALID_ARGUMENT;
+ }
+
+ return MakeResult<FileSys::VirtualFile>(std::move(part));
+}
+
+u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const {
+ switch (id) {
+ case FileSys::StorageId::None:
+ case FileSys::StorageId::GameCard:
+ return 0;
+ case FileSys::StorageId::SdCard:
+ if (sdmc_factory == nullptr)
+ return 0;
+ return sdmc_factory->GetSDMCFreeSpace();
+ case FileSys::StorageId::Host:
+ if (bis_factory == nullptr)
+ return 0;
+ return bis_factory->GetSystemNANDFreeSpace() + bis_factory->GetUserNANDFreeSpace();
+ case FileSys::StorageId::NandSystem:
+ if (bis_factory == nullptr)
+ return 0;
+ return bis_factory->GetSystemNANDFreeSpace();
+ case FileSys::StorageId::NandUser:
+ if (bis_factory == nullptr)
+ return 0;
+ return bis_factory->GetUserNANDFreeSpace();
+ }
+
+ return 0;
+}
+
+u64 FileSystemController::GetTotalSpaceSize(FileSys::StorageId id) const {
+ switch (id) {
+ case FileSys::StorageId::None:
+ case FileSys::StorageId::GameCard:
+ return 0;
+ case FileSys::StorageId::SdCard:
+ if (sdmc_factory == nullptr)
+ return 0;
+ return sdmc_factory->GetSDMCTotalSpace();
+ case FileSys::StorageId::Host:
+ if (bis_factory == nullptr)
+ return 0;
+ return bis_factory->GetFullNANDTotalSpace();
+ case FileSys::StorageId::NandSystem:
+ if (bis_factory == nullptr)
+ return 0;
+ return bis_factory->GetSystemNANDTotalSpace();
+ case FileSys::StorageId::NandUser:
+ if (bis_factory == nullptr)
+ return 0;
+ return bis_factory->GetUserNANDTotalSpace();
+ }
+
+ return 0;
+}
+
+FileSys::SaveDataSize FileSystemController::ReadSaveDataSize(FileSys::SaveDataType type,
+ u64 title_id, u128 user_id) const {
if (save_data_factory == nullptr) {
return {0, 0};
}
@@ -385,13 +468,32 @@ FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id,
return value;
}
-void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
- FileSys::SaveDataSize new_value) {
+void FileSystemController::WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
+ FileSys::SaveDataSize new_value) const {
if (save_data_factory != nullptr)
save_data_factory->WriteSaveDataSize(type, title_id, user_id, new_value);
}
-FileSys::RegisteredCache* GetSystemNANDContents() {
+void FileSystemController::SetGameCard(FileSys::VirtualFile file) {
+ gamecard = std::make_unique<FileSys::XCI>(file);
+ const auto dir = gamecard->ConcatenatedPseudoDirectory();
+ gamecard_registered = std::make_unique<FileSys::RegisteredCache>(dir);
+ gamecard_placeholder = std::make_unique<FileSys::PlaceholderCache>(dir);
+}
+
+FileSys::XCI* FileSystemController::GetGameCard() const {
+ return gamecard.get();
+}
+
+FileSys::RegisteredCache* FileSystemController::GetGameCardContents() const {
+ return gamecard_registered.get();
+}
+
+FileSys::PlaceholderCache* FileSystemController::GetGameCardPlaceholder() const {
+ return gamecard_placeholder.get();
+}
+
+FileSys::RegisteredCache* FileSystemController::GetSystemNANDContents() const {
LOG_TRACE(Service_FS, "Opening System NAND Contents");
if (bis_factory == nullptr)
@@ -400,7 +502,7 @@ FileSys::RegisteredCache* GetSystemNANDContents() {
return bis_factory->GetSystemNANDContents();
}
-FileSys::RegisteredCache* GetUserNANDContents() {
+FileSys::RegisteredCache* FileSystemController::GetUserNANDContents() const {
LOG_TRACE(Service_FS, "Opening User NAND Contents");
if (bis_factory == nullptr)
@@ -409,7 +511,7 @@ FileSys::RegisteredCache* GetUserNANDContents() {
return bis_factory->GetUserNANDContents();
}
-FileSys::RegisteredCache* GetSDMCContents() {
+FileSys::RegisteredCache* FileSystemController::GetSDMCContents() const {
LOG_TRACE(Service_FS, "Opening SDMC Contents");
if (sdmc_factory == nullptr)
@@ -418,7 +520,143 @@ FileSys::RegisteredCache* GetSDMCContents() {
return sdmc_factory->GetSDMCContents();
}
-FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) {
+FileSys::PlaceholderCache* FileSystemController::GetSystemNANDPlaceholder() const {
+ LOG_TRACE(Service_FS, "Opening System NAND Placeholder");
+
+ if (bis_factory == nullptr)
+ return nullptr;
+
+ return bis_factory->GetSystemNANDPlaceholder();
+}
+
+FileSys::PlaceholderCache* FileSystemController::GetUserNANDPlaceholder() const {
+ LOG_TRACE(Service_FS, "Opening User NAND Placeholder");
+
+ if (bis_factory == nullptr)
+ return nullptr;
+
+ return bis_factory->GetUserNANDPlaceholder();
+}
+
+FileSys::PlaceholderCache* FileSystemController::GetSDMCPlaceholder() const {
+ LOG_TRACE(Service_FS, "Opening SDMC Placeholder");
+
+ if (sdmc_factory == nullptr)
+ return nullptr;
+
+ return sdmc_factory->GetSDMCPlaceholder();
+}
+
+FileSys::RegisteredCache* FileSystemController::GetRegisteredCacheForStorage(
+ FileSys::StorageId id) const {
+ switch (id) {
+ case FileSys::StorageId::None:
+ case FileSys::StorageId::Host:
+ UNIMPLEMENTED();
+ return nullptr;
+ case FileSys::StorageId::GameCard:
+ return GetGameCardContents();
+ case FileSys::StorageId::NandSystem:
+ return GetSystemNANDContents();
+ case FileSys::StorageId::NandUser:
+ return GetUserNANDContents();
+ case FileSys::StorageId::SdCard:
+ return GetSDMCContents();
+ }
+
+ return nullptr;
+}
+
+FileSys::PlaceholderCache* FileSystemController::GetPlaceholderCacheForStorage(
+ FileSys::StorageId id) const {
+ switch (id) {
+ case FileSys::StorageId::None:
+ case FileSys::StorageId::Host:
+ UNIMPLEMENTED();
+ return nullptr;
+ case FileSys::StorageId::GameCard:
+ return GetGameCardPlaceholder();
+ case FileSys::StorageId::NandSystem:
+ return GetSystemNANDPlaceholder();
+ case FileSys::StorageId::NandUser:
+ return GetUserNANDPlaceholder();
+ case FileSys::StorageId::SdCard:
+ return GetSDMCPlaceholder();
+ }
+
+ return nullptr;
+}
+
+FileSys::VirtualDir FileSystemController::GetSystemNANDContentDirectory() const {
+ LOG_TRACE(Service_FS, "Opening system NAND content directory");
+
+ if (bis_factory == nullptr)
+ return nullptr;
+
+ return bis_factory->GetSystemNANDContentDirectory();
+}
+
+FileSys::VirtualDir FileSystemController::GetUserNANDContentDirectory() const {
+ LOG_TRACE(Service_FS, "Opening user NAND content directory");
+
+ if (bis_factory == nullptr)
+ return nullptr;
+
+ return bis_factory->GetUserNANDContentDirectory();
+}
+
+FileSys::VirtualDir FileSystemController::GetSDMCContentDirectory() const {
+ LOG_TRACE(Service_FS, "Opening SDMC content directory");
+
+ if (sdmc_factory == nullptr)
+ return nullptr;
+
+ return sdmc_factory->GetSDMCContentDirectory();
+}
+
+FileSys::VirtualDir FileSystemController::GetNANDImageDirectory() const {
+ LOG_TRACE(Service_FS, "Opening NAND image directory");
+
+ if (bis_factory == nullptr)
+ return nullptr;
+
+ return bis_factory->GetImageDirectory();
+}
+
+FileSys::VirtualDir FileSystemController::GetSDMCImageDirectory() const {
+ LOG_TRACE(Service_FS, "Opening SDMC image directory");
+
+ if (sdmc_factory == nullptr)
+ return nullptr;
+
+ return sdmc_factory->GetImageDirectory();
+}
+
+FileSys::VirtualDir FileSystemController::GetContentDirectory(ContentStorageId id) const {
+ switch (id) {
+ case ContentStorageId::System:
+ return GetSystemNANDContentDirectory();
+ case ContentStorageId::User:
+ return GetUserNANDContentDirectory();
+ case ContentStorageId::SdCard:
+ return GetSDMCContentDirectory();
+ }
+
+ return nullptr;
+}
+
+FileSys::VirtualDir FileSystemController::GetImageDirectory(ImageDirectoryId id) const {
+ switch (id) {
+ case ImageDirectoryId::NAND:
+ return GetNANDImageDirectory();
+ case ImageDirectoryId::SdCard:
+ return GetSDMCImageDirectory();
+ }
+
+ return nullptr;
+}
+
+FileSys::VirtualDir FileSystemController::GetModificationLoadRoot(u64 title_id) const {
LOG_TRACE(Service_FS, "Opening mod load root for tid={:016X}", title_id);
if (bis_factory == nullptr)
@@ -427,7 +665,7 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) {
return bis_factory->GetModificationLoadRoot(title_id);
}
-FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) {
+FileSys::VirtualDir FileSystemController::GetModificationDumpRoot(u64 title_id) const {
LOG_TRACE(Service_FS, "Opening mod dump root for tid={:016X}", title_id);
if (bis_factory == nullptr)
@@ -436,7 +674,7 @@ FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) {
return bis_factory->GetModificationDumpRoot(title_id);
}
-void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
+void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
if (overwrite) {
bis_factory = nullptr;
save_data_factory = nullptr;
@@ -472,12 +710,11 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
}
}
-void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) {
- 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);
+void InstallInterfaces(Core::System& system) {
+ std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager());
+ std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager());
+ std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetReporter())
+ ->InstallAsService(system.ServiceManager());
}
} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 6481f237c..3e0c03ec0 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -14,10 +14,13 @@ namespace FileSys {
class BISFactory;
class RegisteredCache;
class RegisteredCacheUnion;
+class PlaceholderCache;
class RomFSFactory;
class SaveDataFactory;
class SDMCFactory;
+class XCI;
+enum class BisPartitionId : u32;
enum class ContentRecordType : u8;
enum class Mode : u32;
enum class SaveDataSpaceId : u8;
@@ -36,36 +39,93 @@ class ServiceManager;
namespace FileSystem {
-ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory);
-ResultCode RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory);
-ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory);
-ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
-
-void SetPackedUpdate(FileSys::VirtualFile update_raw);
-ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess();
-ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
- FileSys::ContentRecordType type);
-ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
- const FileSys::SaveDataDescriptor& descriptor);
-ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
-ResultVal<FileSys::VirtualDir> OpenSDMC();
-
-FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id);
-void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
- FileSys::SaveDataSize new_value);
+enum class ContentStorageId : u32 {
+ System,
+ User,
+ SdCard,
+};
-FileSys::RegisteredCache* GetSystemNANDContents();
-FileSys::RegisteredCache* GetUserNANDContents();
-FileSys::RegisteredCache* GetSDMCContents();
+enum class ImageDirectoryId : u32 {
+ NAND,
+ SdCard,
+};
-FileSys::VirtualDir GetModificationLoadRoot(u64 title_id);
-FileSys::VirtualDir GetModificationDumpRoot(u64 title_id);
+class FileSystemController {
+public:
+ FileSystemController();
+ ~FileSystemController();
+
+ ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory);
+ ResultCode RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory);
+ ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory);
+ ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
+
+ void SetPackedUpdate(FileSys::VirtualFile update_raw);
+ ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const;
+ ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
+ FileSys::ContentRecordType type) const;
+ ResultVal<FileSys::VirtualDir> CreateSaveData(
+ FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& save_struct) const;
+ ResultVal<FileSys::VirtualDir> OpenSaveData(
+ FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& save_struct) const;
+ ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const;
+ ResultVal<FileSys::VirtualDir> OpenSDMC() const;
+ ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const;
+ ResultVal<FileSys::VirtualFile> OpenBISPartitionStorage(FileSys::BisPartitionId id) const;
+
+ u64 GetFreeSpaceSize(FileSys::StorageId id) const;
+ u64 GetTotalSpaceSize(FileSys::StorageId id) const;
+
+ FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id,
+ u128 user_id) const;
+ void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
+ FileSys::SaveDataSize new_value) const;
+
+ void SetGameCard(FileSys::VirtualFile file);
+ FileSys::XCI* GetGameCard() const;
+
+ FileSys::RegisteredCache* GetSystemNANDContents() const;
+ FileSys::RegisteredCache* GetUserNANDContents() const;
+ FileSys::RegisteredCache* GetSDMCContents() const;
+ FileSys::RegisteredCache* GetGameCardContents() const;
+
+ FileSys::PlaceholderCache* GetSystemNANDPlaceholder() const;
+ FileSys::PlaceholderCache* GetUserNANDPlaceholder() const;
+ FileSys::PlaceholderCache* GetSDMCPlaceholder() const;
+ FileSys::PlaceholderCache* GetGameCardPlaceholder() const;
+
+ FileSys::RegisteredCache* GetRegisteredCacheForStorage(FileSys::StorageId id) const;
+ FileSys::PlaceholderCache* GetPlaceholderCacheForStorage(FileSys::StorageId id) const;
+
+ FileSys::VirtualDir GetSystemNANDContentDirectory() const;
+ FileSys::VirtualDir GetUserNANDContentDirectory() const;
+ FileSys::VirtualDir GetSDMCContentDirectory() const;
+
+ FileSys::VirtualDir GetNANDImageDirectory() const;
+ FileSys::VirtualDir GetSDMCImageDirectory() const;
+
+ FileSys::VirtualDir GetContentDirectory(ContentStorageId id) const;
+ FileSys::VirtualDir GetImageDirectory(ImageDirectoryId id) const;
+
+ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) const;
+ FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) const;
+
+ // Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
+ // above is called.
+ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true);
-// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
-// above is called.
-void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true);
+private:
+ std::unique_ptr<FileSys::RomFSFactory> romfs_factory;
+ std::unique_ptr<FileSys::SaveDataFactory> save_data_factory;
+ std::unique_ptr<FileSys::SDMCFactory> sdmc_factory;
+ std::unique_ptr<FileSys::BISFactory> bis_factory;
+
+ std::unique_ptr<FileSys::XCI> gamecard;
+ std::unique_ptr<FileSys::RegisteredCache> gamecard_registered;
+ std::unique_ptr<FileSys::PlaceholderCache> gamecard_placeholder;
+};
-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
@@ -160,12 +220,6 @@ public:
ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path);
/**
- * Get the free space
- * @return The number of free bytes in the archive
- */
- u64 GetFreeSpaceSize() const;
-
- /**
* Get the type of the specified path
* @return The type of the specified path or error code
*/
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index e7df8fd98..eb982ad49 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -19,6 +19,7 @@
#include "core/file_sys/mode.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/patch_manager.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.h"
@@ -26,9 +27,22 @@
#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 {
+struct SizeGetter {
+ std::function<u64()> get_free_size;
+ std::function<u64()> get_total_size;
+
+ static SizeGetter FromStorageId(const FileSystemController& fsc, FileSys::StorageId id) {
+ return {
+ [&fsc, id] { return fsc.GetFreeSpaceSize(id); },
+ [&fsc, id] { return fsc.GetTotalSpaceSize(id); },
+ };
+ }
+};
+
enum class FileSystemType : u8 {
Invalid0 = 0,
Invalid1 = 1,
@@ -288,8 +302,8 @@ private:
class IFileSystem final : public ServiceFramework<IFileSystem> {
public:
- explicit IFileSystem(FileSys::VirtualDir backend)
- : ServiceFramework("IFileSystem"), backend(std::move(backend)) {
+ explicit IFileSystem(FileSys::VirtualDir backend, SizeGetter size)
+ : ServiceFramework("IFileSystem"), backend(std::move(backend)), size(std::move(size)) {
static const FunctionInfo functions[] = {
{0, &IFileSystem::CreateFile, "CreateFile"},
{1, &IFileSystem::DeleteFile, "DeleteFile"},
@@ -466,14 +480,31 @@ public:
rb.Push(RESULT_SUCCESS);
}
+ void GetFreeSpaceSize(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_FS, "called");
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(size.get_free_size());
+ }
+
+ void GetTotalSpaceSize(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_FS, "called");
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(size.get_total_size());
+ }
+
private:
VfsDirectoryServiceWrapper backend;
+ SizeGetter size;
};
class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
public:
- explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space)
- : ServiceFramework("ISaveDataInfoReader") {
+ explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space, FileSystemController& fsc)
+ : ServiceFramework("ISaveDataInfoReader"), fsc(fsc) {
static const FunctionInfo functions[] = {
{0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"},
};
@@ -519,8 +550,13 @@ private:
}
void FindAllSaves(FileSys::SaveDataSpaceId space) {
- const auto save_root = OpenSaveDataSpace(space);
- ASSERT(save_root.Succeeded());
+ const auto save_root = fsc.OpenSaveDataSpace(space);
+
+ if (save_root.Failed() || *save_root == nullptr) {
+ LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!",
+ static_cast<u8>(space));
+ return;
+ }
for (const auto& type : (*save_root)->GetSubdirectories()) {
if (type->GetName() == "save") {
@@ -609,11 +645,13 @@ private:
};
static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
+ FileSystemController& fsc;
std::vector<SaveDataInfo> info;
u64 next_entry_index = 0;
};
-FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
+FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
+ : ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "OpenFileSystem"},
@@ -710,14 +748,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"},
@@ -753,7 +791,8 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) {
void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
- IFileSystem filesystem(OpenSDMC().Unwrap());
+ IFileSystem filesystem(fsc.OpenSDMC().Unwrap(),
+ SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -767,8 +806,10 @@ void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
u128 uid = rp.PopRaw<u128>();
- LOG_WARNING(Service_FS, "(STUBBED) called save_struct = {}, uid = {:016X}{:016X}",
- save_struct.DebugInfo(), uid[1], uid[0]);
+ LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(),
+ uid[1], uid[0]);
+
+ fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandUser, save_struct);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -785,14 +826,24 @@ void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto parameters = rp.PopRaw<Parameters>();
- auto dir = OpenSaveData(parameters.save_data_space_id, parameters.descriptor);
+ auto dir = fsc.OpenSaveData(parameters.save_data_space_id, parameters.descriptor);
if (dir.Failed()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
return;
}
- IFileSystem filesystem(std::move(dir.Unwrap()));
+ FileSys::StorageId id;
+ if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::NandUser) {
+ id = FileSys::StorageId::NandUser;
+ } else if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardSystem ||
+ parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardUser) {
+ id = FileSys::StorageId::SdCard;
+ } else {
+ id = FileSys::StorageId::NandSystem;
+ }
+
+ IFileSystem filesystem(std::move(dir.Unwrap()), SizeGetter::FromStorageId(fsc, id));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -811,30 +862,31 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext&
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space));
+ rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space, fsc));
}
-void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_FS, "(STUBBED) called");
+void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ log_mode = rp.PopEnum<LogMode>();
- enum class LogMode : u32 {
- Off,
- Log,
- RedirectToSdCard,
- LogToSdCard = Log | RedirectToSdCard,
- };
+ 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_DEBUG(Service_FS, "called");
- // 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) {
LOG_DEBUG(Service_FS, "called");
- auto romfs = OpenRomFSCurrentProcess();
+ auto romfs = fsc.OpenRomFSCurrentProcess();
if (romfs.Failed()) {
// TODO (bunnei): Find the right error code to use here
LOG_CRITICAL(Service_FS, "no file system interface available!");
@@ -859,7 +911,7 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called with storage_id={:02X}, unknown={:08X}, title_id={:016X}",
static_cast<u8>(storage_id), unknown, title_id);
- auto data = OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data);
+ auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data);
if (data.Failed()) {
const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id);
@@ -902,4 +954,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
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index d7572ba7a..d52b55999 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -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(FileSystemController& fsc, const Core::Reporter& reporter);
~FSP_SRV() override;
private:
@@ -26,13 +43,22 @@ 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);
+
+ FileSystemController& fsc;
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