filesystem: Implement basic IStorage functionality.
This commit is contained in:
		| @@ -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
									
								
								src/core/hle/service/filesystem/filesystem.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/core/hle/service/filesystem/filesystem.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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
									
								
								src/core/hle/service/filesystem/filesystem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/core/hle/service/filesystem/filesystem.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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
									
								
								src/core/hle/service/filesystem/fsp_srv.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/core/hle/service/filesystem/fsp_srv.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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
									
								
								src/core/hle/service/filesystem/fsp_srv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/core/hle/service/filesystem/fsp_srv.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user