This commit is contained in:
Tobias 2024-03-01 00:32:06 -08:00 committed by GitHub
commit e509ba4ea4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 2535 additions and 209 deletions

View File

@ -46,6 +46,7 @@ add_library(common STATIC
dynamic_library.cpp
dynamic_library.h
elf.h
enum_util.h
error.cpp
error.h
expected.h
@ -148,6 +149,7 @@ add_library(common STATIC
tiny_mt.h
tree.h
typed_address.h
typed_storage.h
uint128.h
unique_function.h
uuid.cpp

22
src/common/enum_util.h Normal file
View File

@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <type_traits>
namespace Common {
template <typename Enum>
requires std::is_enum<Enum>::value
constexpr typename std::underlying_type<Enum>::type ToUnderlying(Enum e) {
return static_cast<typename std::underlying_type<Enum>::type>(e);
}
template <typename Enum>
requires std::is_enum<Enum>::value
constexpr Enum FromUnderlying(typename std::underlying_type<Enum>::type v) {
return static_cast<Enum>(v);
}
} // namespace Common

View File

@ -6,27 +6,9 @@
#include <type_traits>
#include "common/assert.h"
#include "common/typed_storage.h"
namespace Common {
namespace detail {
template <typename T, size_t Size, size_t Align>
struct TypedStorageImpl {
alignas(Align) u8 storage_[Size];
};
} // namespace detail
template <typename T>
using TypedStorage = detail::TypedStorageImpl<T, sizeof(T), alignof(T)>;
template <typename T>
static constexpr T* GetPointer(TypedStorage<T>& ts) {
return static_cast<T*>(static_cast<void*>(std::addressof(ts.storage_)));
}
template <typename T>
static constexpr const T* GetPointer(const TypedStorage<T>& ts) {
return static_cast<const T*>(static_cast<const void*>(std::addressof(ts.storage_)));
}
namespace impl {

View File

@ -84,6 +84,48 @@ namespace Common {
return f;
}
consteval bool IsLittleEndian() {
return std::endian::native == std::endian::little;
}
consteval bool IsBigEndian() {
return std::endian::native == std::endian::big;
}
static_assert(IsLittleEndian() ^ IsBigEndian());
template <std::unsigned_integral U>
U SwapEndian(const U u) {
constexpr std::size_t BitSizeU8 = 8;
if constexpr (sizeof(U) * BitSizeU8 == 64) {
return swap64(u);
} else if constexpr (sizeof(U) * BitSizeU8 == 32) {
return swap32(u);
} else if constexpr (sizeof(U) * BitSizeU8 == 16) {
return swap16(u);
} else if constexpr (sizeof(U) * BitSizeU8 == 8) {
return u;
} else {
static_assert(!std::is_same<U, U>::value);
}
}
template <std::integral T>
constexpr T ConvertToLittleEndian(const T val) {
using U = typename std::make_unsigned<T>::type;
if constexpr (IsBigEndian()) {
return static_cast<T>(SwapEndian<U>(static_cast<U>(val)));
} else {
static_assert(IsLittleEndian());
return static_cast<T>(static_cast<U>(val));
}
}
template <std::integral T>
constexpr T LoadLittleEndian(const T* ptr) {
return ConvertToLittleEndian<T>(*ptr);
}
} // Namespace Common
template <typename T, typename F>

View File

@ -0,0 +1,96 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <utility>
#include "common/common_funcs.h"
namespace Common {
template <typename T, size_t Size = sizeof(T), size_t Align = alignof(T)>
struct TypedStorage {
typename std::aligned_storage<Size, Align>::type _storage;
};
template <typename T>
static T* GetPointer(TypedStorage<T>& ts) {
return std::launder(reinterpret_cast<T*>(std::addressof(ts._storage)));
}
template <typename T>
static const T* GetPointer(const TypedStorage<T>& ts) {
return std::launder(reinterpret_cast<const T*>(std::addressof(ts._storage)));
}
template <typename T>
static T& GetReference(TypedStorage<T>& ts) {
return *GetPointer(ts);
}
template <typename T>
static const T& GetReference(const TypedStorage<T>& ts) {
return *GetPointer(ts);
}
namespace Impl {
template <typename T>
static T* GetPointerForConstructAt(TypedStorage<T>& ts) {
return reinterpret_cast<T*>(std::addressof(ts._storage));
}
} // namespace Impl
template <typename T, typename... Args>
static T* ConstructAt(TypedStorage<T>& ts, Args&&... args) {
return std::construct_at(Impl::GetPointerForConstructAt(ts), std::forward<Args>(args)...);
}
template <typename T>
static void DestroyAt(TypedStorage<T>& ts) {
return std::destroy_at(GetPointer(ts));
}
namespace Impl {
template <typename T>
class TypedStorageGuard {
YUZU_NON_COPYABLE(TypedStorageGuard);
private:
TypedStorage<T>& m_ts;
bool m_active;
public:
template <typename... Args>
TypedStorageGuard(TypedStorage<T>& ts, Args&&... args) : m_ts(ts), m_active(true) {
ConstructAt(m_ts, std::forward<Args>(args)...);
}
~TypedStorageGuard() {
if (m_active) {
DestroyAt(m_ts);
}
}
void Cancel() {
m_active = false;
}
TypedStorageGuard(TypedStorageGuard&& rhs) : m_ts(rhs.m_ts), m_active(rhs.m_active) {
rhs.Cancel();
}
TypedStorageGuard& operator=(TypedStorageGuard&& rhs) = delete;
};
} // namespace Impl
template <typename T, typename... Args>
static Impl::TypedStorageGuard<T> ConstructAtGuarded(TypedStorage<T>& ts, Args&&... args) {
return Impl::TypedStorageGuard<T>(ts, std::forward<Args>(args)...);
}
} // namespace Common

View File

@ -51,6 +51,7 @@ add_library(core STATIC
file_sys/control_metadata.cpp
file_sys/control_metadata.h
file_sys/errors.h
file_sys/fs_common.h
file_sys/fs_directory.h
file_sys/fs_file.h
file_sys/fs_filesystem.h
@ -58,6 +59,7 @@ add_library(core STATIC
file_sys/fs_operate_range.h
file_sys/fs_path.h
file_sys/fs_path_utility.h
file_sys/fs_program_index_map_info.h
file_sys/fs_save_data_types.h
file_sys/fs_string_util.h
file_sys/fsa/fs_i_directory.h
@ -65,9 +67,21 @@ add_library(core STATIC
file_sys/fsa/fs_i_filesystem.h
file_sys/fsmitm_romfsbuild.cpp
file_sys/fsmitm_romfsbuild.h
file_sys/fssrv/fssrv_program_registry_impl.cpp
file_sys/fssrv/fssrv_program_registry_impl.h
file_sys/fssrv/fssrv_program_registry_service.cpp
file_sys/fssrv/fssrv_program_registry_service.h
file_sys/fssrv/fssrv_sf_path.h
file_sys/fssrv/impl/fssrv_access_control.cpp
file_sys/fssrv/impl/fssrv_access_control.h
file_sys/fssrv/impl/fssrv_access_control_bits.h
file_sys/fssrv/impl/fssrv_program_index_map_info_manager.h
file_sys/fssrv/impl/fssrv_program_info.cpp
file_sys/fssrv/impl/fssrv_program_info.h
file_sys/fssrv/impl/fssrv_program_registry_manager.cpp
file_sys/fssrv/impl/fssrv_program_registry_manager.h
file_sys/fssrv/impl/fssrv_save_data_properties.h
file_sys/fssystem/fs_i_storage.h
file_sys/fssystem/fs_types.h
file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp
file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h
file_sys/fssystem/fssystem_aes_ctr_storage.cpp
@ -496,33 +510,33 @@ add_library(core STATIC
hle/service/apm/apm_controller.h
hle/service/apm/apm_interface.cpp
hle/service/apm/apm_interface.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/audio_controller.cpp
hle/service/audio/audio_controller.h
hle/service/audio/audio_device.cpp
hle/service/audio/audio_device.h
hle/service/audio/audio_in_manager.cpp
hle/service/audio/audio_in_manager.h
hle/service/audio/audio_in.cpp
hle/service/audio/audio_in.h
hle/service/audio/audio_out_manager.cpp
hle/service/audio/audio_out_manager.h
hle/service/audio/audio_in_manager.cpp
hle/service/audio/audio_in_manager.h
hle/service/audio/audio_out.cpp
hle/service/audio/audio_out.h
hle/service/audio/audio_renderer_manager.cpp
hle/service/audio/audio_renderer_manager.h
hle/service/audio/audio_out_manager.cpp
hle/service/audio/audio_out_manager.h
hle/service/audio/audio_renderer.cpp
hle/service/audio/audio_renderer.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/audio_renderer_manager.cpp
hle/service/audio/audio_renderer_manager.h
hle/service/audio/errors.h
hle/service/audio/final_output_recorder_manager_for_applet.cpp
hle/service/audio/final_output_recorder_manager_for_applet.h
hle/service/audio/final_output_recorder_manager.cpp
hle/service/audio/final_output_recorder_manager.h
hle/service/audio/hardware_opus_decoder_manager.cpp
hle/service/audio/hardware_opus_decoder_manager.h
hle/service/audio/final_output_recorder_manager_for_applet.cpp
hle/service/audio/final_output_recorder_manager_for_applet.h
hle/service/audio/hardware_opus_decoder.cpp
hle/service/audio/hardware_opus_decoder.h
hle/service/audio/hardware_opus_decoder_manager.cpp
hle/service/audio/hardware_opus_decoder_manager.h
hle/service/bcat/backend/backend.cpp
hle/service/bcat/backend/backend.h
hle/service/bcat/bcat.cpp
@ -614,14 +628,14 @@ add_library(core STATIC
hle/service/filesystem/fsp/fs_i_filesystem.h
hle/service/filesystem/fsp/fs_i_multi_commit_manager.cpp
hle/service/filesystem/fsp/fs_i_multi_commit_manager.h
hle/service/filesystem/fsp/fs_i_program_registry.cpp
hle/service/filesystem/fsp/fs_i_program_registry.h
hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
hle/service/filesystem/fsp/fs_i_storage.cpp
hle/service/filesystem/fsp/fs_i_storage.h
hle/service/filesystem/fsp/fsp_ldr.cpp
hle/service/filesystem/fsp/fsp_ldr.h
hle/service/filesystem/fsp/fsp_pr.cpp
hle/service/filesystem/fsp/fsp_pr.h
hle/service/filesystem/fsp/fsp_srv.cpp
hle/service/filesystem/fsp/fsp_srv.h
hle/service/filesystem/fsp/fsp_types.h
@ -891,12 +905,12 @@ add_library(core STATIC
hle/service/olsc/daemon_controller.h
hle/service/olsc/native_handle_holder.cpp
hle/service/olsc/native_handle_holder.h
hle/service/olsc/olsc.cpp
hle/service/olsc/olsc.h
hle/service/olsc/olsc_service_for_application.cpp
hle/service/olsc/olsc_service_for_application.h
hle/service/olsc/olsc_service_for_system_service.cpp
hle/service/olsc/olsc_service_for_system_service.h
hle/service/olsc/olsc.cpp
hle/service/olsc/olsc.h
hle/service/olsc/remote_storage_controller.cpp
hle/service/olsc/remote_storage_controller.h
hle/service/olsc/transfer_task_list_controller.cpp
@ -920,10 +934,10 @@ add_library(core STATIC
hle/service/os/mutex.h
hle/service/pcie/pcie.cpp
hle/service/pcie/pcie.h
hle/service/pctl/parental_control_service_factory.cpp
hle/service/pctl/parental_control_service_factory.h
hle/service/pctl/parental_control_service.cpp
hle/service/pctl/parental_control_service.h
hle/service/pctl/parental_control_service_factory.cpp
hle/service/pctl/parental_control_service_factory.h
hle/service/pctl/pctl.cpp
hle/service/pctl/pctl.h
hle/service/pctl/pctl_results.h
@ -935,14 +949,14 @@ add_library(core STATIC
hle/service/prepo/prepo.cpp
hle/service/prepo/prepo.h
hle/service/psc/ovln/ovln_types.h
hle/service/psc/ovln/receiver_service.cpp
hle/service/psc/ovln/receiver_service.h
hle/service/psc/ovln/receiver.cpp
hle/service/psc/ovln/receiver.h
hle/service/psc/ovln/sender_service.cpp
hle/service/psc/ovln/sender_service.h
hle/service/psc/ovln/receiver_service.cpp
hle/service/psc/ovln/receiver_service.h
hle/service/psc/ovln/sender.cpp
hle/service/psc/ovln/sender.h
hle/service/psc/ovln/sender_service.cpp
hle/service/psc/ovln/sender_service.h
hle/service/psc/pm_control.cpp
hle/service/psc/pm_control.h
hle/service/psc/pm_module.cpp

View File

@ -22,6 +22,7 @@
#include "core/device_memory.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/fssrv/fssrv_program_registry_impl.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs_factory.h"
@ -137,8 +138,9 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system},
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
: kernel{system}, fs_controller{system}, program_registry{system}, hid_core{},
room_network{}, cpu_manager{system}, reporter{system}, applet_manager{system},
frontend_applets{system}, profile_manager{} {}
void Initialize(System& system) {
device_memory = std::make_unique<Core::DeviceMemory>();
@ -464,7 +466,7 @@ struct System::Impl {
applet_manager.Reset();
services.reset();
service_manager.reset();
fs_controller.Reset();
program_registry.Reset();
cheat_engine.reset();
telemetry_session.reset();
core_timing.ClearPendingEvents();
@ -548,6 +550,7 @@ struct System::Impl {
/// ContentProviderUnion instance
std::unique_ptr<FileSys::ContentProviderUnion> content_provider;
Service::FileSystem::FileSystemController fs_controller;
FileSys::FsSrv::ProgramRegistryImpl program_registry;
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
std::unique_ptr<Tegra::GPU> gpu_core;
@ -931,6 +934,14 @@ void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
impl->content_provider->ClearSlot(slot);
}
FileSys::FsSrv::ProgramRegistryImpl& System::GetProgramRegistry() {
return impl->program_registry;
}
const FileSys::FsSrv::ProgramRegistryImpl& System::GetProgramRegistry() const {
return impl->program_registry;
}
const Reporter& System::GetReporter() const {
return impl->reporter;
}

View File

@ -24,6 +24,10 @@ class ContentProvider;
class ContentProviderUnion;
enum class ContentProviderUnionSlot;
class VfsFilesystem;
namespace FsSrv {
class ProgramRegistryImpl;
}
} // namespace FileSys
namespace Kernel {
@ -373,6 +377,9 @@ public:
void ClearContentProvider(FileSys::ContentProviderUnionSlot slot);
[[nodiscard]] FileSys::FsSrv::ProgramRegistryImpl& GetProgramRegistry();
[[nodiscard]] const FileSys::FsSrv::ProgramRegistryImpl& GetProgramRegistry() const;
[[nodiscard]] const Reporter& GetReporter() const;
[[nodiscard]] Service::Glue::ARPManager& GetARPManager();

View File

@ -16,11 +16,13 @@ constexpr Result ResultPortSdCardNoDevice{ErrorModule::FS, 2001};
constexpr Result ResultNotImplemented{ErrorModule::FS, 3001};
constexpr Result ResultUnsupportedVersion{ErrorModule::FS, 3002};
constexpr Result ResultOutOfRange{ErrorModule::FS, 3005};
constexpr Result ResultAllocationMemoryFailedInProgramRegistryManagerA{ErrorModule::FS, 3258};
constexpr Result ResultAllocationMemoryFailedInFileSystemBuddyHeapA{ErrorModule::FS, 3294};
constexpr Result ResultAllocationMemoryFailedInNcaFileSystemDriverI{ErrorModule::FS, 3341};
constexpr Result ResultAllocationMemoryFailedInNcaReaderA{ErrorModule::FS, 3363};
constexpr Result ResultAllocationMemoryFailedInAesCtrCounterExtendedStorageA{ErrorModule::FS, 3399};
constexpr Result ResultAllocationMemoryFailedInIntegrityRomFsStorageA{ErrorModule::FS, 3412};
constexpr Result ResultAllocationMemoryFailedNew{ErrorModule::FS, 3420};
constexpr Result ResultAllocationMemoryFailedMakeUnique{ErrorModule::FS, 3422};
constexpr Result ResultAllocationMemoryFailedAllocateShared{ErrorModule::FS, 3423};
constexpr Result ResultInvalidAesCtrCounterExtendedEntryOffset{ErrorModule::FS, 4012};
@ -92,6 +94,7 @@ constexpr Result ResultUnsupportedSetSizeForIndirectStorage{ErrorModule::FS, 632
constexpr Result ResultUnsupportedWriteForCompressedStorage{ErrorModule::FS, 6387};
constexpr Result ResultUnsupportedOperateRangeForCompressedStorage{ErrorModule::FS, 6388};
constexpr Result ResultPermissionDenied{ErrorModule::FS, 6400};
constexpr Result ResultProgramInfoNotFound{ErrorModule::FS, 6605};
constexpr Result ResultBufferAllocationFailed{ErrorModule::FS, 6705};
} // namespace FileSys

View File

@ -30,14 +30,6 @@ struct Int64 {
}
};
struct HashSalt {
static constexpr size_t Size = 32;
std::array<u8, Size> value;
};
static_assert(std::is_trivial_v<HashSalt>);
static_assert(sizeof(HashSalt) == HashSalt::Size);
constexpr inline size_t IntegrityMinLayerCount = 2;
constexpr inline size_t IntegrityMaxLayerCount = 7;
constexpr inline size_t IntegrityLayerCountSave = 5;

View File

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_funcs.h"
namespace FileSys {
struct ProgramIndexMapInfo {
u64 program_id;
u64 base_program_id;
u8 program_index;
INSERT_PADDING_BYTES(0xF);
};
static_assert(std::is_trivially_copyable_v<ProgramIndexMapInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(ProgramIndexMapInfo) == 0x20, "ProgramIndexMapInfo has invalid size.");
} // namespace FileSys

View File

@ -7,6 +7,7 @@
#include <fmt/format.h>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
namespace FileSys {
@ -41,6 +42,11 @@ enum class SaveDataRank : u8 {
Secondary = 1,
};
enum class SaveDataFormatType : u8 {
Normal = 0,
NoJournal = 1,
};
struct SaveDataSize {
u64 normal;
u64 journal;
@ -68,28 +74,13 @@ enum class SaveDataMetaType : u8 {
ExtensionContext = 2,
};
struct SaveDataMetaInfo {
u32 size;
SaveDataMetaType type;
INSERT_PADDING_BYTES(0xB);
};
static_assert(std::is_trivially_copyable_v<SaveDataMetaInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataMetaInfo) == 0x10, "SaveDataMetaInfo has invalid size.");
struct HashSalt {
static constexpr size_t Size = 32;
struct SaveDataCreationInfo {
s64 size;
s64 journal_size;
s64 block_size;
u64 owner_id;
u32 flags;
SaveDataSpaceId space_id;
bool pseudo;
INSERT_PADDING_BYTES(0x1A);
std::array<u8, Size> value;
};
static_assert(std::is_trivially_copyable_v<SaveDataCreationInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataCreationInfo) == 0x40, "SaveDataCreationInfo has invalid size.");
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(HashSalt) == HashSalt::Size);
struct SaveDataAttribute {
ProgramId program_id;
@ -149,12 +140,73 @@ constexpr inline bool operator!=(const SaveDataAttribute& lhs, const SaveDataAtt
return !(lhs == rhs);
}
struct SaveDataMetaInfo {
u32 size;
SaveDataMetaType type;
INSERT_PADDING_BYTES(0xB);
};
static_assert(std::is_trivially_copyable_v<SaveDataMetaInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataMetaInfo) == 0x10, "SaveDataMetaInfo has invalid size.");
struct SaveDataInfo {
u64_le save_id_unknown;
FileSys::SaveDataSpaceId space;
FileSys::SaveDataType type;
INSERT_PADDING_BYTES(0x6);
std::array<u8, 0x10> user_id;
u64_le save_id;
u64_le title_id;
u64_le save_image_size;
u16_le index;
FileSys::SaveDataRank rank;
INSERT_PADDING_BYTES(0x25);
};
static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
struct SaveDataCreationInfo {
s64 size;
s64 journal_size;
s64 block_size;
u64 owner_id;
u32 flags;
SaveDataSpaceId space_id;
bool pseudo;
INSERT_PADDING_BYTES(0x1A);
};
static_assert(std::is_trivially_copyable_v<SaveDataCreationInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataCreationInfo) == 0x40, "SaveDataCreationInfo has invalid size.");
const u32 SaveDataCreationInfoV2Version = 0x00010000;
struct SaveDataCreationInfoV2 {
u32 version;
SaveDataAttribute attribute;
s64 size;
s64 journal_size;
s64 block_size;
u64 owner_id;
SaveDataFlags flags;
SaveDataSpaceId space_id;
SaveDataFormatType format_type;
INSERT_PADDING_BYTES(0x2);
bool is_hash_salt_enabled;
INSERT_PADDING_BYTES(0x3);
HashSalt hash_salt;
SaveDataMetaType meta_type;
INSERT_PADDING_BYTES(0x3);
s32 meta_size;
INSERT_PADDING_BYTES(0x164);
};
static_assert(sizeof(SaveDataCreationInfoV2) == 0x200,
"SaveDataCreationInfoV2 has incorrect size.");
struct SaveDataExtraData {
SaveDataAttribute attr;
u64 owner_id;
s64 timestamp;
u32 flags;
INSERT_PADDING_BYTES(4);
INSERT_PADDING_BYTES(0x4);
s64 available_size;
s64 journal_size;
s64 commit_id;
@ -177,12 +229,4 @@ static_assert(sizeof(SaveDataFilter) == 0x48, "SaveDataFilter has invalid size."
static_assert(std::is_trivially_copyable_v<SaveDataFilter>,
"Data type must be trivially copyable.");
struct HashSalt {
static constexpr size_t Size = 32;
std::array<u8, Size> value;
};
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(HashSalt) == HashSalt::Size);
} // namespace FileSys

View File

@ -0,0 +1,77 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fssrv/fssrv_program_registry_impl.h"
#include "core/file_sys/fssrv/fssrv_program_registry_service.h"
namespace FileSys::FsSrv {
// TODO: Move this to a common types file
constexpr u64 InvalidProcessIdProgramRegistry = 0xffffffffffffffffULL;
ProgramRegistryImpl::ProgramRegistryImpl(Core::System& system_)
: m_process_id(InvalidProcessIdProgramRegistry), system{system_},
service_impl{std::make_unique<ProgramRegistryServiceImpl>(
system, initial_program_info, ProgramRegistryServiceImpl::Configuration{})} {}
ProgramRegistryImpl::~ProgramRegistryImpl() {}
Result ProgramRegistryImpl::RegisterProgram(u64 process_id, u64 program_id, u8 storage_id,
const InBuffer<BufferAttr_HipcMapAlias> data,
s64 data_size,
const InBuffer<BufferAttr_HipcMapAlias> desc,
s64 desc_size) {
// Check that we're allowed to register
R_UNLESS(initial_program_info.IsInitialProgram(system, m_process_id), ResultPermissionDenied);
// Check buffer sizes
R_UNLESS(data.size() >= static_cast<size_t>(data_size), ResultInvalidSize);
R_UNLESS(desc.size() >= static_cast<size_t>(desc_size), ResultInvalidSize);
// Register the program
R_RETURN(service_impl->RegisterProgramInfo(process_id, program_id, storage_id, data.data(),
data_size, desc.data(), desc_size));
}
Result ProgramRegistryImpl::RegisterProgramForLoader(
u64 process_id, u64 program_id, std::shared_ptr<FileSys::RomFSFactory> romfs_factory,
std::shared_ptr<FileSys::SaveDataFactory> save_data_factory) {
R_RETURN(service_impl->RegisterProgramInfoForLoader(process_id, program_id, romfs_factory,
save_data_factory));
}
Result ProgramRegistryImpl::UnregisterProgram(u64 process_id) {
// Check that we're allowed to register
R_UNLESS(initial_program_info.IsInitialProgram(system, m_process_id), ResultPermissionDenied);
// Unregister the program
R_RETURN(service_impl->UnregisterProgramInfo(process_id));
}
Result ProgramRegistryImpl::GetProgramInfo(std::shared_ptr<Impl::ProgramInfo>* out,
u64 process_id) {
R_RETURN(service_impl->GetProgramInfo(out, process_id));
}
Result ProgramRegistryImpl::SetCurrentProcess(const Service::ClientProcessId& client_pid) {
// Set our process id
m_process_id = client_pid.pid;
R_SUCCEED();
}
Result ProgramRegistryImpl::SetEnabledProgramVerification(bool enabled) {
// TODO: How to deal with this backwards compat?
ASSERT_MSG(false, "TODO: SetEnabledProgramVerification");
R_THROW(ResultNotImplemented);
}
void ProgramRegistryImpl::Reset() {
initial_program_info = {};
service_impl = std::make_unique<ProgramRegistryServiceImpl>(
system, initial_program_info, ProgramRegistryServiceImpl::Configuration{});
}
} // namespace FileSys::FsSrv

View File

@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_funcs.h"
#include "core/file_sys/fssrv/impl/fssrv_program_info.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hle/result.h"
#include "core/hle/service/cmif_types.h"
namespace Core {
class System;
}
namespace FileSys::FsSrv {
using namespace Service;
class ProgramRegistryServiceImpl;
class ProgramRegistryImpl {
YUZU_NON_COPYABLE(ProgramRegistryImpl);
YUZU_NON_MOVEABLE(ProgramRegistryImpl);
public:
ProgramRegistryImpl(Core::System& system_);
~ProgramRegistryImpl();
Result RegisterProgram(u64 process_id, u64 program_id, u8 storage_id,
const InBuffer<BufferAttr_HipcMapAlias> data, s64 data_size,
const InBuffer<BufferAttr_HipcMapAlias> desc, s64 desc_size);
// This function is not accurate to the Switch, but it is needed to work around current
// limitations in our fs implementation
Result RegisterProgramForLoader(u64 process_id, u64 program_id,
std::shared_ptr<FileSys::RomFSFactory> romfs_factory,
std::shared_ptr<FileSys::SaveDataFactory> save_data_factory);
Result UnregisterProgram(u64 process_id);
Result GetProgramInfo(std::shared_ptr<Impl::ProgramInfo>* out, u64 process_id);
Result SetCurrentProcess(const Service::ClientProcessId& client_pid);
Result SetEnabledProgramVerification(bool enabled);
void Reset();
private:
u64 m_process_id;
Core::System& system;
Impl::InitialProgramInfo initial_program_info{};
std::unique_ptr<ProgramRegistryServiceImpl> service_impl;
};
} // namespace FileSys::FsSrv

View File

@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/file_sys/fssrv/fssrv_program_registry_service.h"
#include "core/file_sys/fssrv/impl/fssrv_program_info.h"
namespace FileSys::FsSrv {
ProgramRegistryServiceImpl::ProgramRegistryServiceImpl(Core::System& system_,
Impl::InitialProgramInfo& program_info,
const Configuration& cfg)
: m_config(cfg),
m_registry_manager(std::make_unique<Impl::ProgramRegistryManager>(system_, program_info)),
m_index_map_info_manager(std::make_unique<Impl::ProgramIndexMapInfoManager>()) {}
Result ProgramRegistryServiceImpl::RegisterProgramInfo(u64 process_id, u64 program_id,
u8 storage_id, const void* data,
s64 data_size, const void* desc,
s64 desc_size) {
R_RETURN(m_registry_manager->RegisterProgram(process_id, program_id, storage_id, data,
data_size, desc, desc_size));
}
Result ProgramRegistryServiceImpl::RegisterProgramInfoForLoader(
u64 process_id, u64 program_id, std::shared_ptr<FileSys::RomFSFactory> romfs_factory,
std::shared_ptr<FileSys::SaveDataFactory> save_data_factory) {
R_RETURN(m_registry_manager->RegisterProgram(process_id, program_id, 0, nullptr, 0, nullptr, 0,
romfs_factory, save_data_factory));
}
Result ProgramRegistryServiceImpl::UnregisterProgramInfo(u64 process_id) {
R_RETURN(m_registry_manager->UnregisterProgram(process_id));
}
Result ProgramRegistryServiceImpl::ResetProgramIndexMapInfo(const ProgramIndexMapInfo* infos,
int count) {
R_RETURN(m_index_map_info_manager->Reset(infos, count));
}
Result ProgramRegistryServiceImpl::GetProgramInfo(std::shared_ptr<Impl::ProgramInfo>* out,
u64 process_id) {
R_RETURN(m_registry_manager->GetProgramInfo(out, process_id));
}
Result ProgramRegistryServiceImpl::GetProgramInfoByProgramId(
std::shared_ptr<Impl::ProgramInfo>* out, u64 program_id) {
R_RETURN(m_registry_manager->GetProgramInfoByProgramId(out, program_id));
}
size_t ProgramRegistryServiceImpl::GetProgramIndexMapInfoCount() {
return m_index_map_info_manager->GetProgramCount();
}
std::optional<ProgramIndexMapInfo> ProgramRegistryServiceImpl::GetProgramIndexMapInfo(
const u64& program_id) {
return m_index_map_info_manager->Get(program_id);
}
u64 ProgramRegistryServiceImpl::GetProgramIdByIndex(const u64& program_id, u8 index) {
return m_index_map_info_manager->GetProgramId(program_id, index);
}
} // namespace FileSys::FsSrv

View File

@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#include "core/file_sys/fs_program_index_map_info.h"
#include "core/file_sys/fssrv/impl/fssrv_program_index_map_info_manager.h"
#include "core/file_sys/fssrv/impl/fssrv_program_registry_manager.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hle/result.h"
namespace Core {
class System;
}
namespace FileSys::FsSrv {
namespace Impl {
class ProgramInfo;
class InitialProgramInfo;
} // namespace Impl
class ProgramRegistryServiceImpl {
public:
struct Configuration {};
ProgramRegistryServiceImpl(Core::System& system_, Impl::InitialProgramInfo& program_info,
const Configuration& cfg);
Result RegisterProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void* data,
s64 data_size, const void* desc, s64 desc_size);
// This function is not accurate to the Switch, but it is needed to work around current
// limitations in our fs implementation
Result RegisterProgramInfoForLoader(
u64 process_id, u64 program_id, std::shared_ptr<FileSys::RomFSFactory> romfs_factory,
std::shared_ptr<FileSys::SaveDataFactory> save_data_factory);
Result UnregisterProgramInfo(u64 process_id);
Result ResetProgramIndexMapInfo(const ProgramIndexMapInfo* infos, int count);
Result GetProgramInfo(std::shared_ptr<Impl::ProgramInfo>* out, u64 process_id);
Result GetProgramInfoByProgramId(std::shared_ptr<Impl::ProgramInfo>* out, u64 program_id);
size_t GetProgramIndexMapInfoCount();
std::optional<ProgramIndexMapInfo> GetProgramIndexMapInfo(const u64& program_id);
u64 GetProgramIdByIndex(const u64& program_id, u8 index);
private:
Configuration m_config;
std::unique_ptr<Impl::ProgramRegistryManager> m_registry_manager;
std::unique_ptr<Impl::ProgramIndexMapInfoManager> m_index_map_info_manager;
};
} // namespace FileSys::FsSrv

View File

@ -0,0 +1,578 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/alignment.h"
#include "common/enum_util.h"
#include "common/swap.h"
#include "core/file_sys/fssrv/impl/fssrv_access_control.h"
namespace FileSys::FsSrv {
namespace Impl {
constexpr u8 LatestFsAccessControlInfoVersion = 1;
AccessControl::AccessControl(const void* data, s64 data_size, const void* desc, s64 desc_size)
: AccessControl(data, data_size, desc, desc_size, DebugFlagDisableMask) {}
AccessControl::AccessControl(const void* fac_data, s64 data_size, const void* fac_desc,
s64 desc_size, u64 flag_mask) {
// If either our data or descriptor is null, give no permissions
if (fac_data == nullptr || fac_desc == nullptr) {
m_flag_bits.emplace(Common::ToUnderlying(AccessControlBits::Bits::None));
return;
}
// Check that data/desc are big enough
ASSERT(data_size >= static_cast<s64>(sizeof(AccessControlDataHeader)));
ASSERT(desc_size >= static_cast<s64>(sizeof(AccessControlDescriptor)));
// Copy in the data/descriptor
AccessControlDataHeader data = {};
AccessControlDescriptor desc = {};
std::memcpy(std::addressof(data), fac_data, sizeof(data));
std::memcpy(std::addressof(desc), fac_desc, sizeof(desc));
// If we don't know how to parse the descriptors, don't
if (data.version != desc.version || data.version < LatestFsAccessControlInfoVersion) {
m_flag_bits.emplace(Common::ToUnderlying(AccessControlBits::Bits::None));
return;
}
// Restrict the descriptor's flag bits
desc.flag_bits &= flag_mask;
// Create our flag bits
m_flag_bits.emplace(data.flag_bits & desc.flag_bits);
// Further check sizes
ASSERT(data_size >= data.content_owner_infos_offset + data.content_owner_infos_size);
ASSERT(desc_size >= static_cast<s64>(sizeof(AccessControlDescriptor) +
desc.content_owner_id_count * sizeof(u64)));
// Read out the content data owner infos
uintptr_t data_start = reinterpret_cast<uintptr_t>(fac_data);
uintptr_t desc_start = reinterpret_cast<uintptr_t>(fac_desc);
if (data.content_owner_infos_size > 0) {
// Get the count
const u32 num_content_owner_infos = Common::LoadLittleEndian<u32>(
reinterpret_cast<u32*>(data_start + data.content_owner_infos_offset));
// Validate the id range
uintptr_t id_start = data_start + data.content_owner_infos_offset + sizeof(u32);
uintptr_t id_end = id_start + sizeof(u64) * num_content_owner_infos;
ASSERT(id_end ==
data_start + data.content_owner_infos_offset + data.content_owner_infos_size);
for (u32 i = 0; i < num_content_owner_infos; ++i) {
// Read the id
const u64 id =
Common::LoadLittleEndian<u64>(reinterpret_cast<u64*>(id_start + i * sizeof(u64)));
// Check that the descriptor allows it
bool allowed = false;
if (desc.content_owner_id_count != 0) {
for (u8 n = 0; n < desc.content_owner_id_count; ++n) {
if (id ==
Common::LoadLittleEndian<u64>(reinterpret_cast<u64*>(
desc_start + sizeof(AccessControlDescriptor) + n * sizeof(u64)))) {
allowed = true;
break;
}
}
} else if ((desc.content_owner_id_min == 0 && desc.content_owner_id_max == 0) ||
(desc.content_owner_id_min <= id && id <= desc.content_owner_id_max)) {
allowed = true;
}
// If the id is allowed, create it
if (allowed) {
if (auto* info = new ContentOwnerInfo(id); info != nullptr) {
m_content_owner_infos.push_front(*info);
}
}
}
}
// Read out the save data owner infos
ASSERT(data_size >= data.save_data_owner_infos_offset + data.save_data_owner_infos_size);
ASSERT(desc_size >= static_cast<s64>(sizeof(AccessControlDescriptor) +
desc.content_owner_id_count * sizeof(u64) +
desc.save_data_owner_id_count * sizeof(u64)));
if (data.save_data_owner_infos_size > 0) {
// Get the count
const u32 num_save_data_owner_infos = Common::LoadLittleEndian<u32>(
reinterpret_cast<u32*>(data_start + data.save_data_owner_infos_offset));
// Get accessibility region
uintptr_t accessibility_start =
data_start + data.save_data_owner_infos_offset + sizeof(u32);
// Validate the id range
uintptr_t id_start =
accessibility_start +
Common::AlignUp(num_save_data_owner_infos * sizeof(Accessibility), alignof(u32));
uintptr_t id_end = id_start + sizeof(u64) * num_save_data_owner_infos;
ASSERT(id_end ==
data_start + data.save_data_owner_infos_offset + data.save_data_owner_infos_size);
for (u32 i = 0; i < num_save_data_owner_infos; ++i) {
// Read the accessibility/id
static_assert(sizeof(Accessibility) == 1);
const Accessibility accessibility =
*reinterpret_cast<Accessibility*>(accessibility_start + i * sizeof(Accessibility));
const u64 id =
Common::LoadLittleEndian<u64>(reinterpret_cast<u64*>(id_start + i * sizeof(u64)));
// Check that the descriptor allows it
bool allowed = false;
if (desc.save_data_owner_id_count != 0) {
for (u8 n = 0; n < desc.save_data_owner_id_count; ++n) {
if (id == Common::LoadLittleEndian<u64>(reinterpret_cast<u64*>(
desc_start + sizeof(AccessControlDescriptor) +
desc.content_owner_id_count * sizeof(u64) + n * sizeof(u64)))) {
allowed = true;
break;
}
}
} else if ((desc.save_data_owner_id_min == 0 && desc.save_data_owner_id_max == 0) ||
(desc.save_data_owner_id_min <= id && id <= desc.save_data_owner_id_max)) {
allowed = true;
}
// If the id is allowed, create it
if (allowed) {
if (auto* info = new SaveDataOwnerInfo(id, accessibility); info != nullptr) {
m_save_data_owner_infos.push_front(*info);
}
}
}
}
}
AccessControl::~AccessControl() {
// Delete all content owner infos
while (!m_content_owner_infos.empty()) {
auto* info = std::addressof(*m_content_owner_infos.rbegin());
m_content_owner_infos.erase(m_content_owner_infos.iterator_to(*info));
delete info;
}
// Delete all save data owner infos
while (!m_save_data_owner_infos.empty()) {
auto* info = std::addressof(*m_save_data_owner_infos.rbegin());
m_save_data_owner_infos.erase(m_save_data_owner_infos.iterator_to(*info));
delete info;
}
}
bool AccessControl::HasContentOwnerId(u64 owner_id) const {
// Check if we have a matching id
for (const auto& info : m_content_owner_infos) {
if (info.GetId() == owner_id) {
return true;
}
}
return false;
}
Accessibility AccessControl::GetAccessibilitySaveDataOwnedBy(u64 owner_id) const {
// Find a matching save data owner
for (const auto& info : m_save_data_owner_infos) {
if (info.GetId() == owner_id) {
return info.GetAccessibility();
}
}
// Default to no accessibility
return Accessibility::MakeAccessibility(false, false);
}
void AccessControl::ListContentOwnerId(s32* out_count, u64* out_owner_ids, s32 offset,
s32 count) const {
// If we have nothing to read, just give the count
if (count == 0) {
*out_count = static_cast<s32>(m_content_owner_infos.size());
return;
}
// Read out the ids
s32 read_offset = 0;
s32 read_count = 0;
if (out_owner_ids != nullptr) {
auto* cur_out = out_owner_ids;
for (const auto& info : m_content_owner_infos) {
// Skip until we get to the desired offset
if (read_offset < offset) {
++read_offset;
continue;
}
// Set the output value
*cur_out = info.GetId();
++cur_out;
++read_count;
// If we've read as many as we can, finish
if (read_count == count) {
break;
}
}
}
// Set the out value
*out_count = read_count;
}
void AccessControl::ListSaveDataOwnedId(s32* out_count, u64* out_owner_ids, s32 offset,
s32 count) const {
// If we have nothing to read, just give the count
if (count == 0) {
*out_count = static_cast<s32>(m_save_data_owner_infos.size());
return;
}
// Read out the ids
s32 read_offset = 0;
s32 read_count = 0;
if (out_owner_ids != nullptr) {
auto* cur_out = out_owner_ids;
for (const auto& info : m_save_data_owner_infos) {
// Skip until we get to the desired offset
if (read_offset < offset) {
++read_offset;
continue;
}
// Set the output value
*cur_out = info.GetId();
++cur_out;
++read_count;
// If we've read as many as we can, finish
if (read_count == count) {
break;
}
}
}
// Set the out value
*out_count = read_count;
}
Accessibility AccessControl::GetAccessibilityFor(AccessibilityType type) const {
switch (type) {
using enum AccessibilityType;
case MountLogo:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountLogoRead(), false);
case MountContentMeta:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentMetaRead(), false);
case MountContentControl:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentControlRead(), false);
case MountContentManual:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentManualRead(), false);
case MountContentData:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentDataRead(), false);
case MountApplicationPackage:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountApplicationPackageRead(),
false);
case MountSaveDataStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountSaveDataStorageRead(),
m_flag_bits->CanMountSaveDataStorageWrite());
case MountContentStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentStorageRead(),
m_flag_bits->CanMountContentStorageWrite());
case MountImageAndVideoStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountImageAndVideoStorageRead(),
m_flag_bits->CanMountImageAndVideoStorageWrite());
case MountCloudBackupWorkStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountCloudBackupWorkStorageRead(),
m_flag_bits->CanMountCloudBackupWorkStorageWrite());
case MountCustomStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountCustomStorage0Read(),
m_flag_bits->CanMountCustomStorage0Write());
case MountBisCalibrationFile:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisCalibrationFileRead(),
m_flag_bits->CanMountBisCalibrationFileWrite());
case MountBisSafeMode:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisSafeModeRead(),
m_flag_bits->CanMountBisSafeModeWrite());
case MountBisUser:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisUserRead(),
m_flag_bits->CanMountBisUserWrite());
case MountBisSystem:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisSystemRead(),
m_flag_bits->CanMountBisSystemWrite());
case MountBisSystemProperEncryption:
return Accessibility::MakeAccessibility(
m_flag_bits->CanMountBisSystemProperEncryptionRead(),
m_flag_bits->CanMountBisSystemProperEncryptionWrite());
case MountBisSystemProperPartition:
return Accessibility::MakeAccessibility(
m_flag_bits->CanMountBisSystemProperPartitionRead(),
m_flag_bits->CanMountBisSystemProperPartitionWrite());
case MountSdCard:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountSdCardRead(),
m_flag_bits->CanMountSdCardWrite());
case MountGameCard:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountGameCardRead(), false);
case MountDeviceSaveData:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountDeviceSaveDataRead(),
m_flag_bits->CanMountDeviceSaveDataWrite());
case MountSystemSaveData:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountSystemSaveDataRead(),
m_flag_bits->CanMountSystemSaveDataWrite());
case MountOthersSaveData:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountOthersSaveDataRead(),
m_flag_bits->CanMountOthersSaveDataWrite());
case MountOthersSystemSaveData:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountOthersSystemSaveDataRead(),
m_flag_bits->CanMountOthersSystemSaveDataWrite());
case OpenBisPartitionBootPartition1Root:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootPartition1RootRead(),
m_flag_bits->CanOpenBisPartitionBootPartition1RootWrite());
case OpenBisPartitionBootPartition2Root:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootPartition2RootRead(),
m_flag_bits->CanOpenBisPartitionBootPartition2RootWrite());
case OpenBisPartitionUserDataRoot:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionUserDataRootRead(),
m_flag_bits->CanOpenBisPartitionUserDataRootWrite());
case OpenBisPartitionBootConfigAndPackage2Part1:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part1Read(),
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part1Write());
case OpenBisPartitionBootConfigAndPackage2Part2:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part2Read(),
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part2Write());
case OpenBisPartitionBootConfigAndPackage2Part3:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part3Read(),
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part3Write());
case OpenBisPartitionBootConfigAndPackage2Part4:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part4Read(),
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part4Write());
case OpenBisPartitionBootConfigAndPackage2Part5:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part5Read(),
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part5Write());
case OpenBisPartitionBootConfigAndPackage2Part6:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part6Read(),
m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part6Write());
case OpenBisPartitionCalibrationBinary:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionCalibrationBinaryRead(),
m_flag_bits->CanOpenBisPartitionCalibrationBinaryWrite());
case OpenBisPartitionCalibrationFile:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionCalibrationFileRead(),
m_flag_bits->CanOpenBisPartitionCalibrationFileWrite());
case OpenBisPartitionSafeMode:
return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionSafeModeRead(),
m_flag_bits->CanOpenBisPartitionSafeModeWrite());
case OpenBisPartitionUser:
return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionUserRead(),
m_flag_bits->CanOpenBisPartitionUserWrite());
case OpenBisPartitionSystem:
return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionSystemRead(),
m_flag_bits->CanOpenBisPartitionSystemWrite());
case OpenBisPartitionSystemProperEncryption:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionSystemProperEncryptionRead(),
m_flag_bits->CanOpenBisPartitionSystemProperEncryptionWrite());
case OpenBisPartitionSystemProperPartition:
return Accessibility::MakeAccessibility(
m_flag_bits->CanOpenBisPartitionSystemProperPartitionRead(),
m_flag_bits->CanOpenBisPartitionSystemProperPartitionWrite());
case OpenSdCardStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanOpenSdCardStorageRead(),
m_flag_bits->CanOpenSdCardStorageWrite());
case OpenGameCardStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanOpenGameCardStorageRead(),
m_flag_bits->CanOpenGameCardStorageWrite());
case MountSystemDataPrivate:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountSystemDataPrivateRead(),
false);
case MountHost:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountHostRead(),
m_flag_bits->CanMountHostWrite());
case MountRegisteredUpdatePartition:
return Accessibility::MakeAccessibility(
m_flag_bits->CanMountRegisteredUpdatePartitionRead(), false);
case MountSaveDataInternalStorage:
return Accessibility::MakeAccessibility(m_flag_bits->CanOpenSaveDataInternalStorageRead(),
m_flag_bits->CanOpenSaveDataInternalStorageWrite());
case MountTemporaryDirectory:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountTemporaryDirectoryRead(),
m_flag_bits->CanMountTemporaryDirectoryWrite());
case MountAllBaseFileSystem:
return Accessibility::MakeAccessibility(m_flag_bits->CanMountAllBaseFileSystemRead(),
m_flag_bits->CanMountAllBaseFileSystemWrite());
case NotMount:
return Accessibility::MakeAccessibility(false, false);
default:
UNREACHABLE();
break;
}
}
bool AccessControl::CanCall(OperationType type) const {
switch (type) {
using enum OperationType;
case InvalidateBisCache:
return m_flag_bits->CanInvalidateBisCache();
case EraseMmc:
return m_flag_bits->CanEraseMmc();
case GetGameCardDeviceCertificate:
return m_flag_bits->CanGetGameCardDeviceCertificate();
case GetGameCardIdSet:
return m_flag_bits->CanGetGameCardIdSet();
case FinalizeGameCardDriver:
return m_flag_bits->CanFinalizeGameCardDriver();
case GetGameCardAsicInfo:
return m_flag_bits->CanGetGameCardAsicInfo();
case CreateSaveData:
return m_flag_bits->CanCreateSaveData();
case DeleteSaveData:
return m_flag_bits->CanDeleteSaveData();
case CreateSystemSaveData:
return m_flag_bits->CanCreateSystemSaveData();
case CreateOthersSystemSaveData:
return m_flag_bits->CanCreateOthersSystemSaveData();
case DeleteSystemSaveData:
return m_flag_bits->CanDeleteSystemSaveData();
case OpenSaveDataInfoReader:
return m_flag_bits->CanOpenSaveDataInfoReader();
case OpenSaveDataInfoReaderForSystem:
return m_flag_bits->CanOpenSaveDataInfoReaderForSystem();
case OpenSaveDataInfoReaderForInternal:
return m_flag_bits->CanOpenSaveDataInfoReaderForInternal();
case OpenSaveDataMetaFile:
return m_flag_bits->CanOpenSaveDataMetaFile();
case SetCurrentPosixTime:
return m_flag_bits->CanSetCurrentPosixTime();
case ReadSaveDataFileSystemExtraData:
return m_flag_bits->CanReadSaveDataFileSystemExtraData();
case SetGlobalAccessLogMode:
return m_flag_bits->CanSetGlobalAccessLogMode();
case SetSpeedEmulationMode:
return m_flag_bits->CanSetSpeedEmulationMode();
case FillBis:
return m_flag_bits->CanFillBis();
case CorruptSaveData:
return m_flag_bits->CanCorruptSaveData();
case CorruptSystemSaveData:
return m_flag_bits->CanCorruptSystemSaveData();
case VerifySaveData:
return m_flag_bits->CanVerifySaveData();
case DebugSaveData:
return m_flag_bits->CanDebugSaveData();
case FormatSdCard:
return m_flag_bits->CanFormatSdCard();
case GetRightsId:
return m_flag_bits->CanGetRightsId();
case RegisterExternalKey:
return m_flag_bits->CanRegisterExternalKey();
case SetEncryptionSeed:
return m_flag_bits->CanSetEncryptionSeed();
case WriteSaveDataFileSystemExtraDataTimeStamp:
return m_flag_bits->CanWriteSaveDataFileSystemExtraDataTimeStamp();
case WriteSaveDataFileSystemExtraDataFlags:
return m_flag_bits->CanWriteSaveDataFileSystemExtraDataFlags();
case WriteSaveDataFileSystemExtraDataCommitId:
return m_flag_bits->CanWriteSaveDataFileSystemExtraDataCommitId();
case WriteSaveDataFileSystemExtraDataAll:
return m_flag_bits->CanWriteSaveDataFileSystemExtraDataAll();
case ExtendSaveData:
return m_flag_bits->CanExtendSaveData();
case ExtendSystemSaveData:
return m_flag_bits->CanExtendSystemSaveData();
case ExtendOthersSystemSaveData:
return m_flag_bits->CanExtendOthersSystemSaveData();
case RegisterUpdatePartition:
return m_flag_bits->CanRegisterUpdatePartition();
case OpenSaveDataTransferManager:
return m_flag_bits->CanOpenSaveDataTransferManager();
case OpenSaveDataTransferManagerVersion2:
return m_flag_bits->CanOpenSaveDataTransferManagerVersion2();
case OpenSaveDataTransferManagerForSaveDataRepair:
return m_flag_bits->CanOpenSaveDataTransferManagerForSaveDataRepair();
case OpenSaveDataTransferManagerForSaveDataRepairTool:
return m_flag_bits->CanOpenSaveDataTransferManagerForSaveDataRepairTool();
case OpenSaveDataTransferProhibiter:
return m_flag_bits->CanOpenSaveDataTransferProhibiter();
case OpenSaveDataMover:
return m_flag_bits->CanOpenSaveDataMover();
case OpenBisWiper:
return m_flag_bits->CanOpenBisWiper();
case ListAccessibleSaveDataOwnerId:
return m_flag_bits->CanListAccessibleSaveDataOwnerId();
case ControlMmcPatrol:
return m_flag_bits->CanControlMmcPatrol();
case OverrideSaveDataTransferTokenSignVerificationKey:
return m_flag_bits->CanOverrideSaveDataTransferTokenSignVerificationKey();
case OpenSdCardDetectionEventNotifier:
return m_flag_bits->CanOpenSdCardDetectionEventNotifier();
case OpenGameCardDetectionEventNotifier:
return m_flag_bits->CanOpenGameCardDetectionEventNotifier();
case OpenSystemDataUpdateEventNotifier:
return m_flag_bits->CanOpenSystemDataUpdateEventNotifier();
case NotifySystemDataUpdateEvent:
return m_flag_bits->CanNotifySystemDataUpdateEvent();
case OpenAccessFailureDetectionEventNotifier:
return m_flag_bits->CanOpenAccessFailureDetectionEventNotifier();
case GetAccessFailureDetectionEvent:
return m_flag_bits->CanGetAccessFailureDetectionEvent();
case IsAccessFailureDetected:
return m_flag_bits->CanIsAccessFailureDetected();
case ResolveAccessFailure:
return m_flag_bits->CanResolveAccessFailure();
case AbandonAccessFailure:
return m_flag_bits->CanAbandonAccessFailure();
case QuerySaveDataInternalStorageTotalSize:
return m_flag_bits->CanQuerySaveDataInternalStorageTotalSize();
case GetSaveDataCommitId:
return m_flag_bits->CanGetSaveDataCommitId();
case SetSdCardAccessibility:
return m_flag_bits->CanSetSdCardAccessibility();
case SimulateDevice:
return m_flag_bits->CanSimulateDevice();
case CreateSaveDataWithHashSalt:
return m_flag_bits->CanCreateSaveDataWithHashSalt();
case RegisterProgramIndexMapInfo:
return m_flag_bits->CanRegisterProgramIndexMapInfo();
case ChallengeCardExistence:
return m_flag_bits->CanChallengeCardExistence();
case CreateOwnSaveData:
return m_flag_bits->CanCreateOwnSaveData();
case DeleteOwnSaveData:
return m_flag_bits->CanDeleteOwnSaveData();
case ReadOwnSaveDataFileSystemExtraData:
return m_flag_bits->CanReadOwnSaveDataFileSystemExtraData();
case ExtendOwnSaveData:
return m_flag_bits->CanExtendOwnSaveData();
case OpenOwnSaveDataTransferProhibiter:
return m_flag_bits->CanOpenOwnSaveDataTransferProhibiter();
case FindOwnSaveDataWithFilter:
return m_flag_bits->CanFindOwnSaveDataWithFilter();
case OpenSaveDataTransferManagerForRepair:
return m_flag_bits->CanOpenSaveDataTransferManagerForRepair();
case SetDebugConfiguration:
return m_flag_bits->CanSetDebugConfiguration();
case OpenDataStorageByPath:
return m_flag_bits->CanOpenDataStorageByPath();
default:
UNREACHABLE();
break;
}
}
} // namespace Impl
} // namespace FileSys::FsSrv

View File

@ -0,0 +1,253 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/enum_util.h"
#include "common/intrusive_list.h"
#include "core/file_sys/fssrv/impl/fssrv_access_control_bits.h"
namespace FileSys::FsSrv::Impl {
struct Accessibility {
u8 value;
constexpr bool CanRead() const {
return value & (1 << 0);
}
constexpr bool CanWrite() const {
return value & (1 << 1);
}
static constexpr Accessibility MakeAccessibility(bool read, bool write) {
return {static_cast<u8>(read * (1 << 0) + write * (1 << 1))};
}
};
static_assert(std::is_trivial<Accessibility>::value);
class ContentOwnerInfo : public Common::IntrusiveListBaseNode<ContentOwnerInfo> {
private:
u64 m_id;
public:
ContentOwnerInfo(u64 id) : m_id(id) {}
u64 GetId() const {
return m_id;
}
};
class SaveDataOwnerInfo : public Common::IntrusiveListBaseNode<SaveDataOwnerInfo> {
private:
u64 m_id;
Accessibility m_accessibility;
public:
SaveDataOwnerInfo(u64 id, Accessibility access) : m_id(id), m_accessibility(access) {}
u64 GetId() const {
return m_id;
}
Accessibility GetAccessibility() const {
return m_accessibility;
}
};
class AccessControl {
public:
enum class AccessibilityType : u32 {
MountLogo,
MountContentMeta,
MountContentControl,
MountContentManual,
MountContentData,
MountApplicationPackage,
MountSaveDataStorage,
MountContentStorage,
MountImageAndVideoStorage,
MountCloudBackupWorkStorage,
MountCustomStorage,
MountBisCalibrationFile,
MountBisSafeMode,
MountBisUser,
MountBisSystem,
MountBisSystemProperEncryption,
MountBisSystemProperPartition,
MountSdCard,
MountGameCard,
MountDeviceSaveData,
MountSystemSaveData,
MountOthersSaveData,
MountOthersSystemSaveData,
OpenBisPartitionBootPartition1Root,
OpenBisPartitionBootPartition2Root,
OpenBisPartitionUserDataRoot,
OpenBisPartitionBootConfigAndPackage2Part1,
OpenBisPartitionBootConfigAndPackage2Part2,
OpenBisPartitionBootConfigAndPackage2Part3,
OpenBisPartitionBootConfigAndPackage2Part4,
OpenBisPartitionBootConfigAndPackage2Part5,
OpenBisPartitionBootConfigAndPackage2Part6,
OpenBisPartitionCalibrationBinary,
OpenBisPartitionCalibrationFile,
OpenBisPartitionSafeMode,
OpenBisPartitionUser,
OpenBisPartitionSystem,
OpenBisPartitionSystemProperEncryption,
OpenBisPartitionSystemProperPartition,
OpenSdCardStorage,
OpenGameCardStorage,
MountSystemDataPrivate,
MountHost,
MountRegisteredUpdatePartition,
MountSaveDataInternalStorage,
MountTemporaryDirectory,
MountAllBaseFileSystem,
NotMount,
Count,
};
enum class OperationType : u32 {
InvalidateBisCache,
EraseMmc,
GetGameCardDeviceCertificate,
GetGameCardIdSet,
FinalizeGameCardDriver,
GetGameCardAsicInfo,
CreateSaveData,
DeleteSaveData,
CreateSystemSaveData,
CreateOthersSystemSaveData,
DeleteSystemSaveData,
OpenSaveDataInfoReader,
OpenSaveDataInfoReaderForSystem,
OpenSaveDataInfoReaderForInternal,
OpenSaveDataMetaFile,
SetCurrentPosixTime,
ReadSaveDataFileSystemExtraData,
SetGlobalAccessLogMode,
SetSpeedEmulationMode,
Debug,
FillBis,
CorruptSaveData,
CorruptSystemSaveData,
VerifySaveData,
DebugSaveData,
FormatSdCard,
GetRightsId,
RegisterExternalKey,
SetEncryptionSeed,
WriteSaveDataFileSystemExtraDataTimeStamp,
WriteSaveDataFileSystemExtraDataFlags,
WriteSaveDataFileSystemExtraDataCommitId,
WriteSaveDataFileSystemExtraDataAll,
ExtendSaveData,
ExtendSystemSaveData,
ExtendOthersSystemSaveData,
RegisterUpdatePartition,
OpenSaveDataTransferManager,
OpenSaveDataTransferManagerVersion2,
OpenSaveDataTransferManagerForSaveDataRepair,
OpenSaveDataTransferManagerForSaveDataRepairTool,
OpenSaveDataTransferProhibiter,
OpenSaveDataMover,
OpenBisWiper,
ListAccessibleSaveDataOwnerId,
ControlMmcPatrol,
OverrideSaveDataTransferTokenSignVerificationKey,
OpenSdCardDetectionEventNotifier,
OpenGameCardDetectionEventNotifier,
OpenSystemDataUpdateEventNotifier,
NotifySystemDataUpdateEvent,
OpenAccessFailureDetectionEventNotifier,
GetAccessFailureDetectionEvent,
IsAccessFailureDetected,
ResolveAccessFailure,
AbandonAccessFailure,
QuerySaveDataInternalStorageTotalSize,
GetSaveDataCommitId,
SetSdCardAccessibility,
SimulateDevice,
CreateSaveDataWithHashSalt,
RegisterProgramIndexMapInfo,
ChallengeCardExistence,
CreateOwnSaveData,
DeleteOwnSaveData,
ReadOwnSaveDataFileSystemExtraData,
ExtendOwnSaveData,
OpenOwnSaveDataTransferProhibiter,
FindOwnSaveDataWithFilter,
OpenSaveDataTransferManagerForRepair,
SetDebugConfiguration,
OpenDataStorageByPath,
Count,
};
#pragma pack(push, 4)
struct AccessControlDataHeader {
u8 version;
u8 reserved[3];
u64 flag_bits;
u32 content_owner_infos_offset;
u32 content_owner_infos_size;
u32 save_data_owner_infos_offset;
u32 save_data_owner_infos_size;
};
struct AccessControlDescriptor {
u8 version;
u8 content_owner_id_count;
u8 save_data_owner_id_count;
u8 reserved;
u64 flag_bits;
u64 content_owner_id_min;
u64 content_owner_id_max;
u64 save_data_owner_id_min;
u64 save_data_owner_id_max;
// u64 content_owner_ids[ContentOwnerIdCount];
// u64 save_data_owner_ids[SaveDataOwnerIdCount];
};
#pragma pack(pop)
static_assert(std::is_trivially_copyable_v<AccessControlDataHeader>,
"Data type must be trivially copyable.");
static_assert(std::is_trivially_copyable_v<AccessControlDescriptor>,
"Data type must be trivially copyable.");
static constexpr u64 AllFlagBitsMask = ~static_cast<u64>(0);
static constexpr u64 DebugFlagDisableMask =
AllFlagBitsMask & ~Common::ToUnderlying(AccessControlBits::Bits::Debug);
public:
AccessControl(const void* data, s64 data_size, const void* desc, s64 desc_size);
AccessControl(const void* data, s64 data_size, const void* desc, s64 desc_size, u64 flag_mask);
~AccessControl();
bool HasContentOwnerId(u64 owner_id) const;
Accessibility GetAccessibilitySaveDataOwnedBy(u64 owner_id) const;
void ListContentOwnerId(s32* out_count, u64* out_owner_ids, s32 offset, s32 count) const;
void ListSaveDataOwnedId(s32* out_count, u64* out_owner_ids, s32 offset, s32 count) const;
Accessibility GetAccessibilityFor(AccessibilityType type) const;
bool CanCall(OperationType type) const;
private:
using ContentOwnerInfoList = Common::IntrusiveListBaseTraits<ContentOwnerInfo>::ListType;
using SaveDataOwnerInfoList = Common::IntrusiveListBaseTraits<SaveDataOwnerInfo>::ListType;
std::optional<AccessControlBits> m_flag_bits;
ContentOwnerInfoList m_content_owner_infos;
SaveDataOwnerInfoList m_save_data_owner_infos;
public:
u64 GetRawFlagBits() const {
return m_flag_bits.value().GetValue();
}
};
} // namespace FileSys::FsSrv::Impl

View File

@ -0,0 +1,268 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/enum_util.h"
namespace FileSys::FsSrv::Impl {
#define YUZU_FSSRV_FOR_EACH_ACCESS_CONTROL_CAPABILITY(HANDLER, _NS_) \
HANDLER(CanAbandonAccessFailure, _NS_::AccessFailureResolution) \
HANDLER(CanChallengeCardExistence, _NS_::GameCard) \
HANDLER(CanControlMmcPatrol, _NS_::None) \
HANDLER(CanCorruptSaveData, _NS_::Debug, _NS_::CorruptSaveData) \
HANDLER(CanCorruptSystemSaveData, _NS_::CorruptSaveData, _NS_::SaveDataManagement, \
_NS_::SaveDataBackUp) \
HANDLER(CanCreateOthersSystemSaveData, _NS_::SaveDataBackUp) \
HANDLER(CanCreateOwnSaveData, _NS_::CreateOwnSaveData) \
HANDLER(CanCreateSaveData, _NS_::CreateSaveData, _NS_::SaveDataBackUp) \
HANDLER(CanCreateSaveDataWithHashSalt, _NS_::None) \
HANDLER(CanCreateSystemSaveData, _NS_::SaveDataBackUp, _NS_::SystemSaveData) \
HANDLER(CanDebugSaveData, _NS_::Debug, _NS_::SaveDataForDebug) \
HANDLER(CanDeleteOwnSaveData, _NS_::CreateOwnSaveData) \
HANDLER(CanDeleteSaveData, _NS_::SaveDataManagement, _NS_::SaveDataBackUp) \
HANDLER(CanDeleteSystemSaveData, _NS_::SystemSaveDataManagement, _NS_::SaveDataBackUp, \
_NS_::SystemSaveData) \
HANDLER(CanEraseMmc, _NS_::BisAllRaw) \
HANDLER(CanExtendOthersSystemSaveData, _NS_::SaveDataBackUp) \
HANDLER(CanExtendOwnSaveData, _NS_::CreateOwnSaveData) \
HANDLER(CanExtendSaveData, _NS_::CreateSaveData, _NS_::SaveDataBackUp) \
HANDLER(CanExtendSystemSaveData, _NS_::SaveDataBackUp, _NS_::SystemSaveData) \
HANDLER(CanFillBis, _NS_::Debug, _NS_::FillBis) \
HANDLER(CanFinalizeGameCardDriver, _NS_::GameCardPrivate) \
HANDLER(CanFindOwnSaveDataWithFilter, _NS_::CreateOwnSaveData) \
HANDLER(CanFormatSdCard, _NS_::FormatSdCard) \
HANDLER(CanGetAccessFailureDetectionEvent, _NS_::AccessFailureResolution) \
HANDLER(CanGetGameCardAsicInfo, _NS_::GameCardPrivate) \
HANDLER(CanGetGameCardDeviceCertificate, _NS_::GameCard) \
HANDLER(CanGetGameCardIdSet, _NS_::GameCard) \
HANDLER(CanGetRightsId, _NS_::GetRightsId) \
HANDLER(CanGetSaveDataCommitId, _NS_::SaveDataTransferVersion2, _NS_::SaveDataBackUp) \
HANDLER(CanInvalidateBisCache, _NS_::BisAllRaw) \
HANDLER(CanIsAccessFailureDetected, _NS_::AccessFailureResolution) \
HANDLER(CanListAccessibleSaveDataOwnerId, _NS_::SaveDataTransferVersion2, \
_NS_::SaveDataTransfer, _NS_::CreateSaveData) \
HANDLER(CanMountAllBaseFileSystemRead, _NS_::None) \
HANDLER(CanMountAllBaseFileSystemWrite, _NS_::None) \
HANDLER(CanMountApplicationPackageRead, _NS_::ContentManager, _NS_::ApplicationInfo) \
HANDLER(CanMountBisCalibrationFileRead, _NS_::BisAllRaw, _NS_::Calibration) \
HANDLER(CanMountBisCalibrationFileWrite, _NS_::BisAllRaw, _NS_::Calibration) \
HANDLER(CanMountBisSafeModeRead, _NS_::BisAllRaw) \
HANDLER(CanMountBisSafeModeWrite, _NS_::BisAllRaw) \
HANDLER(CanMountBisSystemProperEncryptionRead, _NS_::BisAllRaw) \
HANDLER(CanMountBisSystemProperEncryptionWrite, _NS_::BisAllRaw) \
HANDLER(CanMountBisSystemProperPartitionRead, _NS_::BisFileSystem, _NS_::BisAllRaw) \
HANDLER(CanMountBisSystemProperPartitionWrite, _NS_::BisFileSystem, _NS_::BisAllRaw) \
HANDLER(CanMountBisSystemRead, _NS_::BisFileSystem, _NS_::BisAllRaw) \
HANDLER(CanMountBisSystemWrite, _NS_::BisFileSystem, _NS_::BisAllRaw) \
HANDLER(CanMountBisUserRead, _NS_::BisFileSystem, _NS_::BisAllRaw) \
HANDLER(CanMountBisUserWrite, _NS_::BisFileSystem, _NS_::BisAllRaw) \
HANDLER(CanMountCloudBackupWorkStorageRead, _NS_::SaveDataTransferVersion2) \
HANDLER(CanMountCloudBackupWorkStorageWrite, _NS_::SaveDataTransferVersion2) \
HANDLER(CanMountContentControlRead, _NS_::ContentManager, _NS_::ApplicationInfo) \
HANDLER(CanMountContentDataRead, _NS_::ContentManager, _NS_::ApplicationInfo) \
HANDLER(CanMountContentManualRead, _NS_::ContentManager, _NS_::ApplicationInfo) \
HANDLER(CanMountContentMetaRead, _NS_::ContentManager, _NS_::ApplicationInfo) \
HANDLER(CanMountContentStorageRead, _NS_::ContentManager) \
HANDLER(CanMountContentStorageWrite, _NS_::ContentManager) \
HANDLER(CanMountCustomStorage0Read, _NS_::None) \
HANDLER(CanMountCustomStorage0Write, _NS_::None) \
HANDLER(CanMountDeviceSaveDataRead, _NS_::DeviceSaveData, _NS_::SaveDataBackUp) \
HANDLER(CanMountDeviceSaveDataWrite, _NS_::DeviceSaveData, _NS_::SaveDataBackUp) \
HANDLER(CanMountGameCardRead, _NS_::GameCard) \
HANDLER(CanMountHostRead, _NS_::Debug, _NS_::Host) \
HANDLER(CanMountHostWrite, _NS_::Debug, _NS_::Host) \
HANDLER(CanMountImageAndVideoStorageRead, _NS_::ImageManager) \
HANDLER(CanMountImageAndVideoStorageWrite, _NS_::ImageManager) \
HANDLER(CanMountLogoRead, _NS_::ContentManager, _NS_::ApplicationInfo) \
HANDLER(CanMountOthersSaveDataRead, _NS_::SaveDataBackUp) \
HANDLER(CanMountOthersSaveDataWrite, _NS_::SaveDataBackUp) \
HANDLER(CanMountOthersSystemSaveDataRead, _NS_::SaveDataBackUp) \
HANDLER(CanMountOthersSystemSaveDataWrite, _NS_::SaveDataBackUp) \
HANDLER(CanMountRegisteredUpdatePartitionRead, _NS_::SystemUpdate) \
HANDLER(CanMountSaveDataStorageRead, _NS_::None) \
HANDLER(CanMountSaveDataStorageWrite, _NS_::None) \
HANDLER(CanMountSdCardRead, _NS_::Debug, _NS_::SdCard) \
HANDLER(CanMountSdCardWrite, _NS_::Debug, _NS_::SdCard) \
HANDLER(CanMountSystemDataPrivateRead, _NS_::SystemData, _NS_::SystemSaveData) \
HANDLER(CanMountSystemSaveDataRead, _NS_::SaveDataBackUp, _NS_::SystemSaveData) \
HANDLER(CanMountSystemSaveDataWrite, _NS_::SaveDataBackUp, _NS_::SystemSaveData) \
HANDLER(CanMountTemporaryDirectoryRead, _NS_::Debug) \
HANDLER(CanMountTemporaryDirectoryWrite, _NS_::Debug) \
HANDLER(CanNotifySystemDataUpdateEvent, _NS_::SystemUpdate) \
HANDLER(CanOpenAccessFailureDetectionEventNotifier, _NS_::AccessFailureResolution) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part1Read, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part1Write, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part2Read, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part2Write, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part3Read, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part3Write, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part4Read, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part4Write, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part5Read, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part5Write, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part6Read, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootConfigAndPackage2Part6Write, _NS_::SystemUpdate, \
_NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootPartition1RootRead, _NS_::SystemUpdate, _NS_::BisAllRaw, \
_NS_::BootModeControl) \
HANDLER(CanOpenBisPartitionBootPartition1RootWrite, _NS_::SystemUpdate, _NS_::BisAllRaw, \
_NS_::BootModeControl) \
HANDLER(CanOpenBisPartitionBootPartition2RootRead, _NS_::SystemUpdate, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionBootPartition2RootWrite, _NS_::SystemUpdate, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionCalibrationBinaryRead, _NS_::BisAllRaw, _NS_::Calibration) \
HANDLER(CanOpenBisPartitionCalibrationBinaryWrite, _NS_::BisAllRaw, _NS_::Calibration) \
HANDLER(CanOpenBisPartitionCalibrationFileRead, _NS_::BisAllRaw, _NS_::Calibration) \
HANDLER(CanOpenBisPartitionCalibrationFileWrite, _NS_::BisAllRaw, _NS_::Calibration) \
HANDLER(CanOpenBisPartitionSafeModeRead, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionSafeModeWrite, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionSystemProperEncryptionRead, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionSystemProperEncryptionWrite, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionSystemProperPartitionRead, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionSystemProperPartitionWrite, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionSystemRead, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionSystemWrite, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionUserDataRootRead, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionUserDataRootWrite, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionUserRead, _NS_::BisAllRaw) \
HANDLER(CanOpenBisPartitionUserWrite, _NS_::BisAllRaw) \
HANDLER(CanOpenBisWiper, _NS_::ContentManager) \
HANDLER(CanOpenDataStorageByPath, _NS_::None) \
HANDLER(CanOpenGameCardDetectionEventNotifier, _NS_::DeviceDetection, _NS_::GameCardRaw, \
_NS_::GameCard) \
HANDLER(CanOpenGameCardStorageRead, _NS_::GameCardRaw) \
HANDLER(CanOpenGameCardStorageWrite, _NS_::GameCardRaw) \
HANDLER(CanOpenOwnSaveDataTransferProhibiter, _NS_::CreateOwnSaveData) \
HANDLER(CanOpenSaveDataInfoReader, _NS_::SaveDataManagement, _NS_::SaveDataBackUp) \
HANDLER(CanOpenSaveDataInfoReaderForInternal, _NS_::SaveDataManagement) \
HANDLER(CanOpenSaveDataInfoReaderForSystem, _NS_::SystemSaveDataManagement, \
_NS_::SaveDataBackUp) \
HANDLER(CanOpenSaveDataInternalStorageRead, _NS_::None) \
HANDLER(CanOpenSaveDataInternalStorageWrite, _NS_::None) \
HANDLER(CanOpenSaveDataMetaFile, _NS_::SaveDataMeta) \
HANDLER(CanOpenSaveDataMover, _NS_::MoveCacheStorage) \
HANDLER(CanOpenSaveDataTransferManager, _NS_::SaveDataTransfer) \
HANDLER(CanOpenSaveDataTransferManagerForRepair, _NS_::SaveDataBackUp) \
HANDLER(CanOpenSaveDataTransferManagerForSaveDataRepair, _NS_::SaveDataTransferVersion2) \
HANDLER(CanOpenSaveDataTransferManagerForSaveDataRepairTool, _NS_::None) \
HANDLER(CanOpenSaveDataTransferManagerVersion2, _NS_::SaveDataTransferVersion2) \
HANDLER(CanOpenSaveDataTransferProhibiter, _NS_::SaveDataTransferVersion2, \
_NS_::CreateSaveData) \
HANDLER(CanOpenSdCardDetectionEventNotifier, _NS_::DeviceDetection, _NS_::SdCard) \
HANDLER(CanOpenSdCardStorageRead, _NS_::Debug, _NS_::SdCard) \
HANDLER(CanOpenSdCardStorageWrite, _NS_::Debug, _NS_::SdCard) \
HANDLER(CanOpenSystemDataUpdateEventNotifier, _NS_::SystemData, _NS_::SystemSaveData) \
HANDLER(CanOverrideSaveDataTransferTokenSignVerificationKey, _NS_::None) \
HANDLER(CanQuerySaveDataInternalStorageTotalSize, _NS_::SaveDataTransfer) \
HANDLER(CanReadOwnSaveDataFileSystemExtraData, _NS_::CreateOwnSaveData) \
HANDLER(CanReadSaveDataFileSystemExtraData, _NS_::SystemSaveDataManagement, \
_NS_::SaveDataManagement, _NS_::SaveDataBackUp) \
HANDLER(CanRegisterExternalKey, _NS_::RegisterExternalKey) \
HANDLER(CanRegisterProgramIndexMapInfo, _NS_::RegisterProgramIndexMapInfo) \
HANDLER(CanRegisterUpdatePartition, _NS_::RegisterUpdatePartition) \
HANDLER(CanResolveAccessFailure, _NS_::AccessFailureResolution) \
HANDLER(CanSetCurrentPosixTime, _NS_::SetTime) \
HANDLER(CanSetDebugConfiguration, _NS_::None) \
HANDLER(CanSetEncryptionSeed, _NS_::ContentManager) \
HANDLER(CanSetGlobalAccessLogMode, _NS_::SettingsControl) \
HANDLER(CanSetSdCardAccessibility, _NS_::SdCard) \
HANDLER(CanSetSpeedEmulationMode, _NS_::SettingsControl) \
HANDLER(CanSimulateDevice, _NS_::Debug) \
HANDLER(CanVerifySaveData, _NS_::SaveDataManagement, _NS_::SaveDataBackUp) \
HANDLER(CanWriteSaveDataFileSystemExtraDataAll, _NS_::None) \
HANDLER(CanWriteSaveDataFileSystemExtraDataCommitId, _NS_::SaveDataBackUp) \
HANDLER(CanWriteSaveDataFileSystemExtraDataFlags, _NS_::SaveDataTransferVersion2, \
_NS_::SystemSaveDataManagement, _NS_::SaveDataBackUp) \
HANDLER(CanWriteSaveDataFileSystemExtraDataTimeStamp, _NS_::SaveDataBackUp)
class AccessControlBits {
public:
enum class Bits : u64 {
None = 0,
ApplicationInfo = UINT64_C(1) << 0,
BootModeControl = UINT64_C(1) << 1,
Calibration = UINT64_C(1) << 2,
SystemSaveData = UINT64_C(1) << 3,
GameCard = UINT64_C(1) << 4,
SaveDataBackUp = UINT64_C(1) << 5,
SaveDataManagement = UINT64_C(1) << 6,
BisAllRaw = UINT64_C(1) << 7,
GameCardRaw = UINT64_C(1) << 8,
GameCardPrivate = UINT64_C(1) << 9,
SetTime = UINT64_C(1) << 10,
ContentManager = UINT64_C(1) << 11,
ImageManager = UINT64_C(1) << 12,
CreateSaveData = UINT64_C(1) << 13,
SystemSaveDataManagement = UINT64_C(1) << 14,
BisFileSystem = UINT64_C(1) << 15,
SystemUpdate = UINT64_C(1) << 16,
SaveDataMeta = UINT64_C(1) << 17,
DeviceSaveData = UINT64_C(1) << 18,
SettingsControl = UINT64_C(1) << 19,
SystemData = UINT64_C(1) << 20,
SdCard = UINT64_C(1) << 21,
Host = UINT64_C(1) << 22,
FillBis = UINT64_C(1) << 23,
CorruptSaveData = UINT64_C(1) << 24,
SaveDataForDebug = UINT64_C(1) << 25,
FormatSdCard = UINT64_C(1) << 26,
GetRightsId = UINT64_C(1) << 27,
RegisterExternalKey = UINT64_C(1) << 28,
RegisterUpdatePartition = UINT64_C(1) << 29,
SaveDataTransfer = UINT64_C(1) << 30,
DeviceDetection = UINT64_C(1) << 31,
AccessFailureResolution = UINT64_C(1) << 32,
SaveDataTransferVersion2 = UINT64_C(1) << 33,
RegisterProgramIndexMapInfo = UINT64_C(1) << 34,
CreateOwnSaveData = UINT64_C(1) << 35,
MoveCacheStorage = UINT64_C(1) << 36,
Debug = UINT64_C(1) << 62,
FullPermission = UINT64_C(1) << 63
};
private:
static constexpr u64 CombineBits(Bits b) {
return Common::ToUnderlying(b);
}
template <typename... Args>
static constexpr u64 CombineBits(Bits b, Args... args) {
return CombineBits(b) | CombineBits(args...);
}
private:
const u64 m_value;
public:
constexpr AccessControlBits(u64 v) : m_value(v) {}
constexpr u64 GetValue() const {
return m_value;
}
#define DEFINE_ACCESS_GETTER(name, ...) \
constexpr bool name() const { \
constexpr u64 Mask = CombineBits(Bits::FullPermission, ##__VA_ARGS__); \
return (m_value & Mask); \
}
YUZU_FSSRV_FOR_EACH_ACCESS_CONTROL_CAPABILITY(DEFINE_ACCESS_GETTER, Bits)
#undef DEFINE_ACCESS_GETTER
};
} // namespace FileSys::FsSrv::Impl

View File

@ -0,0 +1,152 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <mutex>
#include <optional>
#include "common/common_funcs.h"
#include "common/intrusive_list.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fs_program_index_map_info.h"
#include "core/hle/result.h"
namespace FileSys::FsSrv::Impl {
struct ProgramIndexMapInfoEntry : public ProgramIndexMapInfo,
public Common::IntrusiveListBaseNode<ProgramIndexMapInfoEntry> {};
class ProgramIndexMapInfoManager {
YUZU_NON_COPYABLE(ProgramIndexMapInfoManager);
YUZU_NON_MOVEABLE(ProgramIndexMapInfoManager);
private:
using ProgramIndexMapInfoList =
Common::IntrusiveListBaseTraits<ProgramIndexMapInfoEntry>::ListType;
private:
ProgramIndexMapInfoList m_list;
mutable std::mutex m_mutex;
public:
ProgramIndexMapInfoManager() : m_list(), m_mutex() {}
void Clear() {
// Acquire exclusive access to the map
std::scoped_lock lk(m_mutex);
// Actually clear
this->ClearImpl();
}
size_t GetProgramCount() const {
// Acquire exclusive access to the map
std::scoped_lock lk(m_mutex);
// Get the size
return m_list.size();
}
std::optional<ProgramIndexMapInfo> Get(const u64& program_id) const {
// Acquire exclusive access to the map
std::scoped_lock lk(m_mutex);
// Get the entry from the map
return this->GetImpl(
[&](const ProgramIndexMapInfoEntry& entry) { return entry.program_id == program_id; });
}
u64 GetProgramId(const u64& program_id, u8 program_index) const {
// Acquire exclusive access to the map
std::scoped_lock lk(m_mutex);
// Get the program info for the desired program id
const auto base_info = this->GetImpl(
[&](const ProgramIndexMapInfoEntry& entry) { return entry.program_id == program_id; });
// Check that an entry exists for the program id
if (!base_info.has_value()) {
return {};
}
// Get a program info which matches the same base program with the desired index
const auto target_info = this->GetImpl([&](const ProgramIndexMapInfoEntry& entry) {
return entry.base_program_id == base_info->base_program_id &&
entry.program_index == program_index;
});
// Return the desired program id
if (target_info.has_value()) {
return target_info->program_id;
} else {
return {};
}
}
Result Reset(const ProgramIndexMapInfo* infos, int count) {
// Acquire exclusive access to the map
std::scoped_lock lk(m_mutex);
// Clear the map, and ensure we remain clear if we fail after this point
this->ClearImpl();
ON_RESULT_FAILURE {
this->ClearImpl();
};
// Add each info to the list
for (int i = 0; i < count; ++i) {
// Allocate new entry
auto* entry = new ProgramIndexMapInfoEntry;
R_UNLESS(entry != nullptr, ResultAllocationMemoryFailedNew);
// Copy over the info
entry->program_id = infos[i].program_id;
entry->base_program_id = infos[i].base_program_id;
entry->program_index = infos[i].program_index;
// Add to the list
m_list.push_back(*entry);
}
// We successfully imported the map
R_SUCCEED();
}
private:
void ClearImpl() {
// Delete all entries
while (!m_list.empty()) {
// Get the first entry
ProgramIndexMapInfoEntry* front = std::addressof(*m_list.begin());
// Erase it from the list
m_list.erase(m_list.iterator_to(*front));
// Delete the entry
delete front;
}
}
template <typename F>
std::optional<ProgramIndexMapInfo> GetImpl(F f) const {
// Try to find an entry matching the predicate
std::optional<ProgramIndexMapInfo> match = std::nullopt;
for (const auto& entry : m_list) {
// If the predicate matches, we want to return the relevant info
if (f(entry)) {
match.emplace();
match->program_id = entry.program_id;
match->base_program_id = entry.base_program_id;
match->program_index = entry.program_index;
break;
}
}
return match;
}
};
} // namespace FileSys::FsSrv::Impl

View File

@ -0,0 +1,72 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <mutex>
#include "common/typed_storage.h"
#include "core/core.h"
#include "core/file_sys/fssrv/impl/fssrv_program_info.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_common.h"
namespace FileSys::FsSrv::Impl {
std::shared_ptr<ProgramInfo> InitialProgramInfo::GetProgramInfoForInitialProcess() {
constexpr const std::array<u32, 0x1C / sizeof(u32)> FileAccessControlForInitialProgram = {
0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
constexpr const std::array<u32, 0x2C / sizeof(u32)> FileAccessControlDescForInitialProgram = {
0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF,
0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
if (!initial_program_info) {
initial_program_info = std::make_shared<ProgramInfo>(
FileAccessControlForInitialProgram.data(), sizeof(FileAccessControlForInitialProgram),
FileAccessControlDescForInitialProgram.data(),
sizeof(FileAccessControlDescForInitialProgram));
}
return initial_program_info;
}
void InitialProgramInfo::InitializeInitialAndCurrentProcessId(Core::System& system) {
using namespace Kernel;
if (!initialized_ids) {
// Get initial process id range
ASSERT(Svc::GetSystemInfo(system, std::addressof(initial_process_id_min),
Svc::SystemInfoType::InitialProcessIdRange, Svc::InvalidHandle,
static_cast<u64>(Svc::InitialProcessIdRangeInfo::Minimum)) ==
ResultSuccess);
ASSERT(Svc::GetSystemInfo(system, std::addressof(initial_process_id_max),
Svc::SystemInfoType::InitialProcessIdRange, Svc::InvalidHandle,
static_cast<u64>(Svc::InitialProcessIdRangeInfo::Maximum)) ==
ResultSuccess);
ASSERT(0 < initial_process_id_min);
ASSERT(initial_process_id_min <= initial_process_id_max);
// Get current procss id
ASSERT(Svc::GetProcessId(system, std::addressof(current_process_id),
Svc::PseudoHandle::CurrentProcess) == ResultSuccess);
// Set initialized
initialized_ids = true;
}
}
bool InitialProgramInfo::IsInitialProgram(Core::System& system, u64 process_id) {
// Initialize/sanity check
InitializeInitialAndCurrentProcessId(system);
ASSERT(initial_process_id_min > 0);
// Check process id in range
return initial_process_id_min <= process_id && process_id <= initial_process_id_max;
}
bool InitialProgramInfo::IsCurrentProcess(Core::System& system, u64 process_id) {
// Initialize
InitializeInitialAndCurrentProcessId(system);
return process_id == current_process_id;
}
} // namespace FileSys::FsSrv::Impl

View File

@ -0,0 +1,90 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/file_sys/fssrv/impl/fssrv_access_control.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
namespace Core {
class System;
}
namespace FileSys::FsSrv::Impl {
constexpr u64 InvalidProcessId = 0xffffffffffffffffULL;
class ProgramInfo {
private:
u64 m_process_id;
u64 m_program_id;
FileSys::StorageId m_storage_id;
AccessControl m_access_control;
// Needed to work around current fs limitations
std::shared_ptr<RomFSFactory> m_romfs_factory;
std::shared_ptr<SaveDataFactory> m_save_data_factory;
public:
ProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void* data, s64 data_size,
const void* desc, s64 desc_size, std::shared_ptr<RomFSFactory> romfs_factory,
std::shared_ptr<SaveDataFactory> save_data_factory)
: m_process_id(process_id), m_access_control(data, data_size, desc, desc_size) {
m_program_id = program_id;
m_storage_id = static_cast<FileSys::StorageId>(storage_id);
m_romfs_factory = romfs_factory;
m_save_data_factory = save_data_factory;
}
ProgramInfo(const void* data, s64 data_size, const void* desc, s64 desc_size)
: m_process_id(InvalidProcessId), m_program_id(0),
m_storage_id(static_cast<FileSys::StorageId>(0)),
m_access_control(data, data_size, desc, desc_size, std::numeric_limits<u64>::max()) {}
bool Contains(u64 process_id) const {
return m_process_id == process_id;
}
u64 GetProcessId() const {
return m_process_id;
}
u64 GetProgramId() const {
return m_program_id;
}
FileSys::StorageId GetStorageId() const {
return m_storage_id;
}
AccessControl& GetAccessControl() {
return m_access_control;
}
std::shared_ptr<RomFSFactory> GetRomFsFactory() {
return m_romfs_factory;
}
std::shared_ptr<SaveDataFactory> GetSaveDataFactory() {
return m_save_data_factory;
}
};
struct ProgramInfoNode : public Common::IntrusiveListBaseNode<ProgramInfoNode> {
std::shared_ptr<ProgramInfo> program_info;
};
class InitialProgramInfo {
private:
void InitializeInitialAndCurrentProcessId(Core::System& system);
public:
std::shared_ptr<ProgramInfo> GetProgramInfoForInitialProcess();
bool IsInitialProgram(Core::System& system, u64 process_id);
bool IsCurrentProcess(Core::System& system, u64 process_id);
private:
std::shared_ptr<ProgramInfo> initial_program_info = nullptr;
bool initialized_ids = false;
u64 initial_process_id_min = 0;
u64 initial_process_id_max = 0;
u64 current_process_id = 0;
};
} // namespace FileSys::FsSrv::Impl

View File

@ -0,0 +1,104 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fssrv/impl/fssrv_program_registry_manager.h"
namespace FileSys::FsSrv::Impl {
ProgramRegistryManager::ProgramRegistryManager(Core::System& system_,
InitialProgramInfo& program_info)
: m_initial_program_info{program_info}, system{system_} {}
Result ProgramRegistryManager::RegisterProgram(
u64 process_id, u64 program_id, u8 storage_id, const void* data, s64 data_size,
const void* desc, s64 desc_size, std::shared_ptr<FileSys::RomFSFactory> romfs_factory,
std::shared_ptr<FileSys::SaveDataFactory> save_data_factory) {
// Allocate a new node
std::unique_ptr<ProgramInfoNode> new_node(new ProgramInfoNode());
R_UNLESS(new_node != nullptr, ResultAllocationMemoryFailedInProgramRegistryManagerA);
// Create a new program info
{
// Allocate the new info
std::shared_ptr<ProgramInfo> new_info =
std::make_shared<ProgramInfo>(process_id, program_id, storage_id, data, data_size, desc,
desc_size, romfs_factory, save_data_factory);
R_UNLESS(new_info != nullptr, ResultAllocationMemoryFailedInProgramRegistryManagerA);
// Set the info in the node
new_node->program_info = std::move(new_info);
}
// Acquire exclusive access to the registry
std::scoped_lock lk(m_mutex);
// Check that the process isn't already in the registry
for (const auto& node : m_program_info_list) {
R_UNLESS(!node.program_info->Contains(process_id), ResultInvalidArgument);
}
// Add the node to the registry
m_program_info_list.push_back(*new_node.release());
R_SUCCEED();
}
Result ProgramRegistryManager::UnregisterProgram(u64 process_id) {
// Acquire exclusive access to the registry
std::scoped_lock lk(m_mutex);
// Try to find and remove the process's node
for (auto& node : m_program_info_list) {
if (node.program_info->Contains(process_id)) {
m_program_info_list.erase(m_program_info_list.iterator_to(node));
delete std::addressof(node);
R_SUCCEED();
}
}
// We couldn't find/unregister the process's node
R_THROW(ResultInvalidArgument);
}
Result ProgramRegistryManager::GetProgramInfo(std::shared_ptr<ProgramInfo>* out, u64 process_id) {
// Acquire exclusive access to the registry
std::scoped_lock lk(m_mutex);
// Check if we're getting permissions for an initial program
if (m_initial_program_info.IsInitialProgram(system, process_id)) {
*out = (m_initial_program_info.GetProgramInfoForInitialProcess());
R_SUCCEED();
}
// Find a matching node
for (const auto& node : m_program_info_list) {
if (node.program_info->Contains(process_id)) {
*out = node.program_info;
R_SUCCEED();
}
}
// We didn't find the program info
R_THROW(ResultProgramInfoNotFound);
}
Result ProgramRegistryManager::GetProgramInfoByProgramId(std::shared_ptr<ProgramInfo>* out,
u64 program_id) {
// Acquire exclusive access to the registry
std::scoped_lock lk(m_mutex);
// Find a matching node
for (const auto& node : m_program_info_list) {
if (node.program_info->GetProgramId() == program_id) {
*out = node.program_info;
R_SUCCEED();
}
}
// We didn't find the program info
R_THROW(ResultProgramInfoNotFound);
}
} // namespace FileSys::FsSrv::Impl

View File

@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <mutex>
#include "common/common_funcs.h"
#include "common/intrusive_list.h"
#include "core/file_sys/fssrv/impl/fssrv_program_info.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
namespace Core {
class System;
}
namespace FileSys::FsSrv::Impl {
class ProgramRegistryManager {
YUZU_NON_COPYABLE(ProgramRegistryManager);
YUZU_NON_MOVEABLE(ProgramRegistryManager);
public:
explicit ProgramRegistryManager(Core::System& system_, InitialProgramInfo& program_info);
Result RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const void* data,
s64 data_size, const void* desc, s64 desc_size,
std::shared_ptr<FileSys::RomFSFactory> romfs_factory = nullptr,
std::shared_ptr<FileSys::SaveDataFactory> save_data_factory = nullptr);
Result UnregisterProgram(u64 process_id);
Result GetProgramInfo(std::shared_ptr<ProgramInfo>* out, u64 process_id);
Result GetProgramInfoByProgramId(std::shared_ptr<ProgramInfo>* out, u64 program_id);
private:
using ProgramInfoList = Common::IntrusiveListBaseTraits<ProgramInfoNode>::ListType;
ProgramInfoList m_program_info_list{};
InitialProgramInfo& m_initial_program_info;
mutable std::mutex m_mutex{};
Core::System& system;
};
} // namespace FileSys::FsSrv::Impl

View File

@ -0,0 +1,192 @@
// SPDX-FileCopyrightText: Copyright 2020 Alex Barney
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: MIT AND GPL-2.0-or-later
#pragma once
#include "common/assert.h"
#include "common/common_types.h"
#include "core/file_sys/fs_save_data_types.h"
namespace FileSys::FsSrv::Impl {
class SaveDataProperties {
public:
static constexpr s64 DefaultSaveDataBlockSize = 0x4000;
static constexpr s64 BcatSaveDataJournalSize = 0x200000;
static bool IsJournalingSupported(SaveDataFormatType type) {
switch (type) {
case SaveDataFormatType::Normal:
return true;
case SaveDataFormatType::NoJournal:
return false;
default:
UNREACHABLE();
return false;
}
}
static bool IsJournalingSupported(SaveDataType type) {
switch (type) {
case SaveDataType::System:
case SaveDataType::Account:
case SaveDataType::Bcat:
case SaveDataType::Device:
case SaveDataType::Cache:
return true;
case SaveDataType::Temporary:
return false;
default:
UNREACHABLE();
return false;
}
}
static bool IsMultiCommitSupported(SaveDataType type) {
switch (type) {
case SaveDataType::System:
case SaveDataType::Account:
case SaveDataType::Device:
return true;
case SaveDataType::Bcat:
case SaveDataType::Temporary:
case SaveDataType::Cache:
return false;
default:
UNREACHABLE();
return false;
}
}
static bool IsSharedOpenNeeded(SaveDataType type) {
switch (type) {
case SaveDataType::System:
case SaveDataType::Bcat:
case SaveDataType::Temporary:
case SaveDataType::Cache:
return false;
case SaveDataType::Account:
case SaveDataType::Device:
return true;
default:
UNREACHABLE();
return false;
}
}
static bool CanUseIndexerReservedArea(SaveDataType type) {
switch (type) {
case SaveDataType::System:
return true;
case SaveDataType::Account:
case SaveDataType::Bcat:
case SaveDataType::Device:
case SaveDataType::Temporary:
case SaveDataType::Cache:
return false;
default:
UNREACHABLE();
return false;
}
}
static bool IsSystemSaveData(SaveDataType type) {
switch (type) {
case SaveDataType::System:
return true;
case SaveDataType::Account:
case SaveDataType::Bcat:
case SaveDataType::Device:
case SaveDataType::Temporary:
case SaveDataType::Cache:
return false;
default:
UNREACHABLE();
return false;
}
}
static bool IsObsoleteSystemSaveData(const SaveDataInfo& info) {
constexpr std::array<u64, 2> ObsoleteSystemSaveDataIdList = {0x8000000000000060,
0x8000000000000075};
return std::find(ObsoleteSystemSaveDataIdList.begin(), ObsoleteSystemSaveDataIdList.end(),
info.save_id) != ObsoleteSystemSaveDataIdList.end();
}
static bool IsWipingNeededAtCleanUp(const SaveDataInfo& info) {
switch (info.type) {
case SaveDataType::System:
break;
case SaveDataType::Account:
case SaveDataType::Bcat:
case SaveDataType::Device:
case SaveDataType::Temporary:
case SaveDataType::Cache:
return true;
default:
UNREACHABLE();
break;
}
constexpr std::array<u64, 28> SystemSaveDataIdWipingExceptionList = {
0x8000000000000040, 0x8000000000000041, 0x8000000000000043, 0x8000000000000044,
0x8000000000000045, 0x8000000000000046, 0x8000000000000047, 0x8000000000000048,
0x8000000000000049, 0x800000000000004A, 0x8000000000000070, 0x8000000000000071,
0x8000000000000072, 0x8000000000000074, 0x8000000000000076, 0x8000000000000077,
0x8000000000000090, 0x8000000000000091, 0x8000000000000092, 0x80000000000000B0,
0x80000000000000C1, 0x80000000000000C2, 0x8000000000000120, 0x8000000000000121,
0x8000000000000180, 0x8000000000010003, 0x8000000000010004};
return std::find(SystemSaveDataIdWipingExceptionList.begin(),
SystemSaveDataIdWipingExceptionList.end(),
info.save_id) == SystemSaveDataIdWipingExceptionList.end();
}
static bool IsValidSpaceIdForSaveDataMover(SaveDataType type, SaveDataSpaceId space_id) {
switch (type) {
case SaveDataType::System:
case SaveDataType::Account:
case SaveDataType::Bcat:
case SaveDataType::Device:
case SaveDataType::Temporary:
return false;
case SaveDataType::Cache:
return space_id == SaveDataSpaceId::User || space_id == SaveDataSpaceId::SdUser;
default:
UNREACHABLE();
return false;
}
}
static bool IsReconstructible(SaveDataType type, SaveDataSpaceId space_id) {
switch (space_id) {
case SaveDataSpaceId::System:
case SaveDataSpaceId::User:
case SaveDataSpaceId::ProperSystem:
case SaveDataSpaceId::SafeMode:
switch (type) {
case SaveDataType::System:
case SaveDataType::Account:
case SaveDataType::Device:
return false;
case SaveDataType::Bcat:
case SaveDataType::Temporary:
case SaveDataType::Cache:
return true;
default:
UNREACHABLE();
return false;
}
case SaveDataSpaceId::SdSystem:
case SaveDataSpaceId::Temporary:
case SaveDataSpaceId::SdUser:
return true;
default:
UNREACHABLE();
return false;
}
}
};
} // namespace FileSys::FsSrv::Impl

View File

@ -4,8 +4,9 @@
#pragma once
#include "common/alignment.h"
#include "core/file_sys/fs_common.h"
#include "core/file_sys/fs_save_data_types.h"
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/fssystem/fs_types.h"
#include "core/file_sys/fssystem/fssystem_alignment_matching_storage.h"
#include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h"
#include "core/file_sys/vfs/vfs_offset.h"

View File

@ -5,8 +5,8 @@
#include <optional>
#include "core/file_sys/fs_common.h"
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/fssystem/fs_types.h"
namespace FileSys {

View File

@ -8,7 +8,7 @@
#include "common/literals.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fs_types.h"
#include "core/file_sys/fs_common.h"
namespace FileSys {

View File

@ -11,9 +11,9 @@ namespace HLE::ApiVersion {
// Horizon OS version constants.
constexpr u8 HOS_VERSION_MAJOR = 12;
constexpr u8 HOS_VERSION_MINOR = 1;
constexpr u8 HOS_VERSION_MICRO = 0;
constexpr u8 HOS_VERSION_MAJOR = 17;
constexpr u8 HOS_VERSION_MINOR = 0;
constexpr u8 HOS_VERSION_MICRO = 1;
// NintendoSDK version constants.
@ -21,15 +21,15 @@ constexpr u8 SDK_REVISION_MAJOR = 1;
constexpr u8 SDK_REVISION_MINOR = 0;
constexpr char PLATFORM_STRING[] = "NX";
constexpr char VERSION_HASH[] = "76b10c2dab7d3aa73fc162f8dff1655e6a21caf4";
constexpr char DISPLAY_VERSION[] = "12.1.0";
constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 12.1.0-1.0";
constexpr char VERSION_HASH[] = "30dd7d0584cd38e3a1db26a5719566d21d77110e";
constexpr char DISPLAY_VERSION[] = "17.0.1";
constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 17.0.1-1.0";
// Atmosphere version constants.
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 1;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 0;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 0;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 6;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 2;
constexpr u32 AtmosphereTargetFirmwareWithRevision(u8 major, u8 minor, u8 micro, u8 rev) {
return u32{major} << 24 | u32{minor} << 16 | u32{micro} << 8 | u32{rev};

View File

@ -57,6 +57,7 @@ Result GetThreadId(Core::System& system, uint64_t* out_thread_id, Handle thread_
void Break(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size);
Result OutputDebugString(Core::System& system, uint64_t debug_str, uint64_t len);
void ReturnFromException(Core::System& system, Result result);
Result GetInitialProcessIdRange(u64 *out, InitialProcessIdRangeInfo info);
Result GetInfo(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);
void FlushEntireDataCache(Core::System& system);
Result FlushDataCache(Core::System& system, uint64_t address, uint64_t size);

View File

@ -1,14 +1,34 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/api_version.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_common.h"
namespace Kernel::Svc {
Result GetInitialProcessIdRange(u64* out, InitialProcessIdRangeInfo info) {
switch (info) {
case InitialProcessIdRangeInfo::Minimum:
static_assert(KProcess::InitialProcessIdMin <= KProcess::InitialProcessIdMax);
*out = KProcess::InitialProcessIdMin;
break;
case InitialProcessIdRangeInfo::Maximum:
static_assert(KProcess::InitialProcessIdMin <= KProcess::InitialProcessIdMax);
*out = KProcess::InitialProcessIdMax;
break;
default:
R_THROW(ResultInvalidCombination);
}
R_SUCCEED();
}
/// Gets system/memory information for the current process
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
u64 info_sub_id) {
@ -174,9 +194,17 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_SUCCEED();
case InfoType::InitialProcessIdRange:
LOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query privileged process id bounds, returned 0");
*result = 0;
// NOTE: This info type was added in 4.0.0, and removed in 5.0.0
R_UNLESS(HLE::ApiVersion::GetTargetFirmware() <
HLE::ApiVersion::AtmosphereTargetFirmware(5, 0, 0),
ResultInvalidEnumValue);
// Verify the input handle is invalid
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
// Get the process id range
R_TRY(
GetInitialProcessIdRange(result, static_cast<InitialProcessIdRangeInfo>(info_sub_id)));
R_SUCCEED();
case InfoType::ThreadTickCount: {
@ -255,10 +283,58 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
}
}
static constexpr bool IsValidMemoryPool(u64 pool) {
switch (static_cast<KMemoryManager::Pool>(pool)) {
case KMemoryManager::Pool::Application:
case KMemoryManager::Pool::Applet:
case KMemoryManager::Pool::System:
case KMemoryManager::Pool::SystemNonSecure:
return true;
default:
return false;
}
}
Result GetSystemInfo(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle,
uint64_t info_subtype) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
switch (info_type) {
case SystemInfoType::TotalPhysicalMemorySize:
case SystemInfoType::UsedPhysicalMemorySize: {
// Verify the input handle is invalid
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
// Verify the sub-type is valid
R_UNLESS(IsValidMemoryPool(info_subtype), ResultInvalidCombination);
// Convert to pool
const auto pool = static_cast<KMemoryManager::Pool>(info_subtype);
// Get the memory size
auto& mm = system.Kernel().MemoryManager();
switch (info_type) {
case SystemInfoType::TotalPhysicalMemorySize:
*out = mm.GetSize(pool);
break;
case SystemInfoType::UsedPhysicalMemorySize:
*out = mm.GetSize(pool) - mm.GetFreeSize(pool);
break;
default:
UNREACHABLE();
break;
}
} break;
case SystemInfoType::InitialProcessIdRange: {
// Verify the handle is invalid
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
// Get the process id range
R_TRY(GetInitialProcessIdRange(out, static_cast<InitialProcessIdRangeInfo>(info_subtype)));
} break;
default:
R_THROW(ResultInvalidEnumValue);
}
R_SUCCEED();
}
Result GetInfo64(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,

View File

@ -20,8 +20,8 @@
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_offset.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp/fs_i_program_registry.h"
#include "core/hle/service/filesystem/fsp/fsp_ldr.h"
#include "core/hle/service/filesystem/fsp/fsp_pr.h"
#include "core/hle/service/filesystem/fsp/fsp_srv.h"
#include "core/hle/service/filesystem/romfs_controller.h"
#include "core/hle/service/filesystem/save_data_controller.h"
@ -298,13 +298,8 @@ FileSystemController::~FileSystemController() = default;
Result FileSystemController::RegisterProcess(
ProcessId process_id, ProgramId program_id,
std::shared_ptr<FileSys::RomFSFactory>&& romfs_factory) {
std::scoped_lock lk{registration_lock};
registrations.emplace(process_id, Registration{
.program_id = program_id,
.romfs_factory = std::move(romfs_factory),
.save_data_factory = CreateSaveDataFactory(program_id),
});
system.GetProgramRegistry().RegisterProgramForLoader(
process_id, program_id, std::move(romfs_factory), CreateSaveDataFactory(program_id));
LOG_DEBUG(Service_FS, "Registered for process {}", process_id);
return ResultSuccess;
@ -313,31 +308,28 @@ Result FileSystemController::RegisterProcess(
Result FileSystemController::OpenProcess(
ProgramId* out_program_id, std::shared_ptr<SaveDataController>* out_save_data_controller,
std::shared_ptr<RomFsController>* out_romfs_controller, ProcessId process_id) {
std::scoped_lock lk{registration_lock};
const auto it = registrations.find(process_id);
if (it == registrations.end()) {
std::shared_ptr<FileSys::FsSrv::Impl::ProgramInfo> out_info;
if (system.GetProgramRegistry().GetProgramInfo(&out_info, process_id) != ResultSuccess) {
return FileSys::ResultTargetNotFound;
}
*out_program_id = it->second.program_id;
*out_program_id = out_info->GetProgramId();
*out_save_data_controller =
std::make_shared<SaveDataController>(system, it->second.save_data_factory);
std::make_shared<SaveDataController>(system, out_info->GetSaveDataFactory());
*out_romfs_controller =
std::make_shared<RomFsController>(it->second.romfs_factory, it->second.program_id);
std::make_shared<RomFsController>(out_info->GetRomFsFactory(), out_info->GetProgramId());
return ResultSuccess;
}
void FileSystemController::SetPackedUpdate(ProcessId process_id, FileSys::VirtualFile update_raw) {
LOG_TRACE(Service_FS, "Setting packed update for romfs");
std::scoped_lock lk{registration_lock};
const auto it = registrations.find(process_id);
if (it == registrations.end()) {
std::shared_ptr<FileSys::FsSrv::Impl::ProgramInfo> out_info;
if (system.GetProgramRegistry().GetProgramInfo(&out_info, process_id) != ResultSuccess) {
return;
}
it->second.romfs_factory->SetPackedUpdate(std::move(update_raw));
out_info->GetRomFsFactory()->SetPackedUpdate(std::move(update_raw));
}
std::shared_ptr<SaveDataController> FileSystemController::OpenSaveDataController() {
@ -715,18 +707,13 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
}
}
void FileSystemController::Reset() {
std::scoped_lock lk{registration_lock};
registrations.clear();
}
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
const auto FileSystemProxyFactory = [&] { return std::make_shared<FSP_SRV>(system); };
server_manager->RegisterNamedService("fsp-ldr", std::make_shared<FSP_LDR>(system));
server_manager->RegisterNamedService("fsp:pr", std::make_shared<FSP_PR>(system));
server_manager->RegisterNamedService("fsp:pr", std::make_shared<IProgramRegistry>(system));
server_manager->RegisterNamedService("fsp-srv", std::move(FileSystemProxyFactory));
ServerManager::RunServer(std::move(server_manager));
}

View File

@ -121,20 +121,9 @@ public:
// above is called.
void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true);
void Reset();
private:
std::shared_ptr<FileSys::SaveDataFactory> CreateSaveDataFactory(ProgramId program_id);
struct Registration {
ProgramId program_id;
std::shared_ptr<FileSys::RomFSFactory> romfs_factory;
std::shared_ptr<FileSys::SaveDataFactory> save_data_factory;
};
std::mutex registration_lock;
std::map<ProcessId, Registration> registrations;
std::unique_ptr<FileSys::SDMCFactory> sdmc_factory;
std::unique_ptr<FileSys::BISFactory> bis_factory;

View File

@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_program_registry.h"
namespace Service::FileSystem {
IProgramRegistry::IProgramRegistry(Core::System& system_)
: ServiceFramework{system_, "fsp:pr"}, registry{system_.GetProgramRegistry()} {
// clang-format off
static const FunctionInfo functions[] = {
{0, C<&IProgramRegistry::RegisterProgram>, "RegisterProgram"},
{1, C<&IProgramRegistry::UnregisterProgram>, "UnregisterProgram"},
{2, C<&IProgramRegistry::SetCurrentProcess>, "SetCurrentProcess"},
{256, C<&IProgramRegistry::SetEnabledProgramVerification>, "SetEnabledProgramVerification"},
};
// clang-format on
RegisterHandlers(functions);
}
IProgramRegistry::~IProgramRegistry() = default;
Result IProgramRegistry::RegisterProgram(u8 storage_id, u64 process_id, u64 program_id,
const InBuffer<BufferAttr_HipcMapAlias> data,
s64 data_size,
const InBuffer<BufferAttr_HipcMapAlias> desc,
s64 desc_size) {
LOG_INFO(Service_FS,
"called, process_id={}, program_id={}, storage_id={}, data_size={}, desc_size = {}",
process_id, program_id, storage_id, data_size, desc_size);
R_RETURN(registry.RegisterProgram(process_id, program_id, storage_id, data, data_size, desc,
desc_size));
}
Result IProgramRegistry::UnregisterProgram(u64 process_id) {
LOG_INFO(Service_FS, "called, process_id={}", process_id);
R_RETURN(registry.UnregisterProgram(process_id));
}
Result IProgramRegistry::SetCurrentProcess(const ClientProcessId& client_pid) {
LOG_INFO(Service_FS, "called, client_pid={}", client_pid.pid);
R_RETURN(registry.SetCurrentProcess(client_pid));
}
Result IProgramRegistry::SetEnabledProgramVerification(bool enabled) {
LOG_INFO(Service_FS, "called, enabled={}", enabled);
R_RETURN(registry.SetEnabledProgramVerification(enabled));
}
} // namespace Service::FileSystem

View File

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/file_sys/fssrv/fssrv_program_registry_impl.h"
#include "core/hle/result.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::FileSystem {
class IProgramRegistry final : public ServiceFramework<IProgramRegistry> {
public:
explicit IProgramRegistry(Core::System& system_);
~IProgramRegistry() override;
Result RegisterProgram(u8 storage_id, u64 process_id, u64 program_id,
const InBuffer<BufferAttr_HipcMapAlias> data, s64 data_size,
const InBuffer<BufferAttr_HipcMapAlias> desc, s64 desc_size);
Result UnregisterProgram(u64 process_id);
Result SetCurrentProcess(const ClientProcessId& client_pid);
Result SetEnabledProgramVerification(bool enabled);
private:
FileSys::FsSrv::ProgramRegistryImpl& registry;
};
} // namespace Service::FileSystem

View File

@ -37,7 +37,7 @@ static u64 stoull_be(std::string_view str) {
}
Result ISaveDataInfoReader::ReadSaveDataInfo(
Out<u64> out_count, OutArray<SaveDataInfo, BufferAttr_HipcMapAlias> out_entries) {
Out<u64> out_count, OutArray<FileSys::SaveDataInfo, BufferAttr_HipcMapAlias> out_entries) {
LOG_DEBUG(Service_FS, "called");
// Calculate how many entries we can fit in the output buffer
@ -93,7 +93,7 @@ void ISaveDataInfoReader::FindNormalSaves(FileSys::SaveDataSpaceId space,
if (save_id_numeric != 0) {
// System Save Data
info.emplace_back(SaveDataInfo{
info.emplace_back(FileSys::SaveDataInfo{
0,
space,
FileSys::SaveDataType::System,
@ -112,7 +112,7 @@ void ISaveDataInfoReader::FindNormalSaves(FileSys::SaveDataSpaceId space,
for (const auto& title_id : user_id->GetSubdirectories()) {
const auto device = std::all_of(user_id_numeric.begin(), user_id_numeric.end(),
[](u8 val) { return val == 0; });
info.emplace_back(SaveDataInfo{
info.emplace_back(FileSys::SaveDataInfo{
0,
space,
device ? FileSys::SaveDataType::Device : FileSys::SaveDataType::Account,
@ -141,7 +141,7 @@ void ISaveDataInfoReader::FindTemporaryStorageSaves(FileSys::SaveDataSpaceId spa
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
info.emplace_back(SaveDataInfo{
info.emplace_back(FileSys::SaveDataInfo{
0,
space,
FileSys::SaveDataType::Temporary,

View File

@ -5,6 +5,7 @@
#include <vector>
#include "common/common_types.h"
#include "core/file_sys/fs_save_data_types.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
@ -19,23 +20,8 @@ public:
FileSys::SaveDataSpaceId space);
~ISaveDataInfoReader() override;
struct SaveDataInfo {
u64_le save_id_unknown;
FileSys::SaveDataSpaceId space;
FileSys::SaveDataType type;
INSERT_PADDING_BYTES(0x6);
std::array<u8, 0x10> user_id;
u64_le save_id;
u64_le title_id;
u64_le save_image_size;
u16_le index;
FileSys::SaveDataRank rank;
INSERT_PADDING_BYTES(0x25);
};
static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
Result ReadSaveDataInfo(Out<u64> out_count,
OutArray<SaveDataInfo, BufferAttr_HipcMapAlias> out_entries);
OutArray<FileSys::SaveDataInfo, BufferAttr_HipcMapAlias> out_entries);
private:
void FindAllSaves(FileSys::SaveDataSpaceId space);
@ -43,7 +29,7 @@ private:
void FindTemporaryStorageSaves(FileSys::SaveDataSpaceId space, const FileSys::VirtualDir& type);
std::shared_ptr<SaveDataController> save_data_controller;
std::vector<SaveDataInfo> info;
std::vector<FileSys::SaveDataInfo> info;
u64 next_entry_index = 0;
};

View File

@ -1,23 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/filesystem/fsp/fsp_pr.h"
namespace Service::FileSystem {
FSP_PR::FSP_PR(Core::System& system_) : ServiceFramework{system_, "fsp:pr"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RegisterProgram"},
{1, nullptr, "UnregisterProgram"},
{2, nullptr, "SetCurrentProcess"},
{256, nullptr, "SetEnabledProgramVerification"},
};
// clang-format on
RegisterHandlers(functions);
}
FSP_PR::~FSP_PR() = default;
} // namespace Service::FileSystem

View File

@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::FileSystem {
class FSP_PR final : public ServiceFramework<FSP_PR> {
public:
explicit FSP_PR(Core::System& system_);
~FSP_PR() override;
};
} // namespace Service::FileSystem

View File

@ -225,23 +225,23 @@ Result FSP_SRV::OpenSdCardFileSystem(OutInterface<IFileSystem> out_interface) {
R_SUCCEED();
}
Result FSP_SRV::CreateSaveDataFileSystem(FileSys::SaveDataCreationInfo save_create_struct,
FileSys::SaveDataAttribute save_struct, u128 uid) {
LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(),
uid[1], uid[0]);
Result FSP_SRV::CreateSaveDataFileSystem(FileSys::SaveDataMetaInfo meta_info,
FileSys::SaveDataCreationInfo creation_info,
FileSys::SaveDataAttribute attribute) {
LOG_DEBUG(Service_FS, "called save_struct = {}", attribute.DebugInfo());
FileSys::VirtualDir save_data_dir{};
R_RETURN(save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::User,
save_struct));
attribute));
}
Result FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(
FileSys::SaveDataAttribute save_struct, FileSys::SaveDataCreationInfo save_create_struct) {
LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo());
FileSys::SaveDataAttribute attribute, FileSys::SaveDataCreationInfo save_create_struct) {
LOG_DEBUG(Service_FS, "called save_struct = {}", attribute.DebugInfo());
FileSys::VirtualDir save_data_dir{};
R_RETURN(save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::System,
save_struct));
attribute));
}
Result FSP_SRV::OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,

View File

@ -51,10 +51,11 @@ private:
Result OpenFileSystemWithPatch(OutInterface<IFileSystem> out_interface,
FileSystemProxyType type, u64 open_program_id);
Result OpenSdCardFileSystem(OutInterface<IFileSystem> out_interface);
Result CreateSaveDataFileSystem(FileSys::SaveDataCreationInfo save_create_struct,
FileSys::SaveDataAttribute save_struct, u128 uid);
Result CreateSaveDataFileSystem(FileSys::SaveDataMetaInfo meta_info,
FileSys::SaveDataCreationInfo creation_info,
FileSys::SaveDataAttribute attribute);
Result CreateSaveDataFileSystemBySystemSaveDataId(
FileSys::SaveDataAttribute save_struct, FileSys::SaveDataCreationInfo save_create_struct);
FileSys::SaveDataAttribute attribute, FileSys::SaveDataCreationInfo save_create_struct);
Result OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
FileSys::SaveDataSpaceId space_id,
FileSys::SaveDataAttribute attribute);