Browse Source

filesystem: Implement basic IStorage functionality.

David Marcec 8 years ago
parent
commit
d64b7d7dfd

+ 4 - 0
src/core/CMakeLists.txt

@@ -97,6 +97,10 @@ add_library(core STATIC
     hle/service/audio/audio.h
     hle/service/audio/audout_u.cpp
     hle/service/audio/audout_u.h
+    hle/service/filesystem/filesystem.cpp
+    hle/service/filesystem/filesystem.h
+    hle/service/filesystem/fsp_srv.cpp
+    hle/service/filesystem/fsp_srv.h
     hle/service/hid/hid.cpp
     hle/service/hid/hid.h
     hle/service/lm/lm.cpp

+ 54 - 0
src/core/hle/service/filesystem/filesystem.cpp

@@ -0,0 +1,54 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <boost/container/flat_map.hpp>
+#include "core/file_sys/filesystem.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/filesystem/fsp_srv.h"
+
+namespace Service {
+namespace FileSystem {
+
+/**
+ * Map of registered file systems, identified by type. Once an file system is registered here, it
+ * is never removed until UnregisterFileSystems is called.
+ */
+static boost::container::flat_map<Type, std::unique_ptr<FileSys::FileSystemFactory>> filesystem_map;
+
+ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type) {
+    auto result = filesystem_map.emplace(type, std::move(factory));
+
+    bool inserted = result.second;
+    ASSERT_MSG(inserted, "Tried to register more than one system with same id code");
+
+    auto& filesystem = result.first->second;
+    LOG_DEBUG(Service_FS, "Registered file system %s with id code 0x%08X",
+              filesystem->GetName().c_str(), static_cast<u32>(type));
+    return RESULT_SUCCESS;
+}
+
+ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
+                                                                      FileSys::Path& path) {
+    LOG_TRACE(Service_FS, "Opening FileSystem with type=%d", type);
+
+    auto itr = filesystem_map.find(type);
+    if (itr == filesystem_map.end()) {
+        // TODO(bunnei): Find a better error code for this
+        return ResultCode(-1);
+    }
+
+    return itr->second->Open(path);
+}
+
+void UnregisterFileSystems() {
+    filesystem_map.clear();
+}
+
+void InstallInterfaces(SM::ServiceManager& service_manager) {
+    UnregisterFileSystems();
+    std::make_shared<FSP_SRV>()->InstallAsService(service_manager);
+}
+
+} // namespace FileSystem
+} // namespace Service

+ 41 - 0
src/core/hle/service/filesystem/filesystem.h

@@ -0,0 +1,41 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include "common/common_types.h"
+#include "core/file_sys/filesystem.h"
+#include "core/hle/result.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace FileSystem {
+
+/// Supported FileSystem types
+enum class Type {
+    RomFS = 1,
+};
+
+/**
+ * Registers a FileSystem, instances of which can later be opened using its IdCode.
+ * @param factory FileSystem backend interface to use
+ * @param type Type used to access this type of FileSystem
+ */
+ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type);
+
+/**
+ * Opens a file system
+ * @param type Type of the file system to open
+ * @param path Path to the file system, used with Binary paths
+ * @return FileSys::FileSystemBackend interface to the file system
+ */
+ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
+                                                                      FileSys::Path& path);
+
+/// Registers all Filesystem services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& service_manager);
+
+} // namespace Filesystem
+} // namespace Service

+ 132 - 0
src/core/hle/service/filesystem/fsp_srv.cpp

@@ -0,0 +1,132 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+#include "core/core.h"
+#include "core/file_sys/filesystem.h"
+#include "core/file_sys/storage.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/client_port.h"
+#include "core/hle/kernel/client_session.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/filesystem/fsp_srv.h"
+
+namespace Service {
+namespace FileSystem {
+
+class IStorage final : public ServiceFramework<IStorage> {
+public:
+    IStorage(std::unique_ptr<FileSys::StorageBackend>&& backend)
+        : ServiceFramework("IStorage"), backend(std::move(backend)) {
+        static const FunctionInfo functions[] = {
+            {0, &IStorage::Read, "Read"},       {1, &IStorage::Write, "Write"},
+            {2, &IStorage::Flush, "Flush"},     {3, &IStorage::SetSize, "SetSize"},
+            {4, &IStorage::GetSize, "GetSize"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    std::unique_ptr<FileSys::StorageBackend> backend;
+
+    void Read(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        u64 offset = rp.Pop<u64>();
+        u64 length = rp.Pop<u64>();
+
+        LOG_DEBUG(Service, "called, offset=0x%llx, length=0x%llx", offset, length);
+
+        auto descriptor = ctx.BufferDescriptorB()[0];
+        std::vector<u8> output(length);
+
+        ResultVal<size_t> res = backend->Read(offset, length, output.data());
+        if (res.Failed()) {
+            IPC::RequestBuilder rb{ctx, 2};
+            rb.Push(res.Code());
+        }
+
+        Memory::WriteBlock(descriptor.Address(), output.data(), descriptor.Size());
+
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+    }
+
+    void Write(Kernel::HLERequestContext& ctx) {
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+        LOG_WARNING(Service, "(STUBBED) called");
+    }
+
+    void Flush(Kernel::HLERequestContext& ctx) {
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+        LOG_WARNING(Service, "(STUBBED) called");
+    }
+
+    void SetSize(Kernel::HLERequestContext& ctx) {
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+        LOG_WARNING(Service, "(STUBBED) called");
+    }
+
+    void GetSize(Kernel::HLERequestContext& ctx) {
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+        LOG_WARNING(Service, "(STUBBED) called");
+    }
+};
+
+FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
+    static const FunctionInfo functions[] = {
+        {1, &FSP_SRV::Initalize, "Initalize"},
+        {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
+        {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"},
+        {1005, &FSP_SRV::GetGlobalAccessLogMode, "GetGlobalAccessLogMode"},
+    };
+    RegisterHandlers(functions);
+}
+
+void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) {
+    IPC::RequestBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
+    IPC::RequestBuilder rb{ctx, 4};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push<u32>(5);
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
+    FileSys::Path path;
+    auto filesystem = OpenFileSystem(Type::RomFS, path);
+    if (filesystem.Failed()) {
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(filesystem.Code());
+        return;
+    }
+
+    auto storage = filesystem.Unwrap()->OpenFile({}, {});
+    if (storage.Failed()) {
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(storage.Code());
+        return;
+    }
+
+    // TODO: What if already opened?
+
+    IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushIpcInterface<IStorage>(std::move(storage.Unwrap()));
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
+    OpenDataStorageByCurrentProcess(ctx);
+}
+
+} // namespace Filesystem
+} // namespace Service

+ 25 - 0
src/core/hle/service/filesystem/fsp_srv.h

@@ -0,0 +1,25 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace FileSystem {
+
+class FSP_SRV final : public ServiceFramework<FSP_SRV> {
+public:
+    FSP_SRV();
+    ~FSP_SRV() = default;
+
+private:
+    void Initalize(Kernel::HLERequestContext& ctx);
+    void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
+    void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
+    void OpenRomStorage(Kernel::HLERequestContext& ctx);
+};
+
+} // namespace Filesystem
+} // namespace Service

+ 2 - 0
src/core/hle/service/service.cpp

@@ -19,6 +19,7 @@
 #include "core/hle/service/aoc/aoc_u.h"
 #include "core/hle/service/apm/apm.h"
 #include "core/hle/service/audio/audio.h"
+#include "core/hle/service/filesystem/filesystem.h"
 #include "core/hle/service/hid/hid.h"
 #include "core/hle/service/lm/lm.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
@@ -172,6 +173,7 @@ void Init() {
     AOC::InstallInterfaces(*SM::g_service_manager);
     APM::InstallInterfaces(*SM::g_service_manager);
     Audio::InstallInterfaces(*SM::g_service_manager);
+    FileSystem::InstallInterfaces(*SM::g_service_manager);
     HID::InstallInterfaces(*SM::g_service_manager);
     LM::InstallInterfaces(*SM::g_service_manager);
     Nvidia::InstallInterfaces(*SM::g_service_manager);