filesystem: Add support for loading of system archives
This commit is contained in:
		| @@ -77,12 +77,13 @@ static ContentRecordType GetCRTypeFromNCAType(NCAContentType type) { | ||||
|     case NCAContentType::Control: | ||||
|         return ContentRecordType::Control; | ||||
|     case NCAContentType::Data: | ||||
|     case static_cast<NCAContentType>(0x05): ///< Seems to be used on some system archives | ||||
|         return ContentRecordType::Data; | ||||
|     case NCAContentType::Manual: | ||||
|         // TODO(DarkLordZach): Peek at NCA contents to differentiate Manual and Legal. | ||||
|         return ContentRecordType::Manual; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|         UNREACHABLE_MSG("Invalid NCAContentType={:02X}", static_cast<u8>(type)); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,9 @@ | ||||
| #include <memory> | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/romfs_factory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| @@ -17,9 +19,41 @@ RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id) { | ||||
|     // TODO(DarkLordZach): Use title id. | ||||
| ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess() { | ||||
|     return MakeResult<VirtualFile>(file); | ||||
| } | ||||
|  | ||||
| ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) { | ||||
|     switch (storage) { | ||||
|     case StorageId::NandSystem: { | ||||
|         const auto res = Service::FileSystem::GetSystemNANDContents()->GetEntry(title_id, type); | ||||
|         if (res == nullptr) { | ||||
|             // TODO(DarkLordZach): Find the right error code to use here | ||||
|             return ResultCode(-1); | ||||
|         } | ||||
|         const auto romfs = res->GetRomFS(); | ||||
|         if (romfs == nullptr) { | ||||
|             // TODO(DarkLordZach): Find the right error code to use here | ||||
|             return ResultCode(-1); | ||||
|         } | ||||
|         return MakeResult<VirtualFile>(romfs); | ||||
|     } | ||||
|     case StorageId::NandUser: { | ||||
|         const auto res = Service::FileSystem::GetUserNANDContents()->GetEntry(title_id, type); | ||||
|         if (res == nullptr) { | ||||
|             // TODO(DarkLordZach): Find the right error code to use here | ||||
|             return ResultCode(-1); | ||||
|         } | ||||
|         const auto romfs = res->GetRomFS(); | ||||
|         if (romfs == nullptr) { | ||||
|             // TODO(DarkLordZach): Find the right error code to use here | ||||
|             return ResultCode(-1); | ||||
|         } | ||||
|         return MakeResult<VirtualFile>(romfs); | ||||
|     } | ||||
|     default: | ||||
|         UNIMPLEMENTED_MSG("Unimplmented storage_id={:02X}", static_cast<u8>(storage)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace FileSys | ||||
|   | ||||
| @@ -11,12 +11,22 @@ | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| enum class StorageId : u8 { | ||||
|     None = 0, | ||||
|     Host = 1, | ||||
|     GameCard = 2, | ||||
|     NandSystem = 3, | ||||
|     NandUser = 4, | ||||
|     SdCard = 5, | ||||
| }; | ||||
|  | ||||
| /// File system interface to the RomFS archive | ||||
| class RomFSFactory { | ||||
| public: | ||||
|     explicit RomFSFactory(Loader::AppLoader& app_loader); | ||||
|  | ||||
|     ResultVal<VirtualFile> Open(u64 title_id); | ||||
|     ResultVal<VirtualFile> OpenCurrentProcess(); | ||||
|     ResultVal<VirtualFile> Open(u64 title_id, StorageId storage, ContentRecordType type); | ||||
|  | ||||
| private: | ||||
|     VirtualFile file; | ||||
|   | ||||
| @@ -256,15 +256,28 @@ ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) { | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | ||||
| ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id) { | ||||
|     LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}", title_id); | ||||
| ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() { | ||||
|     LOG_TRACE(Service_FS, "Opening RomFS for current process"); | ||||
|  | ||||
|     if (romfs_factory == nullptr) { | ||||
|         // TODO(bunnei): Find a better error code for this | ||||
|         return ResultCode(-1); | ||||
|     } | ||||
|  | ||||
|     return romfs_factory->Open(title_id); | ||||
|     return romfs_factory->OpenCurrentProcess(); | ||||
| } | ||||
|  | ||||
| ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id, | ||||
|                                           FileSys::ContentRecordType type) { | ||||
|     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)); | ||||
|  | ||||
|     if (romfs_factory == nullptr) { | ||||
|         // TODO(bunnei): Find a better error code for this | ||||
|         return ResultCode(-1); | ||||
|     } | ||||
|  | ||||
|     return romfs_factory->Open(title_id, storage_id, type); | ||||
| } | ||||
|  | ||||
| ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, | ||||
|   | ||||
| @@ -27,7 +27,9 @@ ResultCode RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory) | ||||
| ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory); | ||||
| ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); | ||||
|  | ||||
| ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id); | ||||
| 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, | ||||
|                                             FileSys::SaveDataDescriptor save_struct); | ||||
| ResultVal<FileSys::VirtualDir> OpenSDMC(); | ||||
|   | ||||
| @@ -23,15 +23,6 @@ | ||||
|  | ||||
| namespace Service::FileSystem { | ||||
|  | ||||
| enum class StorageId : u8 { | ||||
|     None = 0, | ||||
|     Host = 1, | ||||
|     GameCard = 2, | ||||
|     NandSystem = 3, | ||||
|     NandUser = 4, | ||||
|     SdCard = 5, | ||||
| }; | ||||
|  | ||||
| class IStorage final : public ServiceFramework<IStorage> { | ||||
| public: | ||||
|     explicit IStorage(FileSys::VirtualFile backend_) | ||||
| @@ -467,7 +458,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | ||||
|         {110, nullptr, "OpenContentStorageFileSystem"}, | ||||
|         {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, | ||||
|         {201, nullptr, "OpenDataStorageByProgramId"}, | ||||
|         {202, nullptr, "OpenDataStorageByDataId"}, | ||||
|         {202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"}, | ||||
|         {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"}, | ||||
|         {400, nullptr, "OpenDeviceOperator"}, | ||||
|         {500, nullptr, "OpenSdCardDetectionEventNotifier"}, | ||||
| @@ -580,7 +571,7 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | ||||
| void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_FS, "called"); | ||||
|  | ||||
|     auto romfs = OpenRomFS(Core::System::GetInstance().CurrentProcess()->program_id); | ||||
|     auto romfs = OpenRomFSCurrentProcess(); | ||||
|     if (romfs.Failed()) { | ||||
|         // TODO (bunnei): Find the right error code to use here | ||||
|         LOG_CRITICAL(Service_FS, "no file system interface available!"); | ||||
| @@ -596,10 +587,37 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | ||||
|     rb.PushIpcInterface<IStorage>(std::move(storage)); | ||||
| } | ||||
|  | ||||
| void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto storage_id = rp.PopRaw<FileSys::StorageId>(); | ||||
|     const auto unknown = rp.PopRaw<u32>(); | ||||
|     const auto title_id = rp.PopRaw<u64>(); | ||||
|  | ||||
|     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); | ||||
|     if (data.Failed()) { | ||||
|         // TODO(DarkLordZach): Find the right error code to use here | ||||
|         LOG_ERROR(Service_FS, | ||||
|                   "could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, | ||||
|                   static_cast<u8>(storage_id)); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultCode(-1)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     IStorage storage(std::move(data.Unwrap())); | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<IStorage>(std::move(storage)); | ||||
| } | ||||
|  | ||||
| void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|  | ||||
|     auto storage_id = rp.PopRaw<StorageId>(); | ||||
|     auto storage_id = rp.PopRaw<FileSys::StorageId>(); | ||||
|     auto title_id = rp.PopRaw<u64>(); | ||||
|  | ||||
|     LOG_DEBUG(Service_FS, "called with storage_id={:02X}, title_id={:016X}", | ||||
|   | ||||
| @@ -25,6 +25,7 @@ private: | ||||
|     void MountSaveData(Kernel::HLERequestContext& ctx); | ||||
|     void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | ||||
|     void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); | ||||
|     void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); | ||||
|     void OpenRomStorage(Kernel::HLERequestContext& ctx); | ||||
|  | ||||
|     FileSys::VirtualFile romfs; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zach Hilman
					Zach Hilman