diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/file_sys/directory.h | 37 | ||||
| -rw-r--r-- | src/core/file_sys/disk_filesystem.cpp | 109 | ||||
| -rw-r--r-- | src/core/file_sys/disk_filesystem.h | 27 | ||||
| -rw-r--r-- | src/core/file_sys/filesystem.h | 8 | ||||
| -rw-r--r-- | src/core/file_sys/romfs_filesystem.cpp | 5 | ||||
| -rw-r--r-- | src/core/file_sys/romfs_filesystem.h | 10 | ||||
| -rw-r--r-- | src/core/file_sys/sdmc_factory.cpp | 40 | ||||
| -rw-r--r-- | src/core/file_sys/sdmc_factory.h | 31 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 102 | 
12 files changed, 329 insertions, 48 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 0a25a52e4..39cdb55f1 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -22,6 +22,8 @@ add_library(core STATIC      file_sys/romfs_filesystem.h      file_sys/savedata_factory.cpp      file_sys/savedata_factory.h +    file_sys/sdmc_factory.cpp +    file_sys/sdmc_factory.h      file_sys/storage.h      frontend/emu_window.cpp      frontend/emu_window.h diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h index 5a40bf472..c7639795e 100644 --- a/src/core/file_sys/directory.h +++ b/src/core/file_sys/directory.h @@ -6,34 +6,28 @@  #include <array>  #include <cstddef> +#include "common/common_funcs.h"  #include "common/common_types.h" +#include "core/file_sys/filesystem.h"  ////////////////////////////////////////////////////////////////////////////////////////////////////  // FileSys namespace  namespace FileSys { -// Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format -const size_t FILENAME_LENGTH = 0x20C / 2; +// Structure of a directory entry, from +// http://switchbrew.org/index.php?title=Filesystem_services#DirectoryEntry +const size_t FILENAME_LENGTH = 0x300;  struct Entry { -    char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) -    std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) -    char unknown1;                  // unknown (observed values: 0x0A, 0x70, 0xFD) -    std::array<char, 4> -        extension;     // 8.3 file extension (set to spaces for directories, null-terminated) -    char unknown2;     // unknown (always 0x01) -    char unknown3;     // unknown (0x00 or 0x08) -    char is_directory; // directory flag -    char is_hidden;    // hidden flag -    char is_archive;   // archive flag -    char is_read_only; // read-only flag -    u64 file_size;     // file size (for files only) +    char filename[FILENAME_LENGTH]; +    INSERT_PADDING_BYTES(4); +    EntryType type; +    INSERT_PADDING_BYTES(3); +    u64 file_size;  }; -static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); -static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); -static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension in Entry."); -static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); -static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); +static_assert(sizeof(Entry) == 0x310, "Directory Entry struct isn't exactly 0x310 bytes long!"); +static_assert(offsetof(Entry, type) == 0x304, "Wrong offset for type in Entry."); +static_assert(offsetof(Entry, file_size) == 0x308, "Wrong offset for file_size in Entry.");  class DirectoryBackend : NonCopyable {  public: @@ -46,7 +40,10 @@ public:       * @param entries Buffer to read data into       * @return Number of entries listed       */ -    virtual u32 Read(const u32 count, Entry* entries) = 0; +    virtual u64 Read(const u64 count, Entry* entries) = 0; + +    /// Returns the number of entries still left to read. +    virtual u64 GetEntryCount() const = 0;      /**       * Close the directory diff --git a/src/core/file_sys/disk_filesystem.cpp b/src/core/file_sys/disk_filesystem.cpp index 22b17ba04..3a4b45721 100644 --- a/src/core/file_sys/disk_filesystem.cpp +++ b/src/core/file_sys/disk_filesystem.cpp @@ -11,16 +11,43 @@  namespace FileSys { +static std::string ModeFlagsToString(Mode mode) { +    std::string mode_str; +    u32 mode_flags = static_cast<u32>(mode); + +    // Calculate the correct open mode for the file. +    if ((mode_flags & static_cast<u32>(Mode::Read)) && +        (mode_flags & static_cast<u32>(Mode::Write))) { +        if (mode_flags & static_cast<u32>(Mode::Append)) +            mode_str = "a+"; +        else +            mode_str = "r+"; +    } else { +        if (mode_flags & static_cast<u32>(Mode::Read)) +            mode_str = "r"; +        else if (mode_flags & static_cast<u32>(Mode::Append)) +            mode_str = "a"; +        else if (mode_flags & static_cast<u32>(Mode::Write)) +            mode_str = "w"; +    } + +    mode_str += "b"; + +    return mode_str; +} +  std::string Disk_FileSystem::GetName() const {      return "Disk";  }  ResultVal<std::unique_ptr<StorageBackend>> Disk_FileSystem::OpenFile(const std::string& path,                                                                       Mode mode) const { -    ASSERT_MSG(mode == Mode::Read || mode == Mode::Write, "Other file modes are not supported"); + +    // Calculate the correct open mode for the file. +    std::string mode_str = ModeFlagsToString(mode);      std::string full_path = base_directory + path; -    auto file = std::make_shared<FileUtil::IOFile>(full_path, mode == Mode::Read ? "rb" : "wb"); +    auto file = std::make_shared<FileUtil::IOFile>(full_path, mode_str.c_str());      if (!file->IsOpen()) {          return ERROR_PATH_NOT_FOUND; @@ -75,8 +102,15 @@ ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const      return ResultCode(-1);  } -ResultCode Disk_FileSystem::CreateDirectory(const Path& path) const { -    LOG_WARNING(Service_FS, "(STUBBED) called"); +ResultCode Disk_FileSystem::CreateDirectory(const std::string& path) const { +    // TODO(Subv): Perform path validation to prevent escaping the emulator sandbox. +    std::string full_path = base_directory + path; + +    if (FileUtil::CreateDir(full_path)) { +        return RESULT_SUCCESS; +    } + +    LOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating %s", full_path.c_str());      // TODO(wwylele): Use correct error code      return ResultCode(-1);  } @@ -88,8 +122,17 @@ ResultCode Disk_FileSystem::RenameDirectory(const Path& src_path, const Path& de  }  ResultVal<std::unique_ptr<DirectoryBackend>> Disk_FileSystem::OpenDirectory( -    const Path& path) const { -    return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<Disk_Directory>()); +    const std::string& path) const { + +    std::string full_path = base_directory + path; + +    if (!FileUtil::IsDirectory(full_path)) { +        // TODO(Subv): Find the correct error code for this. +        return ResultCode(-1); +    } + +    auto directory = std::make_unique<Disk_Directory>(full_path); +    return MakeResult<std::unique_ptr<DirectoryBackend>>(std::move(directory));  }  u64 Disk_FileSystem::GetFreeSpaceSize() const { @@ -103,8 +146,10 @@ ResultVal<FileSys::EntryType> Disk_FileSystem::GetEntryType(const std::string& p          return ERROR_PATH_NOT_FOUND;      } -    // TODO(Subv): Find out the EntryType values -    UNIMPLEMENTED_MSG("Unimplemented GetEntryType"); +    if (FileUtil::IsDirectory(full_path)) +        return MakeResult(EntryType::Directory); + +    return MakeResult(EntryType::File);  }  ResultVal<size_t> Disk_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { @@ -133,14 +178,50 @@ bool Disk_Storage::SetSize(const u64 size) const {      return false;  } -u32 Disk_Directory::Read(const u32 count, Entry* entries) { -    LOG_WARNING(Service_FS, "(STUBBED) called"); -    return 0; +Disk_Directory::Disk_Directory(const std::string& path) : directory() { +    unsigned size = FileUtil::ScanDirectoryTree(path, directory); +    directory.size = size; +    directory.isDirectory = true; +    children_iterator = directory.children.begin();  } -bool Disk_Directory::Close() const { -    LOG_WARNING(Service_FS, "(STUBBED) called"); -    return true; +u64 Disk_Directory::Read(const u64 count, Entry* entries) { +    u64 entries_read = 0; + +    while (entries_read < count && children_iterator != directory.children.cend()) { +        const FileUtil::FSTEntry& file = *children_iterator; +        const std::string& filename = file.virtualName; +        Entry& entry = entries[entries_read]; + +        LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, +                  file.isDirectory); + +        // TODO(Link Mauve): use a proper conversion to UTF-16. +        for (size_t j = 0; j < FILENAME_LENGTH; ++j) { +            entry.filename[j] = filename[j]; +            if (!filename[j]) +                break; +        } + +        if (file.isDirectory) { +            entry.file_size = 0; +            entry.type = EntryType::Directory; +        } else { +            entry.file_size = file.size; +            entry.type = EntryType::File; +        } + +        ++entries_read; +        ++children_iterator; +    } +    return entries_read; +} + +u64 Disk_Directory::GetEntryCount() const { +    // We convert the children iterator into a const_iterator to allow template argument deduction +    // in std::distance. +    std::vector<FileUtil::FSTEntry>::const_iterator current = children_iterator; +    return std::distance(current, directory.children.end());  }  } // namespace FileSys diff --git a/src/core/file_sys/disk_filesystem.h b/src/core/file_sys/disk_filesystem.h index 53767b949..742d7db1a 100644 --- a/src/core/file_sys/disk_filesystem.h +++ b/src/core/file_sys/disk_filesystem.h @@ -30,9 +30,10 @@ public:      ResultCode DeleteDirectory(const Path& path) const override;      ResultCode DeleteDirectoryRecursively(const Path& path) const override;      ResultCode CreateFile(const std::string& path, u64 size) const override; -    ResultCode CreateDirectory(const Path& path) const override; +    ResultCode CreateDirectory(const std::string& path) const override;      ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; -    ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override; +    ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory( +        const std::string& path) const override;      u64 GetFreeSpaceSize() const override;      ResultVal<EntryType> GetEntryType(const std::string& path) const override; @@ -59,8 +60,26 @@ private:  class Disk_Directory : public DirectoryBackend {  public: -    u32 Read(const u32 count, Entry* entries) override; -    bool Close() const override; +    Disk_Directory(const std::string& path); + +    ~Disk_Directory() override { +        Close(); +    } + +    u64 Read(const u64 count, Entry* entries) override; +    u64 GetEntryCount() const override; + +    bool Close() const override { +        return true; +    } + +protected: +    u32 total_entries_in_directory; +    FileUtil::FSTEntry directory; + +    // We need to remember the last entry we returned, so a subsequent call to Read will continue +    // from the next one. This iterator will always point to the next unread entry. +    std::vector<FileUtil::FSTEntry>::iterator children_iterator;  };  } // namespace FileSys diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h index 94ad2abf2..399427ca2 100644 --- a/src/core/file_sys/filesystem.h +++ b/src/core/file_sys/filesystem.h @@ -27,7 +27,7 @@ enum LowPathType : u32 {      Wchar = 4,  }; -enum EntryType : u32 { +enum EntryType : u8 {      Directory = 0,      File = 1,  }; @@ -35,6 +35,7 @@ enum EntryType : u32 {  enum class Mode : u32 {      Read = 1,      Write = 2, +    Append = 4,  };  class Path { @@ -103,7 +104,7 @@ public:       * @param path Path relative to the archive       * @return Result of the operation       */ -    virtual ResultCode CreateDirectory(const Path& path) const = 0; +    virtual ResultCode CreateDirectory(const std::string& path) const = 0;      /**       * Delete a directory specified by its path @@ -149,7 +150,8 @@ public:       * @param path Path relative to the archive       * @return Opened directory, or error code       */ -    virtual ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const = 0; +    virtual ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory( +        const std::string& path) const = 0;      /**       * Get the free space diff --git a/src/core/file_sys/romfs_filesystem.cpp b/src/core/file_sys/romfs_filesystem.cpp index f1f9b4d04..0c6cc3157 100644 --- a/src/core/file_sys/romfs_filesystem.cpp +++ b/src/core/file_sys/romfs_filesystem.cpp @@ -55,7 +55,7 @@ ResultCode RomFS_FileSystem::CreateFile(const std::string& path, u64 size) const      return ResultCode(-1);  } -ResultCode RomFS_FileSystem::CreateDirectory(const Path& path) const { +ResultCode RomFS_FileSystem::CreateDirectory(const std::string& path) const {      LOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive (%s).",                   GetName().c_str());      // TODO(wwylele): Use correct error code @@ -70,7 +70,8 @@ ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& d  }  ResultVal<std::unique_ptr<DirectoryBackend>> RomFS_FileSystem::OpenDirectory( -    const Path& path) const { +    const std::string& path) const { +    LOG_WARNING(Service_FS, "Opening Directory in a ROMFS archive");      return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<ROMFSDirectory>());  } diff --git a/src/core/file_sys/romfs_filesystem.h b/src/core/file_sys/romfs_filesystem.h index cedd70645..3f94c04d0 100644 --- a/src/core/file_sys/romfs_filesystem.h +++ b/src/core/file_sys/romfs_filesystem.h @@ -36,9 +36,10 @@ public:      ResultCode DeleteDirectory(const Path& path) const override;      ResultCode DeleteDirectoryRecursively(const Path& path) const override;      ResultCode CreateFile(const std::string& path, u64 size) const override; -    ResultCode CreateDirectory(const Path& path) const override; +    ResultCode CreateDirectory(const std::string& path) const override;      ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; -    ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override; +    ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory( +        const std::string& path) const override;      u64 GetFreeSpaceSize() const override;      ResultVal<EntryType> GetEntryType(const std::string& path) const override; @@ -70,7 +71,10 @@ private:  class ROMFSDirectory : public DirectoryBackend {  public: -    u32 Read(const u32 count, Entry* entries) override { +    u64 Read(const u64 count, Entry* entries) override { +        return 0; +    } +    u64 GetEntryCount() const override {          return 0;      }      bool Close() const override { diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp new file mode 100644 index 000000000..00e80d2a7 --- /dev/null +++ b/src/core/file_sys/sdmc_factory.cpp @@ -0,0 +1,40 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <cinttypes> +#include <memory> +#include "common/common_types.h" +#include "common/logging/log.h" +#include "common/string_util.h" +#include "core/core.h" +#include "core/file_sys/disk_filesystem.h" +#include "core/file_sys/sdmc_factory.h" + +namespace FileSys { + +SDMC_Factory::SDMC_Factory(std::string sd_directory) : sd_directory(std::move(sd_directory)) {} + +ResultVal<std::unique_ptr<FileSystemBackend>> SDMC_Factory::Open(const Path& path) { +    // Create the SD Card directory if it doesn't already exist. +    if (!FileUtil::IsDirectory(sd_directory)) { +        FileUtil::CreateFullPath(sd_directory); +    } + +    auto archive = std::make_unique<Disk_FileSystem>(sd_directory); +    return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); +} + +ResultCode SDMC_Factory::Format(const Path& path) { +    LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); +    // TODO(Subv): Find the right error code for this +    return ResultCode(-1); +} + +ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const { +    LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); +    // TODO(bunnei): Find the right error code for this +    return ResultCode(-1); +} + +} // namespace FileSys diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h new file mode 100644 index 000000000..93becda25 --- /dev/null +++ b/src/core/file_sys/sdmc_factory.h @@ -0,0 +1,31 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include "common/common_types.h" +#include "core/file_sys/filesystem.h" +#include "core/hle/result.h" + +namespace FileSys { + +/// File system interface to the SDCard archive +class SDMC_Factory final : public FileSystemFactory { +public: +    explicit SDMC_Factory(std::string sd_directory); + +    std::string GetName() const override { +        return "SDMC_Factory"; +    } +    ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override; +    ResultCode Format(const Path& path) override; +    ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; + +private: +    std::string sd_directory; +}; + +} // namespace FileSys diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index ef05955b9..945832e98 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -6,6 +6,7 @@  #include "common/file_util.h"  #include "core/file_sys/filesystem.h"  #include "core/file_sys/savedata_factory.h" +#include "core/file_sys/sdmc_factory.h"  #include "core/hle/service/filesystem/filesystem.h"  #include "core/hle/service/filesystem/fsp_srv.h" @@ -60,9 +61,13 @@ void RegisterFileSystems() {      filesystem_map.clear();      std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); +    std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX);      auto savedata = std::make_unique<FileSys::SaveData_Factory>(std::move(nand_directory));      RegisterFileSystem(std::move(savedata), Type::SaveData); + +    auto sdcard = std::make_unique<FileSys::SDMC_Factory>(std::move(sd_directory)); +    RegisterFileSystem(std::move(sdcard), Type::SDMC);  }  void InstallInterfaces(SM::ServiceManager& service_manager) { diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 8d30e94a1..56d26146e 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -26,6 +26,7 @@ namespace FileSystem {  enum class Type {      RomFS = 1,      SaveData = 2, +    SDMC = 3,  };  /** diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index e5ce41671..41b8cbfd2 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -5,6 +5,7 @@  #include <cinttypes>  #include "common/logging/log.h"  #include "core/core.h" +#include "core/file_sys/directory.h"  #include "core/file_sys/filesystem.h"  #include "core/file_sys/storage.h"  #include "core/hle/ipc_helpers.h" @@ -151,14 +152,66 @@ private:      }  }; +class IDirectory final : public ServiceFramework<IDirectory> { +public: +    explicit IDirectory(std::unique_ptr<FileSys::DirectoryBackend>&& backend) +        : ServiceFramework("IDirectory"), backend(std::move(backend)) { +        static const FunctionInfo functions[] = { +            {0, &IDirectory::Read, "Read"}, +            {1, &IDirectory::GetEntryCount, "GetEntryCount"}, +        }; +        RegisterHandlers(functions); +    } + +private: +    std::unique_ptr<FileSys::DirectoryBackend> backend; + +    void Read(Kernel::HLERequestContext& ctx) { +        IPC::RequestParser rp{ctx}; +        const u64 unk = rp.Pop<u64>(); + +        LOG_DEBUG(Service_FS, "called, unk=0x%llx", unk); + +        // Calculate how many entries we can fit in the output buffer +        u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); + +        // Read the data from the Directory backend +        std::vector<FileSys::Entry> entries(count_entries); +        u64 read_entries = backend->Read(count_entries, entries.data()); + +        // Convert the data into a byte array +        std::vector<u8> output(entries.size() * sizeof(FileSys::Entry)); +        std::memcpy(output.data(), entries.data(), output.size()); + +        // Write the data to memory +        ctx.WriteBuffer(output); + +        IPC::ResponseBuilder rb{ctx, 4}; +        rb.Push(RESULT_SUCCESS); +        rb.Push(read_entries); +    } + +    void GetEntryCount(Kernel::HLERequestContext& ctx) { +        LOG_DEBUG(Service_FS, "called"); + +        u64 count = backend->GetEntryCount(); + +        IPC::ResponseBuilder rb{ctx, 4}; +        rb.Push(RESULT_SUCCESS); +        rb.Push(count); +    } +}; +  class IFileSystem final : public ServiceFramework<IFileSystem> {  public:      explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend)          : ServiceFramework("IFileSystem"), backend(std::move(backend)) {          static const FunctionInfo functions[] = {              {0, &IFileSystem::CreateFile, "CreateFile"}, +            {2, &IFileSystem::CreateDirectory, "CreateDirectory"},              {7, &IFileSystem::GetEntryType, "GetEntryType"},              {8, &IFileSystem::OpenFile, "OpenFile"}, +            {9, &IFileSystem::OpenDirectory, "OpenDirectory"},              {10, &IFileSystem::Commit, "Commit"},          };          RegisterHandlers(functions); @@ -182,6 +235,20 @@ public:          rb.Push(backend->CreateFile(name, size));      } +    void CreateDirectory(Kernel::HLERequestContext& ctx) { +        IPC::RequestParser rp{ctx}; + +        auto file_buffer = ctx.ReadBuffer(); +        auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0'); + +        std::string name(file_buffer.begin(), end); + +        LOG_DEBUG(Service_FS, "called directory %s", name.c_str()); + +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(backend->CreateDirectory(name)); +    } +      void OpenFile(Kernel::HLERequestContext& ctx) {          IPC::RequestParser rp{ctx}; @@ -208,6 +275,33 @@ public:          rb.PushIpcInterface<IFile>(std::move(file));      } +    void OpenDirectory(Kernel::HLERequestContext& ctx) { +        IPC::RequestParser rp{ctx}; + +        auto file_buffer = ctx.ReadBuffer(); +        auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0'); + +        std::string name(file_buffer.begin(), end); + +        // TODO(Subv): Implement this filter. +        u32 filter_flags = rp.Pop<u32>(); + +        LOG_DEBUG(Service_FS, "called directory %s filter %u", name.c_str(), filter_flags); + +        auto result = backend->OpenDirectory(name); +        if (result.Failed()) { +            IPC::ResponseBuilder rb{ctx, 2}; +            rb.Push(result.Code()); +            return; +        } + +        auto directory = std::move(result.Unwrap()); + +        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +        rb.Push(RESULT_SUCCESS); +        rb.PushIpcInterface<IDirectory>(std::move(directory)); +    } +      void GetEntryType(Kernel::HLERequestContext& ctx) {          IPC::RequestParser rp{ctx}; @@ -274,10 +368,14 @@ void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) {  }  void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { -    LOG_WARNING(Service_FS, "(STUBBED) called"); +    LOG_DEBUG(Service_FS, "called"); -    IPC::ResponseBuilder rb{ctx, 2}; +    FileSys::Path unused; +    auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap(); + +    IPC::ResponseBuilder rb{ctx, 2, 0, 1};      rb.Push(RESULT_SUCCESS); +    rb.PushIpcInterface<IFileSystem>(std::move(filesystem));  }  void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {  | 
