Compare commits

...

7 Commits

Author SHA1 Message Date
Zach Hilman
187d5cb60c fsp_srv: Add accessors for content storage and image filesystems 2019-10-01 09:49:00 -04:00
Zach Hilman
8f05e2258b fsp_srv: Add event notifier commands
Allow game to detect insertion.
2019-10-01 09:48:30 -04:00
Zach Hilman
5b3b49b353 fsp_srv: Add additional save data commands
Includes system and readonly variants
2019-10-01 09:47:46 -04:00
Zach Hilman
f4aca09678 fsp_srv: Add BIS accessor commands 2019-10-01 09:46:39 -04:00
Zach Hilman
03c3564af5 fsp_srv: Reduce constructor arguments 2019-10-01 09:06:54 -04:00
Zach Hilman
4f163cf77f vfs: Add readonly layer class
Takes a VirtualDir/File and makes its API read only.
2019-10-01 09:04:10 -04:00
Zach Hilman
a0702e2db3 card_image: Implement system update commands in XCI 2019-09-22 21:52:03 -04:00
7 changed files with 652 additions and 41 deletions

View File

@@ -86,6 +86,8 @@ add_library(core STATIC
file_sys/vfs_offset.h
file_sys/vfs_real.cpp
file_sys/vfs_real.h
file_sys/vfs_ro_layer.cpp
file_sys/vfs_ro_layer.h
file_sys/vfs_static.h
file_sys/vfs_types.h
file_sys/vfs_vector.cpp

View File

@@ -172,6 +172,40 @@ u64 XCI::GetProgramTitleID() const {
return secure_partition->GetProgramTitleID();
}
u32 XCI::GetSystemUpdateVersion() {
const auto update = GetPartition(XCIPartition::Update);
if (update == nullptr)
return 0;
for (const auto& file : update->GetFiles()) {
NCA nca{file, nullptr, 0, keys};
if (nca.GetStatus() != Loader::ResultStatus::Success)
continue;
if (nca.GetType() == NCAContentType::Meta && nca.GetTitleId() == 0x0100000000000816) {
const auto dir = nca.GetSubdirectories()[0];
const auto cnmt = dir->GetFile("SystemUpdate_0100000000000816.cnmt");
if (cnmt == nullptr)
continue;
CNMT cnmt_data{cnmt};
const auto metas = cnmt_data.GetMetaRecords();
if (metas.empty())
continue;
return metas[0].title_version;
}
}
return 0;
}
u64 XCI::GetSystemUpdateTitleID() const {
return 0x0100000000000816;
}
bool XCI::HasProgramNCA() const {
return program != nullptr;
}

View File

@@ -0,0 +1,181 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/file_sys/vfs_ro_layer.h"
namespace FileSys {
ReadOnlyVfsFileLayer::ReadOnlyVfsFileLayer(VirtualFile base) : base(std::move(base)) {}
ReadOnlyVfsFileLayer::~ReadOnlyVfsFileLayer() = default;
std::string ReadOnlyVfsFileLayer::GetName() const {
return base->GetName();
}
std::size_t ReadOnlyVfsFileLayer::GetSize() const {
return base->GetSize();
}
bool ReadOnlyVfsFileLayer::Resize(std::size_t new_size) {
return false;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsFileLayer::GetContainingDirectory() const {
// Make containing read-only to prevent escaping the layer by getting containing and then
// getting this file again.
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetContainingDirectory());
}
bool ReadOnlyVfsFileLayer::IsWritable() const {
return false;
}
bool ReadOnlyVfsFileLayer::IsReadable() const {
return base->IsReadable();
}
std::size_t ReadOnlyVfsFileLayer::Read(u8* data, std::size_t length, std::size_t offset) const {
return base->Read(data, length, offset);
}
std::size_t ReadOnlyVfsFileLayer::Write(const u8* data, std::size_t length, std::size_t offset) {
return 0;
}
bool ReadOnlyVfsFileLayer::Rename(std::string_view name) {
return false;
}
std::string ReadOnlyVfsFileLayer::GetFullPath() const {
return base->GetFullPath();
}
ReadOnlyVfsDirectoryLayer::ReadOnlyVfsDirectoryLayer(VirtualDir base) : base(std::move(base)) {}
ReadOnlyVfsDirectoryLayer::~ReadOnlyVfsDirectoryLayer() = default;
std::vector<std::shared_ptr<VfsFile>> ReadOnlyVfsDirectoryLayer::GetFiles() const {
std::vector<VirtualFile> out;
const auto in = base->GetFiles();
std::transform(in.begin(), in.end(), std::back_inserter(out),
[](const VirtualFile& i) { return std::make_shared<ReadOnlyVfsFileLayer>(i); });
return out;
}
std::vector<std::shared_ptr<VfsDirectory>> ReadOnlyVfsDirectoryLayer::GetSubdirectories() const {
std::vector<VirtualDir> out;
const auto in = base->GetSubdirectories();
std::transform(in.begin(), in.end(), std::back_inserter(out), [](const VirtualDir& i) {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(i);
});
return out;
}
std::string ReadOnlyVfsDirectoryLayer::GetName() const {
return base->GetName();
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetParentDirectory() const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetParentDirectory());
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::GetFileRelative(std::string_view path) const {
return std::make_shared<ReadOnlyVfsFileLayer>(base->GetFileRelative(path));
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::GetFileAbsolute(std::string_view path) const {
return std::make_shared<ReadOnlyVfsFileLayer>(base->GetFileAbsolute(path));
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetDirectoryRelative(
std::string_view path) const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetDirectoryRelative(path));
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetDirectoryAbsolute(
std::string_view path) const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetDirectoryAbsolute(path));
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::GetFile(std::string_view name) const {
return std::make_shared<ReadOnlyVfsFileLayer>(base->GetFile(name));
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::GetSubdirectory(
std::string_view name) const {
return std::make_shared<ReadOnlyVfsDirectoryLayer>(base->GetSubdirectory(name));
}
bool ReadOnlyVfsDirectoryLayer::IsRoot() const {
return base->IsRoot();
}
std::size_t ReadOnlyVfsDirectoryLayer::GetSize() const {
return base->GetSize();
}
bool ReadOnlyVfsDirectoryLayer::Copy(std::string_view src, std::string_view dest) {
return false;
}
std::string ReadOnlyVfsDirectoryLayer::GetFullPath() const {
return base->GetFullPath();
}
bool ReadOnlyVfsDirectoryLayer::IsWritable() const {
return false;
}
bool ReadOnlyVfsDirectoryLayer::IsReadable() const {
return base->IsReadable();
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::CreateSubdirectory(std::string_view name) {
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::CreateFile(std::string_view name) {
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::CreateFileAbsolute(std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsFile> ReadOnlyVfsDirectoryLayer::CreateFileRelative(std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::CreateDirectoryAbsolute(
std::string_view path) {
return nullptr;
}
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectoryLayer::CreateDirectoryRelative(
std::string_view path) {
return nullptr;
}
bool ReadOnlyVfsDirectoryLayer::DeleteSubdirectory(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::DeleteSubdirectoryRecursive(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::CleanSubdirectoryRecursive(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::DeleteFile(std::string_view name) {
return false;
}
bool ReadOnlyVfsDirectoryLayer::Rename(std::string_view name) {
return false;
}
} // namespace FileSys

View File

@@ -0,0 +1,73 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "core/file_sys/vfs.h"
namespace FileSys {
// Class that wraps a VfsFile making it read-only
class ReadOnlyVfsFileLayer : public VfsFile {
public:
explicit ReadOnlyVfsFileLayer(VirtualFile base);
~ReadOnlyVfsFileLayer() override;
std::string GetName() const override;
std::size_t GetSize() const override;
bool Resize(std::size_t new_size) override;
std::shared_ptr<VfsDirectory> GetContainingDirectory() const override;
bool IsWritable() const override;
bool IsReadable() const override;
std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override;
std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override;
bool Rename(std::string_view name) override;
std::string GetFullPath() const override;
private:
VirtualFile base;
};
// Class that wraps a VfsDirectory making it and its children read only.
class ReadOnlyVfsDirectoryLayer : public ReadOnlyVfsDirectory {
public:
explicit ReadOnlyVfsDirectoryLayer(VirtualDir base);
~ReadOnlyVfsDirectoryLayer() override;
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
std::string GetName() const override;
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
std::shared_ptr<VfsFile> GetFileRelative(std::string_view path) const override;
std::shared_ptr<VfsFile> GetFileAbsolute(std::string_view path) const override;
std::shared_ptr<VfsDirectory> GetDirectoryRelative(std::string_view path) const override;
std::shared_ptr<VfsDirectory> GetDirectoryAbsolute(std::string_view path) const override;
std::shared_ptr<VfsFile> GetFile(std::string_view name) const override;
std::shared_ptr<VfsDirectory> GetSubdirectory(std::string_view name) const override;
bool IsRoot() const override;
std::size_t GetSize() const override;
bool Copy(std::string_view src, std::string_view dest) override;
std::string GetFullPath() const override;
bool IsWritable() const override;
bool IsReadable() const override;
std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
std::shared_ptr<VfsFile> CreateFileAbsolute(std::string_view path) override;
std::shared_ptr<VfsFile> CreateFileRelative(std::string_view path) override;
std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path) override;
std::shared_ptr<VfsDirectory> CreateDirectoryRelative(std::string_view path) override;
bool DeleteSubdirectory(std::string_view name) override;
bool DeleteSubdirectoryRecursive(std::string_view name) override;
bool CleanSubdirectoryRecursive(std::string_view name) override;
bool DeleteFile(std::string_view name) override;
bool Rename(std::string_view name) override;
private:
VirtualDir base;
};
} // namespace FileSys

View File

@@ -713,8 +713,7 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
void InstallInterfaces(Core::System& system) {
std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager());
std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager());
std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetReporter())
->InstallAsService(system.ServiceManager());
std::make_shared<FSP_SRV>(system)->InstallAsService(system.ServiceManager());
}
} // namespace Service::FileSystem

View File

@@ -14,17 +14,22 @@
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/directory.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.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"
#include "core/file_sys/vfs_ro_layer.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
#include "core/reporter.h"
@@ -54,6 +59,12 @@ enum class FileSystemType : u8 {
ApplicationPackage = 7,
};
enum class SaveDataOpenMode {
Normal,
ReadOnly,
System,
};
class IStorage final : public ServiceFramework<IStorage> {
public:
explicit IStorage(FileSys::VirtualFile backend_)
@@ -503,14 +514,17 @@ private:
class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
public:
explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space, FileSystemController& fsc)
explicit ISaveDataInfoReader(FileSystemController& fsc,
std::vector<FileSys::SaveDataSpaceId> spaces)
: ServiceFramework("ISaveDataInfoReader"), fsc(fsc) {
static const FunctionInfo functions[] = {
{0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"},
};
RegisterHandlers(functions);
FindAllSaves(space);
for (const auto& space : spaces) {
FindAllSaves(space);
}
}
void ReadSaveDataInfo(Kernel::HLERequestContext& ctx) {
@@ -650,8 +664,31 @@ private:
u64 next_entry_index = 0;
};
FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
: ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) {
class IEventNotifier final : public ServiceFramework<IEventNotifier> {
public:
explicit IEventNotifier(Kernel::SharedPtr<Kernel::ReadableEvent> event)
: ServiceFramework{"IEventNotifier"}, event(std::move(event)) {
static const FunctionInfo functions[] = {
{0, &IEventNotifier::GetEventHandle, "GetEventHandle"},
};
RegisterHandlers(functions);
}
private:
void GetEventHandle(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event);
}
Kernel::SharedPtr<Kernel::ReadableEvent> event;
};
FSP_SRV::FSP_SRV(Core::System& system)
: ServiceFramework("fsp-srv"), system(system), fsc(system.GetFileSystemController()) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "OpenFileSystem"},
@@ -660,15 +697,15 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{7, &FSP_SRV::OpenFileSystemWithPatch, "OpenFileSystemWithPatch"},
{8, nullptr, "OpenFileSystemWithId"},
{9, nullptr, "OpenDataFileSystemByApplicationId"},
{11, nullptr, "OpenBisFileSystem"},
{12, nullptr, "OpenBisStorage"},
{13, nullptr, "InvalidateBisCache"},
{11, &FSP_SRV::OpenBisFileSystem, "OpenBisFileSystem"},
{12, &FSP_SRV::OpenBisStorage, "OpenBisStorage"},
{13, &FSP_SRV::InvalidateBisCache, "InvalidateBisCache"},
{17, nullptr, "OpenHostFileSystem"},
{18, &FSP_SRV::OpenSdCardFileSystem, "OpenSdCardFileSystem"},
{19, nullptr, "FormatSdCardFileSystem"},
{21, nullptr, "DeleteSaveDataFileSystem"},
{22, &FSP_SRV::CreateSaveDataFileSystem, "CreateSaveDataFileSystem"},
{23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"},
{23, &FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId, "CreateSaveDataFileSystemBySystemSaveDataId"},
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
{25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
{26, nullptr, "FormatSdCardDryRun"},
@@ -681,12 +718,12 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{34, nullptr, "GetCacheStorageSize"},
{35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
{51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"},
{52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"},
{52, &FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId, "OpenSaveDataFileSystemBySystemSaveDataId"},
{53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"},
{57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"},
{58, nullptr, "ReadSaveDataFileSystemExtraData"},
{59, nullptr, "WriteSaveDataFileSystemExtraData"},
{60, nullptr, "OpenSaveDataInfoReader"},
{60, &FSP_SRV::OpenSaveDataInfoReader, "OpenSaveDataInfoReader"},
{61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"},
{62, nullptr, "OpenCacheStorageList"},
{64, nullptr, "OpenSaveDataInternalStorageFileSystem"},
@@ -699,8 +736,8 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{82, nullptr, "OpenSaveDataTransferManagerVersion2"},
{83, nullptr, "OpenSaveDataTransferProhibiterForCloudBackUp"},
{84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"},
{100, nullptr, "OpenImageDirectoryFileSystem"},
{110, nullptr, "OpenContentStorageFileSystem"},
{100, &FSP_SRV::OpenImageDirectoryFileSystem, "OpenImageDirectoryFileSystem"},
{110, &FSP_SRV::OpenContentStorageFileSystem, "OpenContentStorageFileSystem"},
{120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
{130, nullptr, "OpenCustomStorageFileSystem"},
{200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
@@ -710,8 +747,8 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{204, nullptr, "OpenDataFileSystemByProgramIndex"},
{205, nullptr, "OpenDataStorageByProgramIndex"},
{400, nullptr, "OpenDeviceOperator"},
{500, nullptr, "OpenSdCardDetectionEventNotifier"},
{501, nullptr, "OpenGameCardDetectionEventNotifier"},
{500, &FSP_SRV::OpenSdCardDetectionEventNotifier, "OpenSdCardDetectionEventNotifier"},
{501, &FSP_SRV::OpenGameCardDetectionEventNotifier, "OpenGameCardDetectionEventNotifier"},
{510, nullptr, "OpenSystemDataUpdateEventNotifier"},
{511, nullptr, "NotifySystemDataUpdateEvent"},
{520, nullptr, "SimulateGameCardDetectionEvent"},
@@ -733,7 +770,7 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
{615, nullptr, "QuerySaveDataInternalStorageTotalSize"},
{616, nullptr, "GetSaveDataCommitId"},
{617, nullptr, "UnregisterExternalKey"},
{620, nullptr, "SetSdCardEncryptionSeed"},
{620, &FSP_SRV::SetSdCardEncryptionSeed, "SetSdCardEncryptionSeed"},
{630, nullptr, "SetSdCardAccessibility"},
{631, nullptr, "IsSdCardAccessible"},
{640, nullptr, "IsSignedSystemPartitionOnSdCardValid"},
@@ -762,6 +799,12 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
};
// clang-format on
RegisterHandlers(functions);
auto& kernel{system.Kernel()};
sd_card_detection_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "fsp-srv:SdCardDetectionEvent");
game_card_detection_event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "fsp-srv:GameCardDetectionEvent");
}
FSP_SRV::~FSP_SRV() = default;
@@ -781,11 +824,134 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) {
const auto type = rp.PopRaw<FileSystemType>();
const auto title_id = rp.PopRaw<u64>();
LOG_WARNING(Service_FS, "(STUBBED) called with type={}, title_id={:016X}",
static_cast<u8>(type), title_id);
LOG_DEBUG(Service_FS, "called with type={}, title_id={:016X}", static_cast<u8>(type), title_id);
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(ResultCode(-1));
const auto& prov{system.GetContentProvider()};
FileSys::PatchManager pm{title_id};
FileSys::ContentRecordType cr_type;
switch (type) {
case FileSystemType::ApplicationPackage:
case FileSystemType::Logo:
cr_type = FileSys::ContentRecordType::Program;
break;
case FileSystemType::ContentControl:
cr_type = FileSys::ContentRecordType::Control;
break;
case FileSystemType::ContentManual:
cr_type = FileSys::ContentRecordType::HtmlDocument;
break;
case FileSystemType::ContentMeta:
cr_type = FileSys::ContentRecordType::Meta;
break;
case FileSystemType::ContentData:
cr_type = FileSys::ContentRecordType::Data;
break;
default:
LOG_WARNING(Service_FS, "called with invalid filesystem type!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
const auto& nca{prov.GetEntry(title_id, cr_type)};
if (nca == nullptr) {
LOG_WARNING(Service_FS, "NCA requested doesn't exist in content provider!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
FileSys::VirtualDir dir;
if (type == FileSystemType::ApplicationPackage) {
dir = nca->GetExeFS();
if (dir != nullptr)
dir = pm.PatchExeFS(dir);
} else if (type == FileSystemType::Logo) {
dir = nca->GetSubdirectories()[1];
} else if (type == FileSystemType::ContentControl || type == FileSystemType::ContentManual ||
type == FileSystemType::ContentData) {
if (nca->GetRomFS() != nullptr) {
const auto romfs = pm.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), cr_type);
if (romfs != nullptr)
dir = FileSys::ExtractRomFS(romfs);
}
} else {
dir = nca->GetSubdirectories()[0];
}
if (dir == nullptr) {
LOG_WARNING(Service_FS, "couldn't get requested NCA section!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IFileSystem>(
dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::Host)));
}
void FSP_SRV::OpenBisFileSystem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto partition = rp.PopRaw<FileSys::BisPartitionId>();
LOG_DEBUG(Service_FS, "called with partition_id={:08X}", static_cast<u32>(partition));
auto dir = fsc.OpenBISPartition(partition);
if (dir.Failed()) {
LOG_ERROR(Service_FS,
"Failed to mount BIS filesystem for partition_id={:08X}! Could be invalid "
"argument or uninitialized system.",
static_cast<u32>(partition));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(dir.Code());
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
IFileSystem fs(dir.Unwrap(), SizeGetter::FromStorageId(fsc, FileSys::StorageId::Host));
rb.PushIpcInterface<IFileSystem>(std::move(fs));
}
void FSP_SRV::OpenBisStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto partition = rp.PopRaw<FileSys::BisPartitionId>();
LOG_DEBUG(Service_FS, "called with partition_id={:08X}", static_cast<u32>(partition));
auto file = fsc.OpenBISPartitionStorage(partition);
if (file.Failed()) {
LOG_ERROR(Service_FS,
"Failed to mount BIS storage for partition_id={:08X}! Could be invalid "
"argument or uninitialized system.",
static_cast<u32>(partition));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(file.Code());
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
IStorage fs(file.Unwrap());
rb.PushIpcInterface<IStorage>(std::move(fs));
}
void FSP_SRV::InvalidateBisCache(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
// Exists for SDK compatibility -- We do not emulate a BIS cache.
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) {
@@ -815,44 +981,103 @@ void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_FS, "called.");
void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto save_struct = rp.PopRaw<FileSys::SaveDataDescriptor>();
auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo());
const auto dir = fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandSystem, save_struct);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(dir.Code());
}
namespace {
FileSys::StorageId StorageFromSaveDataSpace(FileSys::SaveDataSpaceId space) {
switch (space) {
case FileSys::SaveDataSpaceId::NandSystem:
case FileSys::SaveDataSpaceId::ProperSystem:
case FileSys::SaveDataSpaceId::TemporaryStorage:
return FileSys::StorageId::NandSystem;
case FileSys::SaveDataSpaceId::NandUser:
return FileSys::StorageId::NandUser;
case FileSys::SaveDataSpaceId::SdCardSystem:
case FileSys::SaveDataSpaceId::SdCardUser:
return FileSys::StorageId::SdCard;
default:
return FileSys::StorageId::None;
}
}
template <SaveDataOpenMode mode>
void OpenSaveDataFileSystemGeneric(Kernel::HLERequestContext& ctx, FileSystemController& fsc) {
IPC::RequestParser rp{ctx};
struct Parameters {
FileSys::SaveDataSpaceId save_data_space_id;
FileSys::SaveDataDescriptor descriptor;
};
IPC::RequestParser rp{ctx};
const auto parameters = rp.PopRaw<Parameters>();
auto dir = fsc.OpenSaveData(parameters.save_data_space_id, parameters.descriptor);
if (dir.Failed()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
return;
}
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;
auto diru = dir.Unwrap();
if (diru == nullptr) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
return;
}
IFileSystem filesystem(std::move(dir.Unwrap()), SizeGetter::FromStorageId(fsc, id));
if constexpr (mode == SaveDataOpenMode::ReadOnly) {
diru = std::make_shared<FileSys::ReadOnlyVfsDirectoryLayer>(diru);
}
IFileSystem filesystem(
std::move(diru),
SizeGetter::FromStorageId(fsc, StorageFromSaveDataSpace(parameters.save_data_space_id)));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
}
} // namespace
void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
OpenSaveDataFileSystemGeneric<SaveDataOpenMode::Normal>(ctx, fsc);
}
void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
OpenSaveDataFileSystem(ctx);
OpenSaveDataFileSystemGeneric<SaveDataOpenMode::ReadOnly>(ctx, fsc);
}
void FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx) {
OpenSaveDataFileSystemGeneric<SaveDataOpenMode::System>(ctx, fsc);
}
void FSP_SRV::OpenSaveDataInfoReader(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISaveDataInfoReader>(
std::make_shared<ISaveDataInfoReader>(fsc, std::vector<FileSys::SaveDataSpaceId>{
FileSys::SaveDataSpaceId::NandSystem,
FileSys::SaveDataSpaceId::NandUser,
FileSys::SaveDataSpaceId::TemporaryStorage,
FileSys::SaveDataSpaceId::SdCardUser,
}));
}
void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) {
@@ -862,7 +1087,64 @@ 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, fsc));
rb.PushIpcInterface<ISaveDataInfoReader>(
std::make_shared<ISaveDataInfoReader>(fsc, std::vector<FileSys::SaveDataSpaceId>{space}));
}
void FSP_SRV::OpenImageDirectoryFileSystem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto storage = rp.PopRaw<ImageDirectoryId>();
LOG_DEBUG(Service_FS, "called, storage={:08X}", static_cast<u32>(storage));
auto dir = fsc.GetImageDirectory(storage);
if (dir == nullptr) {
LOG_ERROR(Service_FS, "The image directory requested was invalid!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IFileSystem>(
std::move(dir), SizeGetter::FromStorageId(fsc, storage == ImageDirectoryId::NAND
? FileSys::StorageId::NandUser
: FileSys::StorageId::SdCard)));
}
void FSP_SRV::OpenContentStorageFileSystem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto storage = rp.PopRaw<ContentStorageId>();
LOG_DEBUG(Service_FS, "called, storage={:08X}", static_cast<u32>(storage));
auto dir = fsc.GetContentDirectory(storage);
if (dir == nullptr) {
LOG_ERROR(Service_FS, "The content storage requested was invalid!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ERROR_INVALID_ARGUMENT);
return;
}
FileSys::StorageId storage_id = FileSys::StorageId::None;
switch (storage) {
case ContentStorageId::SdCard:
storage_id = FileSys::StorageId::SdCard;
break;
case ContentStorageId::User:
storage_id = FileSys::StorageId::NandUser;
break;
case ContentStorageId::System:
storage_id = FileSys::StorageId::NandSystem;
break;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(
std::make_shared<IFileSystem>(std::move(dir), SizeGetter::FromStorageId(fsc, storage_id)));
}
void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
@@ -961,7 +1243,7 @@ void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called, log='{}'", log);
reporter.SaveFilesystemAccessReport(log_mode, std::move(log));
system.GetReporter().SaveFilesystemAccessReport(log_mode, std::move(log));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -976,4 +1258,30 @@ void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) {
rb.Push(access_log_program_index);
}
void FSP_SRV::OpenSdCardDetectionEventNotifier(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IEventNotifier>(sd_card_detection_event.readable));
}
void FSP_SRV::OpenGameCardDetectionEventNotifier(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface(std::make_shared<IEventNotifier>(game_card_detection_event.readable));
}
void FSP_SRV::SetSdCardEncryptionSeed(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto seed = rp.PopRaw<u128>();
LOG_INFO(Service_FS, "called with seed={:016X}{:016X}", seed[1], seed[0]);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
} // namespace Service::FileSystem

View File

@@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -32,17 +33,25 @@ enum class LogMode : u32 {
class FSP_SRV final : public ServiceFramework<FSP_SRV> {
public:
explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter);
explicit FSP_SRV(Core::System& system);
~FSP_SRV() override;
private:
void SetCurrentProcess(Kernel::HLERequestContext& ctx);
void OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx);
void OpenBisFileSystem(Kernel::HLERequestContext& ctx);
void OpenBisStorage(Kernel::HLERequestContext& ctx);
void InvalidateBisCache(Kernel::HLERequestContext& ctx);
void OpenSdCardFileSystem(Kernel::HLERequestContext& ctx);
void CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx);
void CreateSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx);
void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx);
void OpenSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx);
void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx);
void OpenSaveDataInfoReader(Kernel::HLERequestContext& ctx);
void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx);
void OpenImageDirectoryFileSystem(Kernel::HLERequestContext& ctx);
void OpenContentStorageFileSystem(Kernel::HLERequestContext& ctx);
void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
@@ -50,7 +59,11 @@ private:
void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx);
void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx);
void OpenSdCardDetectionEventNotifier(Kernel::HLERequestContext& ctx);
void OpenGameCardDetectionEventNotifier(Kernel::HLERequestContext& ctx);
void SetSdCardEncryptionSeed(Kernel::HLERequestContext& ctx);
Core::System& system;
FileSystemController& fsc;
FileSys::VirtualFile romfs;
@@ -58,7 +71,8 @@ private:
u32 access_log_program_index = 0;
LogMode log_mode = LogMode::LogToSdCard;
const Core::Reporter& reporter;
Kernel::EventPair sd_card_detection_event;
Kernel::EventPair game_card_detection_event;
};
} // namespace Service::FileSystem