mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-11-26 14:05:46 +01:00
fssrv: Add various data types and utility classes
These will be needed to reimplement the filesystem at a later point.
This commit is contained in:
parent
1e0e36c2c2
commit
f9a67ff75d
@ -60,6 +60,7 @@ add_library(core STATIC
|
||||
file_sys/fs_path_utility.h
|
||||
file_sys/fs_save_data_types.h
|
||||
file_sys/fs_string_util.h
|
||||
file_sys/fs_program_index_map_info.h
|
||||
file_sys/fsa/fs_i_directory.h
|
||||
file_sys/fsa/fs_i_file.h
|
||||
file_sys/fsa/fs_i_filesystem.h
|
||||
@ -109,6 +110,19 @@ add_library(core STATIC
|
||||
file_sys/fssystem/fssystem_switch_storage.h
|
||||
file_sys/fssystem/fssystem_utility.cpp
|
||||
file_sys/fssystem/fssystem_utility.h
|
||||
file_sys/fssrv/impl/fssrv_program_info.cpp
|
||||
file_sys/fssrv/impl/fssrv_program_info.h
|
||||
file_sys/fssrv/impl/fssrv_access_control.h
|
||||
file_sys/fssrv/impl/fssrv_access_control.cpp
|
||||
file_sys/fssrv/impl/fssrv_access_control_bits.h
|
||||
file_sys/fssrv/impl/fssrv_program_registry_manager.cpp
|
||||
file_sys/fssrv/impl/fssrv_program_registry_manager.h
|
||||
file_sys/fssrv/impl/fssrv_program_index_map_info_manager.h
|
||||
file_sys/fssrv/impl/fssrv_save_data_properties.h
|
||||
file_sys/fssrv/fssrv_program_registry_impl.h
|
||||
file_sys/fssrv/fssrv_program_registry_impl.cpp
|
||||
file_sys/fssrv/fssrv_program_registry_service.h
|
||||
file_sys/fssrv/fssrv_program_registry_service.cpp
|
||||
file_sys/ips_layer.cpp
|
||||
file_sys/ips_layer.h
|
||||
file_sys/kernel_executable.cpp
|
||||
|
@ -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
|
||||
|
20
src/core/file_sys/fs_program_index_map_info.h
Normal file
20
src/core/file_sys/fs_program_index_map_info.h
Normal 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
|
77
src/core/file_sys/fssrv/fssrv_program_registry_impl.cpp
Normal file
77
src/core/file_sys/fssrv/fssrv_program_registry_impl.cpp
Normal 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"
|
||||
#include "core/file_sys/fssrv/impl/fssrv_program_info.h"
|
||||
|
||||
namespace FileSys::FsSrv {
|
||||
|
||||
namespace {
|
||||
constinit ProgramRegistryServiceImpl* g_impl = nullptr;
|
||||
}
|
||||
|
||||
// TODO: Move this to a common types file
|
||||
constexpr u64 InvalidProcessIdProgramRegistry = 0xffffffffffffffffULL;
|
||||
|
||||
ProgramRegistryImpl::ProgramRegistryImpl(Core::System& system_)
|
||||
: m_process_id(InvalidProcessIdProgramRegistry), system{system_} {}
|
||||
|
||||
ProgramRegistryImpl::~ProgramRegistryImpl() {}
|
||||
|
||||
void ProgramRegistryImpl::Initialize(ProgramRegistryServiceImpl* service) {
|
||||
// Check pre-conditions
|
||||
ASSERT(g_impl != nullptr);
|
||||
ASSERT(g_impl == nullptr);
|
||||
|
||||
// Set the global service
|
||||
g_impl = service;
|
||||
}
|
||||
|
||||
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 pre-conditions
|
||||
ASSERT(g_impl != nullptr);
|
||||
|
||||
// Check that we're allowed to register
|
||||
R_UNLESS(FsSrv::Impl::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(g_impl->RegisterProgramInfo(process_id, program_id, storage_id, data.data(), data_size,
|
||||
desc.data(), desc_size));
|
||||
}
|
||||
|
||||
Result ProgramRegistryImpl::UnregisterProgram(u64 process_id) {
|
||||
// Check pre-conditions
|
||||
ASSERT(g_impl != nullptr);
|
||||
|
||||
// Check that we're allowed to register
|
||||
R_UNLESS(FsSrv::Impl::IsInitialProgram(system, m_process_id), ResultPermissionDenied);
|
||||
|
||||
// Unregister the program
|
||||
R_RETURN(g_impl->UnregisterProgramInfo(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);
|
||||
}
|
||||
|
||||
} // namespace FileSys::FsSrv
|
46
src/core/file_sys/fssrv/fssrv_program_registry_impl.h
Normal file
46
src/core/file_sys/fssrv/fssrv_program_registry_impl.h
Normal file
@ -0,0 +1,46 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_funcs.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;
|
||||
|
||||
namespace Impl {
|
||||
class ProgramInfo;
|
||||
}
|
||||
|
||||
class ProgramRegistryImpl {
|
||||
YUZU_NON_COPYABLE(ProgramRegistryImpl);
|
||||
YUZU_NON_MOVEABLE(ProgramRegistryImpl);
|
||||
|
||||
public:
|
||||
ProgramRegistryImpl(Core::System& system_);
|
||||
~ProgramRegistryImpl();
|
||||
|
||||
static void Initialize(ProgramRegistryServiceImpl* service);
|
||||
|
||||
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);
|
||||
Result UnregisterProgram(u64 process_id);
|
||||
Result SetCurrentProcess(const Service::ClientProcessId& client_pid);
|
||||
Result SetEnabledProgramVerification(bool enabled);
|
||||
|
||||
private:
|
||||
u64 m_process_id;
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
} // namespace FileSys::FsSrv
|
57
src/core/file_sys/fssrv/fssrv_program_registry_service.cpp
Normal file
57
src/core/file_sys/fssrv/fssrv_program_registry_service.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// 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_index_map_info_manager.h"
|
||||
#include "core/file_sys/fssrv/impl/fssrv_program_info.h"
|
||||
#include "core/file_sys/fssrv/impl/fssrv_program_registry_manager.h"
|
||||
|
||||
namespace FileSys::FsSrv {
|
||||
|
||||
ProgramRegistryServiceImpl::ProgramRegistryServiceImpl(Core::System& system_,
|
||||
const Configuration& cfg)
|
||||
: m_config(cfg), m_registry_manager(std::make_unique<Impl::ProgramRegistryManager>(system_)),
|
||||
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::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
|
48
src/core/file_sys/fssrv/fssrv_program_registry_service.h
Normal file
48
src/core/file_sys/fssrv/fssrv_program_registry_service.h
Normal file
@ -0,0 +1,48 @@
|
||||
// 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/hle/result.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys::FsSrv {
|
||||
|
||||
namespace Impl {
|
||||
class ProgramInfo;
|
||||
class ProgramRegistryManager;
|
||||
class ProgramIndexMapInfoManager;
|
||||
} // namespace Impl
|
||||
|
||||
class ProgramRegistryServiceImpl {
|
||||
public:
|
||||
struct Configuration {};
|
||||
|
||||
ProgramRegistryServiceImpl(Core::System& system_, 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);
|
||||
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
|
592
src/core/file_sys/fssrv/impl/fssrv_access_control.cpp
Normal file
592
src/core/file_sys/fssrv/impl/fssrv_access_control.cpp
Normal file
@ -0,0 +1,592 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/enum_util.h"
|
||||
#include "core/file_sys/fssrv/impl/fssrv_access_control.h"
|
||||
|
||||
namespace FileSys::FsSrv {
|
||||
|
||||
namespace {
|
||||
constinit bool g_is_debug_flag_enabled = false;
|
||||
}
|
||||
|
||||
bool IsDebugFlagEnabled() {
|
||||
return g_is_debug_flag_enabled;
|
||||
}
|
||||
|
||||
void SetDebugFlagEnabled(bool enabled) {
|
||||
// Set global debug flag
|
||||
g_is_debug_flag_enabled = enabled;
|
||||
}
|
||||
|
||||
namespace Impl {
|
||||
|
||||
namespace {
|
||||
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,
|
||||
g_is_debug_flag_enabled ? AllFlagBitsMask : 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() && g_is_debug_flag_enabled, 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() && g_is_debug_flag_enabled;
|
||||
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
|
260
src/core/file_sys/fssrv/impl/fssrv_access_control.h
Normal file
260
src/core/file_sys/fssrv/impl/fssrv_access_control.h
Normal file
@ -0,0 +1,260 @@
|
||||
// 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 {
|
||||
|
||||
bool IsDebugFlagEnabled();
|
||||
void SetDebugFlagEnabled(bool enabled);
|
||||
|
||||
} // namespace FileSys::FsSrv
|
||||
|
||||
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
|
268
src/core/file_sys/fssrv/impl/fssrv_access_control_bits.h
Normal file
268
src/core/file_sys/fssrv/impl/fssrv_access_control_bits.h
Normal 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
|
@ -0,0 +1,155 @@
|
||||
// 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 Common::IntrusiveListBaseNode<ProgramIndexMapInfoEntry> {
|
||||
u64 program_id;
|
||||
u64 base_program_id;
|
||||
u8 program_index;
|
||||
};
|
||||
|
||||
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
|
128
src/core/file_sys/fssrv/impl/fssrv_program_info.cpp
Normal file
128
src/core/file_sys/fssrv/impl/fssrv_program_info.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
// 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"
|
||||
|
||||
namespace FileSys::FsSrv::Impl {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit std::aligned_storage<0x80>::type g_static_buffer_for_program_info_for_initial_process =
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
class StaticAllocatorForProgramInfoForInitialProcess : public std::allocator<T> {
|
||||
public:
|
||||
StaticAllocatorForProgramInfoForInitialProcess() {}
|
||||
|
||||
template <typename U>
|
||||
StaticAllocatorForProgramInfoForInitialProcess(
|
||||
const StaticAllocatorForProgramInfoForInitialProcess<U>&) {}
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
using other = StaticAllocatorForProgramInfoForInitialProcess<U>;
|
||||
};
|
||||
|
||||
[[nodiscard]] T* allocate(::std::size_t n) {
|
||||
ASSERT(sizeof(T) * n <= sizeof(g_static_buffer_for_program_info_for_initial_process));
|
||||
return reinterpret_cast<T*>(
|
||||
std::addressof(g_static_buffer_for_program_info_for_initial_process));
|
||||
}
|
||||
|
||||
void deallocate([[maybe_unused]] T* p, [[maybe_unused]] std::size_t n) {
|
||||
// No-op
|
||||
}
|
||||
};
|
||||
|
||||
constexpr const u32 FileAccessControlForInitialProgram[0x1C / sizeof(u32)] = {
|
||||
0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
|
||||
constexpr const u32 FileAccessControlDescForInitialProgram[0x2C / sizeof(u32)] = {
|
||||
0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
constinit bool g_initialized = false;
|
||||
|
||||
constinit u64 g_initial_process_id_min = 0;
|
||||
constinit u64 g_initial_process_id_max = 0;
|
||||
|
||||
constinit u64 g_current_process_id = 0;
|
||||
|
||||
void InitializeInitialAndCurrentProcessId(Core::System& system) {
|
||||
using namespace Kernel;
|
||||
|
||||
if (!g_initialized) {
|
||||
// Get initial process id range
|
||||
ASSERT(Svc::GetSystemInfo(system, std::addressof(g_initial_process_id_min),
|
||||
Svc::SystemInfoType::InitialProcessIdRange, Svc::InvalidHandle,
|
||||
static_cast<u64>(Svc::InitialProcessIdRangeInfo::Minimum)) ==
|
||||
ResultSuccess);
|
||||
ASSERT(Svc::GetSystemInfo(system, std::addressof(g_initial_process_id_max),
|
||||
Svc::SystemInfoType::InitialProcessIdRange, Svc::InvalidHandle,
|
||||
static_cast<u64>(Svc::InitialProcessIdRangeInfo::Maximum)) ==
|
||||
ResultSuccess);
|
||||
|
||||
ASSERT(0 < g_initial_process_id_min);
|
||||
ASSERT(g_initial_process_id_min <= g_initial_process_id_max);
|
||||
|
||||
// Get current procss id
|
||||
ASSERT(Svc::GetProcessId(system, std::addressof(g_current_process_id),
|
||||
Svc::PseudoHandle::CurrentProcess) == ResultSuccess);
|
||||
|
||||
/* Set initialized. */
|
||||
g_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<ProgramInfo> ProgramInfo::GetProgramInfoForInitialProcess() {
|
||||
class ProgramInfoHelper : public ProgramInfo {
|
||||
public:
|
||||
ProgramInfoHelper(const void* data, s64 data_size, const void* desc, s64 desc_size)
|
||||
: ProgramInfo(data, data_size, desc, desc_size) {}
|
||||
};
|
||||
|
||||
static constinit Common::TypedStorage<std::shared_ptr<ProgramInfo>>
|
||||
s_fls_storage_for_s_initial_program_info{};
|
||||
static constinit bool s_fls_initialized_s_initial_program_info = false;
|
||||
static std::mutex s_fls_init_lock_s_initial_program_info{};
|
||||
if (!(s_fls_initialized_s_initial_program_info)) {
|
||||
std::scoped_lock sl_fls_for_s_initial_program_info{s_fls_init_lock_s_initial_program_info};
|
||||
if (!(s_fls_initialized_s_initial_program_info)) {
|
||||
new (Common::Impl::GetPointerForConstructAt(s_fls_storage_for_s_initial_program_info))
|
||||
std::shared_ptr<ProgramInfo>(std::allocate_shared<ProgramInfoHelper>(
|
||||
StaticAllocatorForProgramInfoForInitialProcess<char>{},
|
||||
FileAccessControlForInitialProgram, sizeof(FileAccessControlForInitialProgram),
|
||||
FileAccessControlDescForInitialProgram,
|
||||
sizeof(FileAccessControlDescForInitialProgram)));
|
||||
s_fls_initialized_s_initial_program_info = true;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<ProgramInfo>& s_initial_program_info =
|
||||
Common::GetReference(s_fls_storage_for_s_initial_program_info);
|
||||
|
||||
return s_initial_program_info;
|
||||
}
|
||||
|
||||
bool IsInitialProgram(Core::System& system, u64 process_id) {
|
||||
// Initialize/sanity check
|
||||
InitializeInitialAndCurrentProcessId(system);
|
||||
ASSERT(g_initial_process_id_min > 0);
|
||||
|
||||
// Check process id in range
|
||||
return g_initial_process_id_min <= process_id && process_id <= g_initial_process_id_max;
|
||||
}
|
||||
|
||||
bool IsCurrentProcess(Core::System& system, u64 process_id) {
|
||||
// Initialize
|
||||
InitializeInitialAndCurrentProcessId(system);
|
||||
|
||||
return process_id == g_current_process_id;
|
||||
}
|
||||
|
||||
} // namespace FileSys::FsSrv::Impl
|
65
src/core/file_sys/fssrv/impl/fssrv_program_info.h
Normal file
65
src/core/file_sys/fssrv/impl/fssrv_program_info.h
Normal file
@ -0,0 +1,65 @@
|
||||
// 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"
|
||||
|
||||
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;
|
||||
|
||||
public:
|
||||
ProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void* data, s64 data_size,
|
||||
const void* desc, s64 desc_size)
|
||||
: 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static std::shared_ptr<ProgramInfo> GetProgramInfoForInitialProcess();
|
||||
|
||||
private:
|
||||
const u64 InvalidProgramId = {};
|
||||
ProgramInfo(const void* data, s64 data_size, const void* desc, s64 desc_size)
|
||||
: m_process_id(InvalidProcessId), m_program_id(InvalidProgramId),
|
||||
m_storage_id(static_cast<FileSys::StorageId>(0)),
|
||||
m_access_control(data, data_size, desc, desc_size, std::numeric_limits<u64>::max()) {}
|
||||
};
|
||||
|
||||
struct ProgramInfoNode : public Common::IntrusiveListBaseNode<ProgramInfoNode> {
|
||||
std::shared_ptr<ProgramInfo> program_info;
|
||||
};
|
||||
|
||||
bool IsInitialProgram(Core::System& system, u64 process_id);
|
||||
bool IsCurrentProcess(Core::System& system, u64 process_id);
|
||||
|
||||
} // namespace FileSys::FsSrv::Impl
|
100
src/core/file_sys/fssrv/impl/fssrv_program_registry_manager.cpp
Normal file
100
src/core/file_sys/fssrv/impl/fssrv_program_registry_manager.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
// 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_) : 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) {
|
||||
// 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);
|
||||
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 (IsInitialProgram(system, process_id)) {
|
||||
*out = ProgramInfo::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
|
@ -0,0 +1,39 @@
|
||||
// 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"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys::FsSrv::Impl {
|
||||
|
||||
class ProgramRegistryManager {
|
||||
YUZU_NON_COPYABLE(ProgramRegistryManager);
|
||||
YUZU_NON_MOVEABLE(ProgramRegistryManager);
|
||||
|
||||
public:
|
||||
explicit ProgramRegistryManager(Core::System& system_);
|
||||
|
||||
Result RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const void* data,
|
||||
s64 data_size, const void* desc, s64 desc_size);
|
||||
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{};
|
||||
mutable std::mutex m_mutex{};
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
} // namespace FileSys::FsSrv::Impl
|
193
src/core/file_sys/fssrv/impl/fssrv_save_data_properties.h
Normal file
193
src/core/file_sys/fssrv/impl/fssrv_save_data_properties.h
Normal file
@ -0,0 +1,193 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// TODO: Properly credit LibHac before this gets merged
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/savedata_factory.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::SystemSaveData:
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
case SaveDataType::CacheStorage:
|
||||
return true;
|
||||
case SaveDataType::TemporaryStorage:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsMultiCommitSupported(SaveDataType type) {
|
||||
switch (type) {
|
||||
case SaveDataType::SystemSaveData:
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
return true;
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::TemporaryStorage:
|
||||
case SaveDataType::CacheStorage:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSharedOpenNeeded(SaveDataType type) {
|
||||
switch (type) {
|
||||
case SaveDataType::SystemSaveData:
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::TemporaryStorage:
|
||||
case SaveDataType::CacheStorage:
|
||||
return false;
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
return true;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CanUseIndexerReservedArea(SaveDataType type) {
|
||||
switch (type) {
|
||||
case SaveDataType::SystemSaveData:
|
||||
return true;
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
case SaveDataType::TemporaryStorage:
|
||||
case SaveDataType::CacheStorage:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSystemSaveData(SaveDataType type) {
|
||||
switch (type) {
|
||||
case SaveDataType::SystemSaveData:
|
||||
return true;
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
case SaveDataType::TemporaryStorage:
|
||||
case SaveDataType::CacheStorage:
|
||||
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::SystemSaveData:
|
||||
break;
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
case SaveDataType::TemporaryStorage:
|
||||
case SaveDataType::CacheStorage:
|
||||
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::SystemSaveData:
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
case SaveDataType::TemporaryStorage:
|
||||
return false;
|
||||
case SaveDataType::CacheStorage:
|
||||
return space_id == SaveDataSpaceId::NandUser || space_id == SaveDataSpaceId::SdCardUser;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsReconstructible(SaveDataType type, SaveDataSpaceId space_id) {
|
||||
switch (space_id) {
|
||||
case SaveDataSpaceId::NandSystem:
|
||||
case SaveDataSpaceId::NandUser:
|
||||
case SaveDataSpaceId::ProperSystem:
|
||||
case SaveDataSpaceId::SafeMode:
|
||||
switch (type) {
|
||||
case SaveDataType::SystemSaveData:
|
||||
case SaveDataType::SaveData:
|
||||
case SaveDataType::DeviceSaveData:
|
||||
return false;
|
||||
case SaveDataType::BcatDeliveryCacheStorage:
|
||||
case SaveDataType::TemporaryStorage:
|
||||
case SaveDataType::CacheStorage:
|
||||
return true;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
case SaveDataSpaceId::SdCardSystem:
|
||||
case SaveDataSpaceId::TemporaryStorage:
|
||||
case SaveDataSpaceId::SdCardUser:
|
||||
return true;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace FileSys::FsSrv::Impl
|
Loading…
Reference in New Issue
Block a user