diff options
| author | David <25727384+ogniK5377@users.noreply.github.com> | 2019-09-22 11:42:34 +1000 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-22 11:42:34 +1000 | 
| commit | c9ccdfbeac21ddd74d3cc79e8ef2c8d82f3d4efd (patch) | |
| tree | e260125fd1ef6e8a29b255b967a447eeb1aeb204 /src/core/hle/service | |
| parent | 7979ccd9569865952b552635f918c98899c91ce9 (diff) | |
| parent | 038bcec11153cefd713ddb06eddcc42b0a936df2 (diff) | |
Merge pull request #2430 from DarkLordZach/fs-controller
core: Implement FileSystemController to deglobalize FS services
Diffstat (limited to 'src/core/hle/service')
| -rw-r--r-- | src/core/hle/service/am/am.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet_ae.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet_oe.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 329 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.h | 116 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 80 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/ns/ns.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/ns/ns.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/ns/pl_u.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/ns/pl_u.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/service/service.h | 8 | 
13 files changed, 493 insertions, 116 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index aa2c83937..6c594dcaf 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1143,13 +1143,21 @@ void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(  void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx}; -    u128 uid = rp.PopRaw<u128>(); // What does this do? -    LOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]); +    u128 user_id = rp.PopRaw<u128>(); + +    LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); + +    FileSys::SaveDataDescriptor descriptor{}; +    descriptor.title_id = Core::CurrentProcess()->GetTitleID(); +    descriptor.user_id = user_id; +    descriptor.type = FileSys::SaveDataType::SaveData; +    const auto res = system.GetFileSystemController().CreateSaveData( +        FileSys::SaveDataSpaceId::NandUser, descriptor);      IPC::ResponseBuilder rb{ctx, 4}; -    rb.Push(RESULT_SUCCESS); +    rb.Push(res.Code());      rb.Push<u64>(0); -} // namespace Service::AM +}  void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {      // Takes an input u32 Result, no output. @@ -1261,8 +1269,8 @@ void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {                "new_journal={:016X}",                static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); -    const auto title_id = system.CurrentProcess()->GetTitleID(); -    FileSystem::WriteSaveDataSize(type, title_id, user_id, {new_normal_size, new_journal_size}); +    system.GetFileSystemController().WriteSaveDataSize( +        type, system.CurrentProcess()->GetTitleID(), user_id, {new_normal_size, new_journal_size});      IPC::ResponseBuilder rb{ctx, 4};      rb.Push(RESULT_SUCCESS); @@ -1281,8 +1289,8 @@ void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {      LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", static_cast<u8>(type),                user_id[1], user_id[0]); -    const auto title_id = system.CurrentProcess()->GetTitleID(); -    const auto size = FileSystem::ReadSaveDataSize(type, title_id, user_id); +    const auto size = system.GetFileSystemController().ReadSaveDataSize( +        type, system.CurrentProcess()->GetTitleID(), user_id);      IPC::ResponseBuilder rb{ctx, 6};      rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 9e006cd9d..0e0d10858 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h @@ -9,6 +9,10 @@  #include "core/hle/service/service.h"  namespace Service { +namespace FileSystem { +class FileSystemController; +} +  namespace NVFlinger {  class NVFlinger;  } diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 22c05419d..99a65e7b5 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -9,6 +9,10 @@  #include "core/hle/service/service.h"  namespace Service { +namespace FileSystem { +class FileSystemController; +} +  namespace NVFlinger {  class NVFlinger;  } diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 8ce110dd1..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; @@ -473,11 +711,10 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {  }  void InstallInterfaces(Core::System& system) { -    romfs_factory = nullptr; -    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()); +    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 3849dd89e..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,34 +39,91 @@ 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(Core::System& system); @@ -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 d3cd46a9b..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" @@ -30,6 +31,18 @@  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, @@ -289,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"}, @@ -467,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"},          }; @@ -520,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") { @@ -610,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(const Core::Reporter& reporter) : ServiceFramework("fsp-srv"), reporter(reporter) { +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"}, @@ -754,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); @@ -768,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); @@ -786,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); @@ -812,7 +862,7 @@ 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::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { @@ -836,7 +886,7 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {  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!"); @@ -861,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); diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index b5486a193..d52b55999 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -32,7 +32,7 @@ enum class LogMode : u32 {  class FSP_SRV final : public ServiceFramework<FSP_SRV> {  public: -    explicit FSP_SRV(const Core::Reporter& reporter); +    explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter);      ~FSP_SRV() override;  private: @@ -51,6 +51,8 @@ private:      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; diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index ce88a2941..13121c4f1 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -617,7 +617,7 @@ public:      }  }; -void InstallInterfaces(SM::ServiceManager& service_manager) { +void InstallInterfaces(SM::ServiceManager& service_manager, FileSystem::FileSystemController& fsc) {      std::make_shared<NS>("ns:am2")->InstallAsService(service_manager);      std::make_shared<NS>("ns:ec")->InstallAsService(service_manager);      std::make_shared<NS>("ns:rid")->InstallAsService(service_manager); @@ -628,7 +628,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {      std::make_shared<NS_SU>()->InstallAsService(service_manager);      std::make_shared<NS_VM>()->InstallAsService(service_manager); -    std::make_shared<PL_U>()->InstallAsService(service_manager); +    std::make_shared<PL_U>(fsc)->InstallAsService(service_manager);  }  } // namespace Service::NS diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 0e8256cb4..d067e7a9a 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -6,7 +6,13 @@  #include "core/hle/service/service.h" -namespace Service::NS { +namespace Service { + +namespace FileSystem { +class FileSystemController; +} // namespace FileSystem + +namespace NS {  class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {  public: @@ -91,6 +97,8 @@ private:  };  /// Registers all NS services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, FileSystem::FileSystemController& fsc); + +} // namespace NS -} // namespace Service::NS +} // namespace Service diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index 2a522136d..9d49f36e8 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp @@ -150,7 +150,8 @@ struct PL_U::Impl {      std::vector<FontRegion> shared_font_regions;  }; -PL_U::PL_U() : ServiceFramework("pl:u"), impl{std::make_unique<Impl>()} { +PL_U::PL_U(FileSystem::FileSystemController& fsc) +    : ServiceFramework("pl:u"), impl{std::make_unique<Impl>()} {      static const FunctionInfo functions[] = {          {0, &PL_U::RequestLoad, "RequestLoad"},          {1, &PL_U::GetLoadState, "GetLoadState"}, @@ -161,7 +162,7 @@ PL_U::PL_U() : ServiceFramework("pl:u"), impl{std::make_unique<Impl>()} {      };      RegisterHandlers(functions);      // Attempt to load shared font data from disk -    const auto* nand = FileSystem::GetSystemNANDContents(); +    const auto* nand = fsc.GetSystemNANDContents();      std::size_t offset = 0;      // Rebuild shared fonts from data ncas      if (nand->HasEntry(static_cast<u64>(FontArchives::Standard), diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/pl_u.h index 253f26a2a..35ca424d2 100644 --- a/src/core/hle/service/ns/pl_u.h +++ b/src/core/hle/service/ns/pl_u.h @@ -7,11 +7,17 @@  #include <memory>  #include "core/hle/service/service.h" -namespace Service::NS { +namespace Service { + +namespace FileSystem { +class FileSystemController; +} // namespace FileSystem + +namespace NS {  class PL_U final : public ServiceFramework<PL_U> {  public: -    PL_U(); +    PL_U(FileSystem::FileSystemController& fsc);      ~PL_U() override;  private: @@ -26,4 +32,6 @@ private:      std::unique_ptr<Impl> impl;  }; -} // namespace Service::NS +} // namespace NS + +} // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 3a0f8c3f6..454387467 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -199,6 +199,7 @@ 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()); +    system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);      SM::ServiceManager::InstallInterfaces(sm); @@ -235,7 +236,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {      NIFM::InstallInterfaces(*sm);      NIM::InstallInterfaces(*sm);      NPNS::InstallInterfaces(*sm); -    NS::InstallInterfaces(*sm); +    NS::InstallInterfaces(*sm, system.GetFileSystemController());      Nvidia::InstallInterfaces(*sm, *nv_flinger, system);      PCIe::InstallInterfaces(*sm);      PCTL::InstallInterfaces(*sm); diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index c6c4bdae5..aef964861 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -18,10 +18,6 @@ namespace Core {  class System;  } -namespace FileSys { -class VfsFilesystem; -} -  namespace Kernel {  class ClientPort;  class ServerPort; @@ -31,6 +27,10 @@ class HLERequestContext;  namespace Service { +namespace FileSystem { +class FileSystemController; +} // namespace FileSystem +  namespace SM {  class ServiceManager;  }  | 
