Merge pull request #11825 from AdmiralCurtiss/ios-split-es-fs
IOS: Further deglobalization and emulation/maintainance code splitting.
This commit is contained in:
commit
e0ef474d95
|
@ -160,7 +160,7 @@ JNIEXPORT jboolean JNICALL
|
||||||
Java_org_dolphinemu_dolphinemu_utils_WiiUtils_isSystemMenuInstalled(JNIEnv* env, jclass)
|
Java_org_dolphinemu_dolphinemu_utils_WiiUtils_isSystemMenuInstalled(JNIEnv* env, jclass)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
const auto tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
|
const auto tmd = ios.GetESCore().FindInstalledTMD(Titles::SYSTEM_MENU);
|
||||||
|
|
||||||
return tmd.IsValid();
|
return tmd.IsValid();
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ JNIEXPORT jboolean JNICALL
|
||||||
Java_org_dolphinemu_dolphinemu_utils_WiiUtils_isSystemMenuvWii(JNIEnv* env, jclass)
|
Java_org_dolphinemu_dolphinemu_utils_WiiUtils_isSystemMenuvWii(JNIEnv* env, jclass)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
const auto tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
|
const auto tmd = ios.GetESCore().FindInstalledTMD(Titles::SYSTEM_MENU);
|
||||||
|
|
||||||
return tmd.IsvWii();
|
return tmd.IsvWii();
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ JNIEXPORT jstring JNICALL
|
||||||
Java_org_dolphinemu_dolphinemu_utils_WiiUtils_getSystemMenuVersion(JNIEnv* env, jclass)
|
Java_org_dolphinemu_dolphinemu_utils_WiiUtils_getSystemMenuVersion(JNIEnv* env, jclass)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
const auto tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
|
const auto tmd = ios.GetESCore().FindInstalledTMD(Titles::SYSTEM_MENU);
|
||||||
|
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
{
|
{
|
||||||
|
|
|
@ -690,8 +690,8 @@ void UpdateStateFlags(std::function<void(StateFlags*)> update_function)
|
||||||
|
|
||||||
void CreateSystemMenuTitleDirs()
|
void CreateSystemMenuTitleDirs()
|
||||||
{
|
{
|
||||||
const auto es = IOS::HLE::GetIOS()->GetES();
|
const auto& es = IOS::HLE::GetIOS()->GetESCore();
|
||||||
es->CreateTitleDirectories(Titles::SYSTEM_MENU, IOS::SYSMENU_GID);
|
es.CreateTitleDirectories(Titles::SYSTEM_MENU, IOS::SYSMENU_GID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddRiivolutionPatches(BootParameters* boot_params,
|
void AddRiivolutionPatches(BootParameters* boot_params,
|
||||||
|
|
|
@ -595,7 +595,7 @@ bool CBoot::EmulatedBS2_Wii(Core::System& system, const Core::CPUThreadGuard& gu
|
||||||
|
|
||||||
// Warning: This call will set incorrect running game metadata if our volume parameter
|
// Warning: This call will set incorrect running game metadata if our volume parameter
|
||||||
// doesn't point to the same disc as the one that's inserted in the emulated disc drive!
|
// doesn't point to the same disc as the one that's inserted in the emulated disc drive!
|
||||||
IOS::HLE::GetIOS()->GetES()->DIVerify(tmd, volume.GetTicket(partition));
|
IOS::HLE::GetIOS()->GetESDevice()->DIVerify(tmd, volume.GetTicket(partition));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ bool CBoot::BootNANDTitle(Core::System& system, const u64 title_id)
|
||||||
state->type = 0x04; // TYPE_NANDBOOT
|
state->type = 0x04; // TYPE_NANDBOOT
|
||||||
});
|
});
|
||||||
|
|
||||||
auto es = IOS::HLE::GetIOS()->GetES();
|
auto es = IOS::HLE::GetIOS()->GetESDevice();
|
||||||
const IOS::ES::TicketReader ticket = es->FindSignedTicket(title_id);
|
const IOS::ES::TicketReader ticket = es->GetCore().FindSignedTicket(title_id);
|
||||||
auto console_type = IOS::HLE::IOSC::ConsoleType::Retail;
|
auto console_type = IOS::HLE::IOSC::ConsoleType::Retail;
|
||||||
if (ticket.IsValid())
|
if (ticket.IsValid())
|
||||||
console_type = ticket.GetConsoleType();
|
console_type = ticket.GetConsoleType();
|
||||||
|
|
|
@ -286,7 +286,7 @@ struct SetGameMetadata
|
||||||
bool operator()(const BootParameters::NANDTitle& nand_title) const
|
bool operator()(const BootParameters::NANDTitle& nand_title) const
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
const IOS::ES::TMDReader tmd = ios.GetES()->FindInstalledTMD(nand_title.id);
|
const IOS::ES::TMDReader tmd = ios.GetESCore().FindInstalledTMD(nand_title.id);
|
||||||
if (!tmd.IsValid() || !IOS::ES::IsChannel(nand_title.id))
|
if (!tmd.IsValid() || !IOS::ES::IsChannel(nand_title.id))
|
||||||
{
|
{
|
||||||
PanicAlertFmtT("This title cannot be booted.");
|
PanicAlertFmtT("This title cannot be booted.");
|
||||||
|
|
|
@ -553,7 +553,7 @@ CopyResult Import(const std::string& data_bin_path, std::function<bool()> can_ov
|
||||||
return CopyResult::CorruptedSource;
|
return CopyResult::CorruptedSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WiiUtils::EnsureTMDIsImported(*ios.GetFS(), *ios.GetES(), header->tid))
|
if (!WiiUtils::EnsureTMDIsImported(*ios.GetFS(), ios.GetESCore(), header->tid))
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CORE, "WiiSave::Import: Failed to find or import TMD for title {:16x}",
|
ERROR_LOG_FMT(CORE, "WiiSave::Import: Failed to find or import TMD for title {:16x}",
|
||||||
header->tid);
|
header->tid);
|
||||||
|
@ -585,7 +585,7 @@ size_t ExportAll(std::string_view export_path)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
size_t exported_save_count = 0;
|
size_t exported_save_count = 0;
|
||||||
for (const u64 title : ios.GetES()->GetInstalledTitles())
|
for (const u64 title : ios.GetESCore().GetInstalledTitles())
|
||||||
{
|
{
|
||||||
if (Export(title, export_path, &ios) == CopyResult::Success)
|
if (Export(title, export_path, &ios) == CopyResult::Success)
|
||||||
++exported_save_count;
|
++exported_save_count;
|
||||||
|
|
|
@ -736,7 +736,8 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
|
||||||
const std::vector<u8>& raw_tmd = tmd.GetBytes();
|
const std::vector<u8>& raw_tmd = tmd.GetBytes();
|
||||||
memory.CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
|
memory.CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
|
||||||
|
|
||||||
ReturnCode es_result = m_ios.GetES()->DIVerify(tmd, dvd_thread.GetTicket(m_current_partition));
|
ReturnCode es_result = GetEmulationKernel().GetESDevice()->DIVerify(
|
||||||
|
tmd, dvd_thread.GetTicket(m_current_partition));
|
||||||
memory.Write_U32(es_result, request.io_vectors[1].address);
|
memory.Write_U32(es_result, request.io_vectors[1].address);
|
||||||
|
|
||||||
return_value = DIResult::Success;
|
return_value = DIResult::Success;
|
||||||
|
|
|
@ -28,7 +28,7 @@ OpenRequest::OpenRequest(Core::System& system, const u32 address_) : Request(sys
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
path = memory.GetString(memory.Read_U32(address + 0xc));
|
path = memory.GetString(memory.Read_U32(address + 0xc));
|
||||||
flags = static_cast<OpenMode>(memory.Read_U32(address + 0x10));
|
flags = static_cast<OpenMode>(memory.Read_U32(address + 0x10));
|
||||||
const Kernel* ios = GetIOS();
|
const EmulationKernel* ios = GetIOS();
|
||||||
if (ios)
|
if (ios)
|
||||||
{
|
{
|
||||||
uid = ios->GetUidForPPC();
|
uid = ios->GetUidForPPC();
|
||||||
|
|
|
@ -81,7 +81,7 @@ constexpr SystemTimers::TimeBaseTick GetESBootTicks(u32 ios_version)
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ESDevice::ESDevice(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
|
ESCore::ESCore(Kernel& ios) : m_ios(ios)
|
||||||
{
|
{
|
||||||
for (const auto& directory : s_directories_to_create)
|
for (const auto& directory : s_directories_to_create)
|
||||||
{
|
{
|
||||||
|
@ -101,13 +101,19 @@ ESDevice::ESDevice(Kernel& ios, const std::string& device_name) : Device(ios, de
|
||||||
}
|
}
|
||||||
|
|
||||||
FinishAllStaleImports();
|
FinishAllStaleImports();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESCore::~ESCore() = default;
|
||||||
|
|
||||||
|
ESDevice::ESDevice(EmulationKernel& ios, ESCore& core, const std::string& device_name)
|
||||||
|
: EmulationDevice(ios, device_name), m_core(core)
|
||||||
|
{
|
||||||
if (Core::IsRunningAndStarted())
|
if (Core::IsRunningAndStarted())
|
||||||
{
|
{
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = ios.GetSystem();
|
||||||
auto& core_timing = system.GetCoreTiming();
|
auto& core_timing = system.GetCoreTiming();
|
||||||
core_timing.RemoveEvent(s_finish_init_event);
|
core_timing.RemoveEvent(s_finish_init_event);
|
||||||
core_timing.ScheduleEvent(GetESBootTicks(m_ios.GetVersion()), s_finish_init_event);
|
core_timing.ScheduleEvent(GetESBootTicks(ios.GetVersion()), s_finish_init_event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -115,19 +121,23 @@ ESDevice::ESDevice(Kernel& ios, const std::string& device_name) : Device(ios, de
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESDevice::~ESDevice() = default;
|
||||||
|
|
||||||
void ESDevice::InitializeEmulationState()
|
void ESDevice::InitializeEmulationState()
|
||||||
{
|
{
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
auto& core_timing = system.GetCoreTiming();
|
auto& core_timing = system.GetCoreTiming();
|
||||||
s_finish_init_event = core_timing.RegisterEvent(
|
s_finish_init_event =
|
||||||
"IOS-ESFinishInit", [](Core::System& system_, u64, s64) { GetIOS()->GetES()->FinishInit(); });
|
core_timing.RegisterEvent("IOS-ESFinishInit", [](Core::System& system_, u64, s64) {
|
||||||
|
GetIOS()->GetESDevice()->FinishInit();
|
||||||
|
});
|
||||||
s_reload_ios_for_ppc_launch_event = core_timing.RegisterEvent(
|
s_reload_ios_for_ppc_launch_event = core_timing.RegisterEvent(
|
||||||
"IOS-ESReloadIOSForPPCLaunch", [](Core::System& system_, u64 ios_id, s64) {
|
"IOS-ESReloadIOSForPPCLaunch", [](Core::System& system_, u64 ios_id, s64) {
|
||||||
GetIOS()->GetES()->LaunchTitle(ios_id, HangPPC::Yes);
|
GetIOS()->GetESDevice()->LaunchTitle(ios_id, HangPPC::Yes);
|
||||||
});
|
});
|
||||||
s_bootstrap_ppc_for_launch_event =
|
s_bootstrap_ppc_for_launch_event =
|
||||||
core_timing.RegisterEvent("IOS-ESBootstrapPPCForLaunch", [](Core::System& system_, u64, s64) {
|
core_timing.RegisterEvent("IOS-ESBootstrapPPCForLaunch", [](Core::System& system_, u64, s64) {
|
||||||
GetIOS()->GetES()->BootstrapPPC();
|
GetIOS()->GetESDevice()->BootstrapPPC();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,13 +150,13 @@ void ESDevice::FinalizeEmulationState()
|
||||||
|
|
||||||
void ESDevice::FinishInit()
|
void ESDevice::FinishInit()
|
||||||
{
|
{
|
||||||
m_ios.InitIPC();
|
GetEmulationKernel().InitIPC();
|
||||||
|
|
||||||
std::optional<u64> pending_launch_title_id;
|
std::optional<u64> pending_launch_title_id;
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto launch_file =
|
const auto launch_file = GetEmulationKernel().GetFS()->OpenFile(
|
||||||
m_ios.GetFS()->OpenFile(PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, FS::Mode::Read);
|
PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, FS::Mode::Read);
|
||||||
if (launch_file)
|
if (launch_file)
|
||||||
{
|
{
|
||||||
u64 id;
|
u64 id;
|
||||||
|
@ -202,7 +212,7 @@ IPCReply ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 1))
|
if (!request.HasNumberOfValidVectors(1, 1))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
|
@ -215,7 +225,7 @@ IPCReply ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::GetTitleId(u64* title_id) const
|
ReturnCode ESCore::GetTitleId(u64* title_id) const
|
||||||
{
|
{
|
||||||
if (!m_title_context.active)
|
if (!m_title_context.active)
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -229,11 +239,11 @@ IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
const ReturnCode ret = GetTitleId(&title_id);
|
const ReturnCode ret = m_core.GetTitleId(&title_id);
|
||||||
if (ret != IPC_SUCCESS)
|
if (ret != IPC_SUCCESS)
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
memory.Write_U64(title_id, request.io_vectors[0].address);
|
memory.Write_U64(title_id, request.io_vectors[0].address);
|
||||||
|
@ -242,9 +252,9 @@ IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
|
static bool UpdateUIDAndGID(EmulationKernel& kernel, const ES::TMDReader& tmd)
|
||||||
{
|
{
|
||||||
ES::UIDSys uid_sys{kernel.GetFSDevice()};
|
ES::UIDSys uid_sys{kernel.GetFSCore()};
|
||||||
const u64 title_id = tmd.GetTitleId();
|
const u64 title_id = tmd.GetTitleId();
|
||||||
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
|
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
|
||||||
if (uid == 0)
|
if (uid == 0)
|
||||||
|
@ -257,10 +267,10 @@ static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid,
|
static ReturnCode CheckIsAllowedToSetUID(EmulationKernel& kernel, const u32 caller_uid,
|
||||||
const ES::TMDReader& active_tmd)
|
const ES::TMDReader& active_tmd)
|
||||||
{
|
{
|
||||||
ES::UIDSys uid_map{kernel.GetFSDevice()};
|
ES::UIDSys uid_map{kernel.GetFSCore()};
|
||||||
const u32 system_menu_uid = uid_map.GetOrInsertUIDForTitle(Titles::SYSTEM_MENU);
|
const u32 system_menu_uid = uid_map.GetOrInsertUIDForTitle(Titles::SYSTEM_MENU);
|
||||||
if (!system_menu_uid)
|
if (!system_menu_uid)
|
||||||
return ES_SHORT_READ;
|
return ES_SHORT_READ;
|
||||||
|
@ -284,23 +294,23 @@ IPCReply ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
|
|
||||||
const s32 ret = CheckIsAllowedToSetUID(m_ios, uid, m_title_context.tmd);
|
const s32 ret = CheckIsAllowedToSetUID(GetEmulationKernel(), uid, m_core.m_title_context.tmd);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(IOS_ES, "SetUID: Permission check failed with error {}", ret);
|
ERROR_LOG_FMT(IOS_ES, "SetUID: Permission check failed with error {}", ret);
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto tmd = FindInstalledTMD(title_id);
|
const auto tmd = m_core.FindInstalledTMD(title_id);
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(FS_ENOENT);
|
return IPCReply(FS_ENOENT);
|
||||||
|
|
||||||
if (!UpdateUIDAndGID(m_ios, tmd))
|
if (!UpdateUIDAndGID(GetEmulationKernel(), tmd))
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(IOS_ES, "SetUID: Failed to get UID for title {:016x}", title_id);
|
ERROR_LOG_FMT(IOS_ES, "SetUID: Failed to get UID for title {:016x}", title_id);
|
||||||
return IPCReply(ES_SHORT_READ);
|
return IPCReply(ES_SHORT_READ);
|
||||||
|
@ -311,13 +321,13 @@ IPCReply ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
|
||||||
|
|
||||||
bool ESDevice::LaunchTitle(u64 title_id, HangPPC hang_ppc)
|
bool ESDevice::LaunchTitle(u64 title_id, HangPPC hang_ppc)
|
||||||
{
|
{
|
||||||
m_title_context.Clear();
|
m_core.m_title_context.Clear();
|
||||||
INFO_LOG_FMT(IOS_ES, "ES_Launch: Title context changed: (none)");
|
INFO_LOG_FMT(IOS_ES, "ES_Launch: Title context changed: (none)");
|
||||||
|
|
||||||
NOTICE_LOG_FMT(IOS_ES, "Launching title {:016x}...", title_id);
|
NOTICE_LOG_FMT(IOS_ES, "Launching title {:016x}...", title_id);
|
||||||
|
|
||||||
if ((title_id == Titles::SHOP || title_id == Titles::KOREAN_SHOP) &&
|
if ((title_id == Titles::SHOP || title_id == Titles::KOREAN_SHOP) &&
|
||||||
m_ios.GetIOSC().IsUsingDefaultId())
|
GetEmulationKernel().GetIOSC().IsUsingDefaultId())
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(IOS_ES, "Refusing to launch the shop channel with default device credentials");
|
ERROR_LOG_FMT(IOS_ES, "Refusing to launch the shop channel with default device credentials");
|
||||||
CriticalAlertFmtT(
|
CriticalAlertFmtT(
|
||||||
|
@ -358,12 +368,12 @@ bool ESDevice::LaunchIOS(u64 ios_title_id, HangPPC hang_ppc)
|
||||||
// so only have this check for MIOS (for which having the binary is *required*).
|
// so only have this check for MIOS (for which having the binary is *required*).
|
||||||
if (ios_title_id == Titles::MIOS)
|
if (ios_title_id == Titles::MIOS)
|
||||||
{
|
{
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(ios_title_id);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(ios_title_id);
|
||||||
const ES::TicketReader ticket = FindSignedTicket(ios_title_id);
|
const ES::TicketReader ticket = m_core.FindSignedTicket(ios_title_id);
|
||||||
ES::Content content;
|
ES::Content content;
|
||||||
if (!tmd.IsValid() || !ticket.IsValid() || !tmd.GetContent(tmd.GetBootIndex(), &content) ||
|
if (!tmd.IsValid() || !ticket.IsValid() || !tmd.GetContent(tmd.GetBootIndex(), &content) ||
|
||||||
!m_ios.BootIOS(Core::System::GetInstance(), ios_title_id, hang_ppc,
|
!GetEmulationKernel().BootIOS(GetSystem(), ios_title_id, hang_ppc,
|
||||||
GetContentPath(ios_title_id, content)))
|
m_core.GetContentPath(ios_title_id, content)))
|
||||||
{
|
{
|
||||||
PanicAlertFmtT("Could not launch IOS {0:016x} because it is missing from the NAND.\n"
|
PanicAlertFmtT("Could not launch IOS {0:016x} because it is missing from the NAND.\n"
|
||||||
"The emulated software will likely hang now.",
|
"The emulated software will likely hang now.",
|
||||||
|
@ -373,12 +383,12 @@ bool ESDevice::LaunchIOS(u64 ios_title_id, HangPPC hang_ppc)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_ios.BootIOS(Core::System::GetInstance(), ios_title_id, hang_ppc);
|
return GetEmulationKernel().BootIOS(GetSystem(), ios_title_id, hang_ppc);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ESDevice::WriteLaunchFile(const ES::TMDReader& tmd, Ticks ticks)
|
s32 ESDevice::WriteLaunchFile(const ES::TMDReader& tmd, Ticks ticks)
|
||||||
{
|
{
|
||||||
m_ios.GetFSDevice()->DeleteFile(PID_KERNEL, PID_KERNEL, SPACE_FILE_PATH, ticks);
|
GetEmulationKernel().GetFSCore().DeleteFile(PID_KERNEL, PID_KERNEL, SPACE_FILE_PATH, ticks);
|
||||||
|
|
||||||
std::vector<u8> launch_data(sizeof(u64) + sizeof(ES::TicketView));
|
std::vector<u8> launch_data(sizeof(u64) + sizeof(ES::TicketView));
|
||||||
const u64 title_id = tmd.GetTitleId();
|
const u64 title_id = tmd.GetTitleId();
|
||||||
|
@ -393,8 +403,8 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
||||||
{
|
{
|
||||||
u64 ticks = 0;
|
u64 ticks = 0;
|
||||||
|
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(title_id, &ticks);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(title_id, &ticks);
|
||||||
const ES::TicketReader ticket = FindSignedTicket(title_id);
|
const ES::TicketReader ticket = m_core.FindSignedTicket(title_id);
|
||||||
|
|
||||||
if (!tmd.IsValid() || !ticket.IsValid())
|
if (!tmd.IsValid() || !ticket.IsValid())
|
||||||
{
|
{
|
||||||
|
@ -412,7 +422,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& core_timing = system.GetCoreTiming();
|
auto& core_timing = system.GetCoreTiming();
|
||||||
|
|
||||||
// Before launching a title, IOS first reads the TMD and reloads into the specified IOS version,
|
// Before launching a title, IOS first reads the TMD and reloads into the specified IOS version,
|
||||||
|
@ -422,7 +432,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
||||||
// To keep track of the PPC title launch, a temporary launch file (LAUNCH_FILE_PATH) is used
|
// To keep track of the PPC title launch, a temporary launch file (LAUNCH_FILE_PATH) is used
|
||||||
// to store the title ID of the title to launch and its TMD.
|
// to store the title ID of the title to launch and its TMD.
|
||||||
// The launch file not existing means an IOS reload is required.
|
// The launch file not existing means an IOS reload is required.
|
||||||
if (const auto launch_file_fd = m_ios.GetFSDevice()->Open(
|
if (const auto launch_file_fd = GetEmulationKernel().GetFSCore().Open(
|
||||||
PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, FS::Mode::Read, {}, &ticks);
|
PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, FS::Mode::Read, {}, &ticks);
|
||||||
launch_file_fd.Get() < 0)
|
launch_file_fd.Get() < 0)
|
||||||
{
|
{
|
||||||
|
@ -442,17 +452,17 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
||||||
|
|
||||||
// Otherwise, assume that the PPC title can now be launched directly.
|
// Otherwise, assume that the PPC title can now be launched directly.
|
||||||
// Unlike IOS, we won't bother checking the title ID in the launch file. (It's not useful.)
|
// Unlike IOS, we won't bother checking the title ID in the launch file. (It's not useful.)
|
||||||
m_ios.GetFSDevice()->DeleteFile(PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, &ticks);
|
GetEmulationKernel().GetFSCore().DeleteFile(PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, &ticks);
|
||||||
WriteSystemFile(SPACE_FILE_PATH, std::vector<u8>(SPACE_FILE_SIZE), &ticks);
|
WriteSystemFile(SPACE_FILE_PATH, std::vector<u8>(SPACE_FILE_SIZE), &ticks);
|
||||||
|
|
||||||
m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiWAD);
|
m_core.m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiWAD);
|
||||||
INFO_LOG_FMT(IOS_ES, "LaunchPPCTitle: Title context changed: {:016x}", tmd.GetTitleId());
|
INFO_LOG_FMT(IOS_ES, "LaunchPPCTitle: Title context changed: {:016x}", tmd.GetTitleId());
|
||||||
|
|
||||||
// Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles
|
// Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles
|
||||||
// are installed, we can only do this for PPC titles.
|
// are installed, we can only do this for PPC titles.
|
||||||
if (!UpdateUIDAndGID(m_ios, m_title_context.tmd))
|
if (!UpdateUIDAndGID(GetEmulationKernel(), m_core.m_title_context.tmd))
|
||||||
{
|
{
|
||||||
m_title_context.Clear();
|
m_core.m_title_context.Clear();
|
||||||
INFO_LOG_FMT(IOS_ES, "LaunchPPCTitle: Title context changed: (none)");
|
INFO_LOG_FMT(IOS_ES, "LaunchPPCTitle: Title context changed: (none)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -461,7 +471,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
||||||
if (!tmd.GetContent(tmd.GetBootIndex(), &content))
|
if (!tmd.GetContent(tmd.GetBootIndex(), &content))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_pending_ppc_boot_content_path = GetContentPath(tmd.GetTitleId(), content);
|
m_pending_ppc_boot_content_path = m_core.GetContentPath(tmd.GetTitleId(), content);
|
||||||
if (!Core::IsRunningAndStarted())
|
if (!Core::IsRunningAndStarted())
|
||||||
return BootstrapPPC();
|
return BootstrapPPC();
|
||||||
|
|
||||||
|
@ -473,12 +483,12 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
||||||
bool ESDevice::BootstrapPPC()
|
bool ESDevice::BootstrapPPC()
|
||||||
{
|
{
|
||||||
const bool result =
|
const bool result =
|
||||||
m_ios.BootstrapPPC(Core::System::GetInstance(), m_pending_ppc_boot_content_path);
|
GetEmulationKernel().BootstrapPPC(GetSystem(), m_pending_ppc_boot_content_path);
|
||||||
m_pending_ppc_boot_content_path = {};
|
m_pending_ppc_boot_content_path = {};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESDevice::Context::DoState(PointerWrap& p)
|
void ESCore::Context::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
p.Do(uid);
|
p.Do(uid);
|
||||||
p.Do(gid);
|
p.Do(gid);
|
||||||
|
@ -492,7 +502,7 @@ void ESDevice::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
Device::DoState(p);
|
Device::DoState(p);
|
||||||
|
|
||||||
for (auto& entry : m_content_table)
|
for (auto& entry : m_core.m_content_table)
|
||||||
{
|
{
|
||||||
p.Do(entry.m_opened);
|
p.Do(entry.m_opened);
|
||||||
p.Do(entry.m_title_id);
|
p.Do(entry.m_title_id);
|
||||||
|
@ -501,7 +511,7 @@ void ESDevice::DoState(PointerWrap& p)
|
||||||
p.Do(entry.m_uid);
|
p.Do(entry.m_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_title_context.DoState(p);
|
m_core.m_title_context.DoState(p);
|
||||||
|
|
||||||
for (auto& context : m_contexts)
|
for (auto& context : m_contexts)
|
||||||
context.DoState(p);
|
context.DoState(p);
|
||||||
|
@ -702,7 +712,7 @@ std::optional<IPCReply> ESDevice::IOCtlV(const IOCtlVRequest& request)
|
||||||
case IOCTL_ES_UNKNOWN_42:
|
case IOCTL_ES_UNKNOWN_42:
|
||||||
PanicAlertFmt("IOS-ES: Unimplemented ioctlv {:#x} ({} in vectors, {} io vectors)",
|
PanicAlertFmt("IOS-ES: Unimplemented ioctlv {:#x} ({} in vectors, {} io vectors)",
|
||||||
request.request, request.in_vectors.size(), request.io_vectors.size());
|
request.request, request.in_vectors.size(), request.io_vectors.size());
|
||||||
request.DumpUnknown(Core::System::GetInstance(), GetDeviceName(), Common::Log::LogType::IOS_ES,
|
request.DumpUnknown(GetSystem(), GetDeviceName(), Common::Log::LogType::IOS_ES,
|
||||||
Common::Log::LogLevel::LERROR);
|
Common::Log::LogLevel::LERROR);
|
||||||
return IPCReply(IPC_EINVAL);
|
return IPCReply(IPC_EINVAL);
|
||||||
|
|
||||||
|
@ -718,7 +728,7 @@ IPCReply ESDevice::GetConsumption(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
// This is at least what crediar's ES module does
|
// This is at least what crediar's ES module does
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.Write_U32(0, request.io_vectors[1].address);
|
memory.Write_U32(0, request.io_vectors[1].address);
|
||||||
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETCONSUMPTION");
|
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETCONSUMPTION");
|
||||||
|
@ -730,7 +740,7 @@ std::optional<IPCReply> ESDevice::Launch(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(2, 0))
|
if (!request.HasNumberOfValidVectors(2, 0))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
|
@ -765,7 +775,7 @@ std::optional<IPCReply> ESDevice::LaunchBC(const IOCtlVRequest& request)
|
||||||
|
|
||||||
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
|
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
|
||||||
// An alternative way to do this is to check whether the current active IOS is MIOS.
|
// An alternative way to do this is to check whether the current active IOS is MIOS.
|
||||||
if (m_ios.GetVersion() == 0x101)
|
if (GetEmulationKernel().GetVersion() == 0x101)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
if (!LaunchTitle(0x0000000100000100))
|
if (!LaunchTitle(0x0000000100000100))
|
||||||
|
@ -808,7 +818,7 @@ static ReturnCode WriteTmdForDiVerify(FS::FileSystem* fs, const ES::TMDReader& t
|
||||||
|
|
||||||
ReturnCode ESDevice::DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket)
|
ReturnCode ESDevice::DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket)
|
||||||
{
|
{
|
||||||
m_title_context.Clear();
|
m_core.m_title_context.Clear();
|
||||||
INFO_LOG_FMT(IOS_ES, "ES_DIVerify: Title context changed: (none)");
|
INFO_LOG_FMT(IOS_ES, "ES_DIVerify: Title context changed: (none)");
|
||||||
|
|
||||||
if (!tmd.IsValid() || !ticket.IsValid())
|
if (!tmd.IsValid() || !ticket.IsValid())
|
||||||
|
@ -817,14 +827,14 @@ ReturnCode ESDevice::DIVerify(const ES::TMDReader& tmd, const ES::TicketReader&
|
||||||
if (tmd.GetTitleId() != ticket.GetTitleId())
|
if (tmd.GetTitleId() != ticket.GetTitleId())
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
|
||||||
m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiDisc);
|
m_core.m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiDisc);
|
||||||
INFO_LOG_FMT(IOS_ES, "ES_DIVerify: Title context changed: {:016x}", tmd.GetTitleId());
|
INFO_LOG_FMT(IOS_ES, "ES_DIVerify: Title context changed: {:016x}", tmd.GetTitleId());
|
||||||
|
|
||||||
// XXX: We are supposed to verify the TMD and ticket here, but cannot because
|
// XXX: We are supposed to verify the TMD and ticket here, but cannot because
|
||||||
// this may cause issues with custom/patched games.
|
// this may cause issues with custom/patched games.
|
||||||
|
|
||||||
const auto fs = m_ios.GetFS();
|
const auto fs = GetEmulationKernel().GetFS();
|
||||||
if (!FindInstalledTMD(tmd.GetTitleId()).IsValid())
|
if (!m_core.FindInstalledTMD(tmd.GetTitleId()).IsValid())
|
||||||
{
|
{
|
||||||
if (const ReturnCode ret = WriteTmdForDiVerify(fs.get(), tmd))
|
if (const ReturnCode ret = WriteTmdForDiVerify(fs.get(), tmd))
|
||||||
{
|
{
|
||||||
|
@ -833,7 +843,7 @@ ReturnCode ESDevice::DIVerify(const ES::TMDReader& tmd, const ES::TicketReader&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UpdateUIDAndGID(*GetIOS(), m_title_context.tmd))
|
if (!UpdateUIDAndGID(GetEmulationKernel(), m_core.m_title_context.tmd))
|
||||||
{
|
{
|
||||||
return ES_SHORT_READ;
|
return ES_SHORT_READ;
|
||||||
}
|
}
|
||||||
|
@ -842,11 +852,11 @@ ReturnCode ESDevice::DIVerify(const ES::TMDReader& tmd, const ES::TicketReader&
|
||||||
// Might already exist, so we only need to check whether the second operation succeeded.
|
// Might already exist, so we only need to check whether the second operation succeeded.
|
||||||
constexpr FS::Modes data_dir_modes{FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None};
|
constexpr FS::Modes data_dir_modes{FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None};
|
||||||
fs->CreateDirectory(PID_KERNEL, PID_KERNEL, data_dir, 0, data_dir_modes);
|
fs->CreateDirectory(PID_KERNEL, PID_KERNEL, data_dir, 0, data_dir_modes);
|
||||||
return FS::ConvertResult(
|
return FS::ConvertResult(fs->SetMetadata(0, data_dir, GetEmulationKernel().GetUidForPPC(),
|
||||||
fs->SetMetadata(0, data_dir, m_ios.GetUidForPPC(), m_ios.GetGidForPPC(), 0, data_dir_modes));
|
GetEmulationKernel().GetGidForPPC(), 0, data_dir_modes));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::CheckStreamKeyPermissions(const u32 uid, const u8* ticket_view,
|
ReturnCode ESCore::CheckStreamKeyPermissions(const u32 uid, const u8* ticket_view,
|
||||||
const ES::TMDReader& tmd) const
|
const ES::TMDReader& tmd) const
|
||||||
{
|
{
|
||||||
const u32 title_flags = tmd.GetTitleFlags();
|
const u32 title_flags = tmd.GetTitleFlags();
|
||||||
|
@ -889,7 +899,7 @@ ReturnCode ESDevice::CheckStreamKeyPermissions(const u32 uid, const u8* ticket_v
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::SetUpStreamKey(const u32 uid, const u8* ticket_view, const ES::TMDReader& tmd,
|
ReturnCode ESCore::SetUpStreamKey(const u32 uid, const u8* ticket_view, const ES::TMDReader& tmd,
|
||||||
u32* handle)
|
u32* handle)
|
||||||
{
|
{
|
||||||
ReturnCode ret = CheckStreamKeyPermissions(uid, ticket_view, tmd);
|
ReturnCode ret = CheckStreamKeyPermissions(uid, ticket_view, tmd);
|
||||||
|
@ -952,7 +962,7 @@ IPCReply ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& r
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
std::vector<u8> tmd_bytes(request.in_vectors[1].size);
|
std::vector<u8> tmd_bytes(request.in_vectors[1].size);
|
||||||
|
@ -963,8 +973,8 @@ IPCReply ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& r
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
u32 handle;
|
u32 handle;
|
||||||
const ReturnCode ret =
|
const ReturnCode ret = m_core.SetUpStreamKey(
|
||||||
SetUpStreamKey(context.uid, memory.GetPointer(request.in_vectors[0].address), tmd, &handle);
|
context.uid, memory.GetPointer(request.in_vectors[0].address), tmd, &handle);
|
||||||
memory.Write_U32(handle, request.io_vectors[0].address);
|
memory.Write_U32(handle, request.io_vectors[0].address);
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
}
|
}
|
||||||
|
@ -974,13 +984,13 @@ IPCReply ESDevice::DeleteStreamKey(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u32 handle = memory.Read_U32(request.in_vectors[0].address);
|
const u32 handle = memory.Read_U32(request.in_vectors[0].address);
|
||||||
return IPCReply(m_ios.GetIOSC().DeleteObject(handle, PID_ES));
|
return IPCReply(GetEmulationKernel().GetIOSC().DeleteObject(handle, PID_ES));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESDevice::IsActiveTitlePermittedByTicket(const u8* ticket_view) const
|
bool ESCore::IsActiveTitlePermittedByTicket(const u8* ticket_view) const
|
||||||
{
|
{
|
||||||
if (!m_title_context.active)
|
if (!m_title_context.active)
|
||||||
return false;
|
return false;
|
||||||
|
@ -993,7 +1003,7 @@ bool ESDevice::IsActiveTitlePermittedByTicket(const u8* ticket_view) const
|
||||||
return title_identifier && (title_identifier & ~permitted_title_mask) == permitted_title_id;
|
return title_identifier && (title_identifier & ~permitted_title_mask) == permitted_title_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESDevice::IsIssuerCorrect(VerifyContainerType type, const ES::CertReader& issuer_cert) const
|
bool ESCore::IsIssuerCorrect(VerifyContainerType type, const ES::CertReader& issuer_cert) const
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -1010,7 +1020,7 @@ bool ESDevice::IsIssuerCorrect(VerifyContainerType type, const ES::CertReader& i
|
||||||
|
|
||||||
static const std::string CERT_STORE_PATH = "/sys/cert.sys";
|
static const std::string CERT_STORE_PATH = "/sys/cert.sys";
|
||||||
|
|
||||||
ReturnCode ESDevice::ReadCertStore(std::vector<u8>* buffer) const
|
ReturnCode ESCore::ReadCertStore(std::vector<u8>* buffer) const
|
||||||
{
|
{
|
||||||
const auto store_file =
|
const auto store_file =
|
||||||
m_ios.GetFS()->OpenFile(PID_KERNEL, PID_KERNEL, CERT_STORE_PATH, FS::Mode::Read);
|
m_ios.GetFS()->OpenFile(PID_KERNEL, PID_KERNEL, CERT_STORE_PATH, FS::Mode::Read);
|
||||||
|
@ -1023,7 +1033,7 @@ ReturnCode ESDevice::ReadCertStore(std::vector<u8>* buffer) const
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::WriteNewCertToStore(const ES::CertReader& cert)
|
ReturnCode ESCore::WriteNewCertToStore(const ES::CertReader& cert)
|
||||||
{
|
{
|
||||||
// Read the current store to determine if the new cert needs to be written.
|
// Read the current store to determine if the new cert needs to be written.
|
||||||
std::vector<u8> current_store;
|
std::vector<u8> current_store;
|
||||||
|
@ -1048,7 +1058,7 @@ ReturnCode ESDevice::WriteNewCertToStore(const ES::CertReader& cert)
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
ReturnCode ESCore::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
||||||
const ES::SignedBlobReader& signed_blob,
|
const ES::SignedBlobReader& signed_blob,
|
||||||
const std::vector<u8>& cert_chain, u32* issuer_handle_out)
|
const std::vector<u8>& cert_chain, u32* issuer_handle_out)
|
||||||
{
|
{
|
||||||
|
@ -1144,7 +1154,7 @@ ReturnCode ESDevice::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
ReturnCode ESCore::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
||||||
const ES::CertReader& cert, const std::vector<u8>& cert_chain,
|
const ES::CertReader& cert, const std::vector<u8>& cert_chain,
|
||||||
u32 certificate_iosc_handle)
|
u32 certificate_iosc_handle)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,22 +37,17 @@ struct TitleContext
|
||||||
bool first_change = true;
|
bool first_change = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESDevice final : public Device
|
class ESDevice;
|
||||||
|
|
||||||
|
class ESCore final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ESDevice(Kernel& ios, const std::string& device_name);
|
explicit ESCore(Kernel& ios);
|
||||||
|
ESCore(const ESCore& other) = delete;
|
||||||
static void InitializeEmulationState();
|
ESCore(ESCore&& other) = delete;
|
||||||
static void FinalizeEmulationState();
|
ESCore& operator=(const ESCore& other) = delete;
|
||||||
|
ESCore& operator=(ESCore&& other) = delete;
|
||||||
ReturnCode DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket);
|
~ESCore();
|
||||||
bool LaunchTitle(u64 title_id, HangPPC hang_ppc = HangPPC::No);
|
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
|
||||||
|
|
||||||
std::optional<IPCReply> Open(const OpenRequest& request) override;
|
|
||||||
std::optional<IPCReply> Close(u32 fd) override;
|
|
||||||
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
|
|
||||||
|
|
||||||
struct TitleImportExportContext
|
struct TitleImportExportContext
|
||||||
{
|
{
|
||||||
|
@ -83,12 +78,6 @@ public:
|
||||||
s32 ipc_fd = -1;
|
s32 ipc_fd = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CheckContentHashes : bool
|
|
||||||
{
|
|
||||||
Yes = true,
|
|
||||||
No = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
ES::TMDReader FindImportTMD(u64 title_id, Ticks ticks = {}) const;
|
ES::TMDReader FindImportTMD(u64 title_id, Ticks ticks = {}) const;
|
||||||
ES::TMDReader FindInstalledTMD(u64 title_id, Ticks ticks = {}) const;
|
ES::TMDReader FindInstalledTMD(u64 title_id, Ticks ticks = {}) const;
|
||||||
ES::TicketReader FindSignedTicket(u64 title_id,
|
ES::TicketReader FindSignedTicket(u64 title_id,
|
||||||
|
@ -101,6 +90,12 @@ public:
|
||||||
// Get titles for which there is a ticket (in /ticket).
|
// Get titles for which there is a ticket (in /ticket).
|
||||||
std::vector<u64> GetTitlesWithTickets() const;
|
std::vector<u64> GetTitlesWithTickets() const;
|
||||||
|
|
||||||
|
enum class CheckContentHashes : bool
|
||||||
|
{
|
||||||
|
Yes = true,
|
||||||
|
No = false,
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<ES::Content>
|
std::vector<ES::Content>
|
||||||
GetStoredContentsFromTMD(const ES::TMDReader& tmd,
|
GetStoredContentsFromTMD(const ES::TMDReader& tmd,
|
||||||
CheckContentHashes check_content_hashes = CheckContentHashes::No) const;
|
CheckContentHashes check_content_hashes = CheckContentHashes::No) const;
|
||||||
|
@ -186,6 +181,71 @@ public:
|
||||||
const ES::CertReader& certificate, const std::vector<u8>& cert_chain,
|
const ES::CertReader& certificate, const std::vector<u8>& cert_chain,
|
||||||
u32 certificate_iosc_handle);
|
u32 certificate_iosc_handle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Start a title import.
|
||||||
|
bool InitImport(const ES::TMDReader& tmd);
|
||||||
|
// Clean up the import content directory and move it back to /title.
|
||||||
|
bool FinishImport(const ES::TMDReader& tmd);
|
||||||
|
// Write a TMD for a title in /import atomically.
|
||||||
|
bool WriteImportTMD(const ES::TMDReader& tmd);
|
||||||
|
// Finish stale imports and clear the import directory.
|
||||||
|
void FinishStaleImport(u64 title_id);
|
||||||
|
void FinishAllStaleImports();
|
||||||
|
|
||||||
|
std::string GetContentPath(u64 title_id, const ES::Content& content, Ticks ticks = {}) const;
|
||||||
|
|
||||||
|
bool IsActiveTitlePermittedByTicket(const u8* ticket_view) const;
|
||||||
|
|
||||||
|
bool IsIssuerCorrect(VerifyContainerType type, const ES::CertReader& issuer_cert) const;
|
||||||
|
ReturnCode ReadCertStore(std::vector<u8>* buffer) const;
|
||||||
|
ReturnCode WriteNewCertToStore(const ES::CertReader& cert);
|
||||||
|
|
||||||
|
ReturnCode CheckStreamKeyPermissions(u32 uid, const u8* ticket_view,
|
||||||
|
const ES::TMDReader& tmd) const;
|
||||||
|
|
||||||
|
struct OpenedContent
|
||||||
|
{
|
||||||
|
bool m_opened = false;
|
||||||
|
u64 m_fd = 0;
|
||||||
|
u64 m_title_id = 0;
|
||||||
|
ES::Content m_content{};
|
||||||
|
u32 m_uid = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Kernel& m_ios;
|
||||||
|
|
||||||
|
using ContentTable = std::array<OpenedContent, 16>;
|
||||||
|
ContentTable m_content_table;
|
||||||
|
|
||||||
|
TitleContext m_title_context{};
|
||||||
|
|
||||||
|
friend class ESDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ESDevice final : public EmulationDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ESDevice(EmulationKernel& ios, ESCore& core, const std::string& device_name);
|
||||||
|
ESDevice(const ESDevice& other) = delete;
|
||||||
|
ESDevice(ESDevice&& other) = delete;
|
||||||
|
ESDevice& operator=(const ESDevice& other) = delete;
|
||||||
|
ESDevice& operator=(ESDevice&& other) = delete;
|
||||||
|
~ESDevice();
|
||||||
|
|
||||||
|
static void InitializeEmulationState();
|
||||||
|
static void FinalizeEmulationState();
|
||||||
|
|
||||||
|
ReturnCode DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket);
|
||||||
|
bool LaunchTitle(u64 title_id, HangPPC hang_ppc = HangPPC::No);
|
||||||
|
|
||||||
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
|
std::optional<IPCReply> Open(const OpenRequest& request) override;
|
||||||
|
std::optional<IPCReply> Close(u32 fd) override;
|
||||||
|
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
|
||||||
|
|
||||||
|
ESCore& GetCore() const { return m_core; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -261,6 +321,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ES can only have 3 contexts at one time.
|
// ES can only have 3 contexts at one time.
|
||||||
|
using Context = ESCore::Context;
|
||||||
using ContextArray = std::array<Context, 3>;
|
using ContextArray = std::array<Context, 3>;
|
||||||
|
|
||||||
// Title management
|
// Title management
|
||||||
|
@ -348,47 +409,15 @@ private:
|
||||||
|
|
||||||
bool LaunchIOS(u64 ios_title_id, HangPPC hang_ppc);
|
bool LaunchIOS(u64 ios_title_id, HangPPC hang_ppc);
|
||||||
bool LaunchPPCTitle(u64 title_id);
|
bool LaunchPPCTitle(u64 title_id);
|
||||||
bool IsActiveTitlePermittedByTicket(const u8* ticket_view) const;
|
|
||||||
|
|
||||||
ReturnCode CheckStreamKeyPermissions(u32 uid, const u8* ticket_view,
|
|
||||||
const ES::TMDReader& tmd) const;
|
|
||||||
|
|
||||||
bool IsIssuerCorrect(VerifyContainerType type, const ES::CertReader& issuer_cert) const;
|
|
||||||
ReturnCode ReadCertStore(std::vector<u8>* buffer) const;
|
|
||||||
ReturnCode WriteNewCertToStore(const ES::CertReader& cert);
|
|
||||||
|
|
||||||
// Start a title import.
|
|
||||||
bool InitImport(const ES::TMDReader& tmd);
|
|
||||||
// Clean up the import content directory and move it back to /title.
|
|
||||||
bool FinishImport(const ES::TMDReader& tmd);
|
|
||||||
// Write a TMD for a title in /import atomically.
|
|
||||||
bool WriteImportTMD(const ES::TMDReader& tmd);
|
|
||||||
// Finish stale imports and clear the import directory.
|
|
||||||
void FinishStaleImport(u64 title_id);
|
|
||||||
void FinishAllStaleImports();
|
|
||||||
|
|
||||||
void FinishInit();
|
void FinishInit();
|
||||||
|
|
||||||
std::string GetContentPath(u64 title_id, const ES::Content& content, Ticks ticks = {}) const;
|
|
||||||
|
|
||||||
s32 WriteSystemFile(const std::string& path, const std::vector<u8>& data, Ticks ticks = {});
|
s32 WriteSystemFile(const std::string& path, const std::vector<u8>& data, Ticks ticks = {});
|
||||||
s32 WriteLaunchFile(const ES::TMDReader& tmd, Ticks ticks = {});
|
s32 WriteLaunchFile(const ES::TMDReader& tmd, Ticks ticks = {});
|
||||||
bool BootstrapPPC();
|
bool BootstrapPPC();
|
||||||
|
|
||||||
struct OpenedContent
|
ESCore& m_core;
|
||||||
{
|
|
||||||
bool m_opened = false;
|
|
||||||
u64 m_fd = 0;
|
|
||||||
u64 m_title_id = 0;
|
|
||||||
ES::Content m_content{};
|
|
||||||
u32 m_uid = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ContentTable = std::array<OpenedContent, 16>;
|
|
||||||
ContentTable m_content_table;
|
|
||||||
|
|
||||||
ContextArray m_contexts;
|
ContextArray m_contexts;
|
||||||
TitleContext m_title_context{};
|
|
||||||
std::string m_pending_ppc_boot_content_path;
|
std::string m_pending_ppc_boot_content_path;
|
||||||
};
|
};
|
||||||
} // namespace IOS::HLE
|
} // namespace IOS::HLE
|
||||||
|
|
|
@ -554,17 +554,16 @@ struct SharedContentMap::Entry
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr char CONTENT_MAP_PATH[] = "/shared1/content.map";
|
constexpr char CONTENT_MAP_PATH[] = "/shared1/content.map";
|
||||||
SharedContentMap::SharedContentMap(std::shared_ptr<HLE::FSDevice> fs)
|
SharedContentMap::SharedContentMap(HLE::FSCore& fs_core) : m_fs_core{fs_core}, m_fs{fs_core.GetFS()}
|
||||||
: m_fs_device{fs}, m_fs{fs->GetFS()}
|
|
||||||
{
|
{
|
||||||
static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size");
|
static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size");
|
||||||
|
|
||||||
Entry entry;
|
Entry entry;
|
||||||
const auto fd =
|
const auto fd =
|
||||||
fs->Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
fs_core.Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
||||||
if (fd.Get() < 0)
|
if (fd.Get() < 0)
|
||||||
return;
|
return;
|
||||||
while (fs->Read(fd.Get(), &entry, 1, &m_ticks) == sizeof(entry))
|
while (fs_core.Read(fd.Get(), &entry, 1, &m_ticks) == sizeof(entry))
|
||||||
{
|
{
|
||||||
m_entries.push_back(entry);
|
m_entries.push_back(entry);
|
||||||
m_last_id++;
|
m_last_id++;
|
||||||
|
@ -637,7 +636,7 @@ bool SharedContentMap::WriteEntries() const
|
||||||
HLE::FS::ResultCode::Success;
|
HLE::FS::ResultCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::pair<u32, u64> ReadUidSysEntry(HLE::FSDevice& fs, u64 fd, u64* ticks)
|
static std::pair<u32, u64> ReadUidSysEntry(HLE::FSCore& fs, u64 fd, u64* ticks)
|
||||||
{
|
{
|
||||||
u64 title_id = 0;
|
u64 title_id = 0;
|
||||||
if (fs.Read(fd, &title_id, 1, ticks) != sizeof(title_id))
|
if (fs.Read(fd, &title_id, 1, ticks) != sizeof(title_id))
|
||||||
|
@ -651,15 +650,15 @@ static std::pair<u32, u64> ReadUidSysEntry(HLE::FSDevice& fs, u64 fd, u64* ticks
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr char UID_MAP_PATH[] = "/sys/uid.sys";
|
constexpr char UID_MAP_PATH[] = "/sys/uid.sys";
|
||||||
UIDSys::UIDSys(std::shared_ptr<HLE::FSDevice> fs) : m_fs_device{fs}, m_fs{fs->GetFS()}
|
UIDSys::UIDSys(HLE::FSCore& fs_core) : m_fs_core{fs_core}, m_fs{fs_core.GetFS()}
|
||||||
{
|
{
|
||||||
if (const auto fd =
|
if (const auto fd =
|
||||||
fs->Open(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
fs_core.Open(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
||||||
fd.Get() >= 0)
|
fd.Get() >= 0)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
std::pair<u32, u64> entry = ReadUidSysEntry(*fs, fd.Get(), &m_ticks);
|
std::pair<u32, u64> entry = ReadUidSysEntry(fs_core, fd.Get(), &m_ticks);
|
||||||
if (!entry.first && !entry.second)
|
if (!entry.first && !entry.second)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -280,7 +280,7 @@ public:
|
||||||
class SharedContentMap final
|
class SharedContentMap final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SharedContentMap(std::shared_ptr<HLE::FSDevice> fs);
|
explicit SharedContentMap(HLE::FSCore& fs_core);
|
||||||
~SharedContentMap();
|
~SharedContentMap();
|
||||||
|
|
||||||
std::optional<std::string> GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
|
std::optional<std::string> GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
|
||||||
|
@ -296,7 +296,7 @@ private:
|
||||||
struct Entry;
|
struct Entry;
|
||||||
u32 m_last_id = 0;
|
u32 m_last_id = 0;
|
||||||
std::vector<Entry> m_entries;
|
std::vector<Entry> m_entries;
|
||||||
std::shared_ptr<HLE::FSDevice> m_fs_device;
|
HLE::FSCore& m_fs_core;
|
||||||
std::shared_ptr<HLE::FS::FileSystem> m_fs;
|
std::shared_ptr<HLE::FS::FileSystem> m_fs;
|
||||||
u64 m_ticks = 0;
|
u64 m_ticks = 0;
|
||||||
};
|
};
|
||||||
|
@ -304,7 +304,7 @@ private:
|
||||||
class UIDSys final
|
class UIDSys final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit UIDSys(std::shared_ptr<HLE::FSDevice> fs);
|
explicit UIDSys(HLE::FSCore& fs_core);
|
||||||
|
|
||||||
u32 GetUIDFromTitle(u64 title_id) const;
|
u32 GetUIDFromTitle(u64 title_id) const;
|
||||||
u32 GetOrInsertUIDForTitle(u64 title_id);
|
u32 GetOrInsertUIDForTitle(u64 title_id);
|
||||||
|
@ -313,7 +313,7 @@ public:
|
||||||
u64 GetTicks() const { return m_ticks; }
|
u64 GetTicks() const { return m_ticks; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<HLE::FSDevice> m_fs_device;
|
HLE::FSCore& m_fs_core;
|
||||||
std::shared_ptr<HLE::FS::FileSystem> m_fs;
|
std::shared_ptr<HLE::FS::FileSystem> m_fs;
|
||||||
std::map<u32, u64> m_entries;
|
std::map<u32, u64> m_entries;
|
||||||
u64 m_ticks = 0;
|
u64 m_ticks = 0;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
namespace IOS::HLE
|
namespace IOS::HLE
|
||||||
{
|
{
|
||||||
ReturnCode ESDevice::GetDeviceId(u32* device_id) const
|
ReturnCode ESCore::GetDeviceId(u32* device_id) const
|
||||||
{
|
{
|
||||||
*device_id = m_ios.GetIOSC().GetDeviceId();
|
*device_id = m_ios.GetIOSC().GetDeviceId();
|
||||||
INFO_LOG_FMT(IOS_ES, "GetDeviceId: {:08X}", *device_id);
|
INFO_LOG_FMT(IOS_ES, "GetDeviceId: {:08X}", *device_id);
|
||||||
|
@ -32,11 +32,11 @@ IPCReply ESDevice::GetDeviceId(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
u32 device_id;
|
u32 device_id;
|
||||||
const ReturnCode ret = GetDeviceId(&device_id);
|
const ReturnCode ret = m_core.GetDeviceId(&device_id);
|
||||||
if (ret != IPC_SUCCESS)
|
if (ret != IPC_SUCCESS)
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.Write_U32(device_id, request.io_vectors[0].address);
|
memory.Write_U32(device_id, request.io_vectors[0].address);
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
|
@ -47,7 +47,7 @@ IPCReply ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(3, 2))
|
if (!request.HasNumberOfValidVectors(3, 2))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
|
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
|
||||||
u8* source = memory.GetPointer(request.in_vectors[2].address);
|
u8* source = memory.GetPointer(request.in_vectors[2].address);
|
||||||
|
@ -57,7 +57,8 @@ IPCReply ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
|
||||||
|
|
||||||
// TODO: Check whether the active title is allowed to encrypt.
|
// TODO: Check whether the active title is allowed to encrypt.
|
||||||
|
|
||||||
const ReturnCode ret = m_ios.GetIOSC().Encrypt(keyIndex, iv, source, size, destination, PID_ES);
|
const ReturnCode ret =
|
||||||
|
GetEmulationKernel().GetIOSC().Encrypt(keyIndex, iv, source, size, destination, PID_ES);
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ IPCReply ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(3, 2))
|
if (!request.HasNumberOfValidVectors(3, 2))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
|
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
|
||||||
u8* source = memory.GetPointer(request.in_vectors[2].address);
|
u8* source = memory.GetPointer(request.in_vectors[2].address);
|
||||||
|
@ -76,7 +77,8 @@ IPCReply ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
|
||||||
|
|
||||||
// TODO: Check whether the active title is allowed to decrypt.
|
// TODO: Check whether the active title is allowed to decrypt.
|
||||||
|
|
||||||
const ReturnCode ret = m_ios.GetIOSC().Decrypt(keyIndex, iv, source, size, destination, PID_ES);
|
const ReturnCode ret =
|
||||||
|
GetEmulationKernel().GetIOSC().Decrypt(keyIndex, iv, source, size, destination, PID_ES);
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +102,9 @@ IPCReply ESDevice::GetDeviceCertificate(const IOCtlVRequest& request)
|
||||||
|
|
||||||
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETDEVICECERT");
|
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETDEVICECERT");
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const IOS::CertECC cert = m_ios.GetIOSC().GetDeviceCertificate();
|
const IOS::CertECC cert = GetEmulationKernel().GetIOSC().GetDeviceCertificate();
|
||||||
memory.CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
|
memory.CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -113,21 +115,22 @@ IPCReply ESDevice::Sign(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_SIGN");
|
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_SIGN");
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
u8* ap_cert_out = memory.GetPointer(request.io_vectors[1].address);
|
u8* ap_cert_out = memory.GetPointer(request.io_vectors[1].address);
|
||||||
u8* data = memory.GetPointer(request.in_vectors[0].address);
|
u8* data = memory.GetPointer(request.in_vectors[0].address);
|
||||||
u32 data_size = request.in_vectors[0].size;
|
u32 data_size = request.in_vectors[0].size;
|
||||||
u8* sig_out = memory.GetPointer(request.io_vectors[0].address);
|
u8* sig_out = memory.GetPointer(request.io_vectors[0].address);
|
||||||
|
|
||||||
if (!m_title_context.active)
|
if (!m_core.m_title_context.active)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
m_ios.GetIOSC().Sign(sig_out, ap_cert_out, m_title_context.tmd.GetTitleId(), data, data_size);
|
GetEmulationKernel().GetIOSC().Sign(sig_out, ap_cert_out, m_core.m_title_context.tmd.GetTitleId(),
|
||||||
|
data, data_size);
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u8>& ecc_signature,
|
ReturnCode ESCore::VerifySign(const std::vector<u8>& hash, const std::vector<u8>& ecc_signature,
|
||||||
const std::vector<u8>& certs_bytes)
|
const std::vector<u8>& certs_bytes)
|
||||||
{
|
{
|
||||||
const std::map<std::string, ES::CertReader> certs = ES::ParseCertChain(certs_bytes);
|
const std::map<std::string, ES::CertReader> certs = ES::ParseCertChain(certs_bytes);
|
||||||
|
@ -205,7 +208,7 @@ IPCReply ESDevice::VerifySign(const IOCtlVRequest& request)
|
||||||
if (request.in_vectors[1].size != sizeof(Common::ec::Signature))
|
if (request.in_vectors[1].size != sizeof(Common::ec::Signature))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
std::vector<u8> hash(request.in_vectors[0].size);
|
std::vector<u8> hash(request.in_vectors[0].size);
|
||||||
|
@ -217,6 +220,6 @@ IPCReply ESDevice::VerifySign(const IOCtlVRequest& request)
|
||||||
std::vector<u8> certs(request.in_vectors[2].size);
|
std::vector<u8> certs(request.in_vectors[2].size);
|
||||||
memory.CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());
|
memory.CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());
|
||||||
|
|
||||||
return IPCReply(VerifySign(hash, ecc_signature, certs));
|
return IPCReply(m_core.VerifySign(hash, ecc_signature, certs));
|
||||||
}
|
}
|
||||||
} // namespace IOS::HLE
|
} // namespace IOS::HLE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
namespace IOS::HLE
|
namespace IOS::HLE
|
||||||
{
|
{
|
||||||
static ES::TMDReader FindTMD(FSDevice& fs, const std::string& tmd_path, Ticks ticks)
|
static ES::TMDReader FindTMD(FSCore& fs, const std::string& tmd_path, Ticks ticks)
|
||||||
{
|
{
|
||||||
const auto fd = fs.Open(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::Read, {}, ticks);
|
const auto fd = fs.Open(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::Read, {}, ticks);
|
||||||
if (fd.Get() < 0)
|
if (fd.Get() < 0)
|
||||||
|
@ -38,18 +38,18 @@ static ES::TMDReader FindTMD(FSDevice& fs, const std::string& tmd_path, Ticks ti
|
||||||
return ES::TMDReader{std::move(tmd_bytes)};
|
return ES::TMDReader{std::move(tmd_bytes)};
|
||||||
}
|
}
|
||||||
|
|
||||||
ES::TMDReader ESDevice::FindImportTMD(u64 title_id, Ticks ticks) const
|
ES::TMDReader ESCore::FindImportTMD(u64 title_id, Ticks ticks) const
|
||||||
{
|
{
|
||||||
return FindTMD(*m_ios.GetFSDevice(), Common::GetImportTitlePath(title_id) + "/content/title.tmd",
|
return FindTMD(m_ios.GetFSCore(), Common::GetImportTitlePath(title_id) + "/content/title.tmd",
|
||||||
ticks);
|
ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
ES::TMDReader ESDevice::FindInstalledTMD(u64 title_id, Ticks ticks) const
|
ES::TMDReader ESCore::FindInstalledTMD(u64 title_id, Ticks ticks) const
|
||||||
{
|
{
|
||||||
return FindTMD(*m_ios.GetFSDevice(), Common::GetTMDFileName(title_id), ticks);
|
return FindTMD(m_ios.GetFSCore(), Common::GetTMDFileName(title_id), ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
ES::TicketReader ESDevice::FindSignedTicket(u64 title_id, std::optional<u8> desired_version) const
|
ES::TicketReader ESCore::FindSignedTicket(u64 title_id, std::optional<u8> desired_version) const
|
||||||
{
|
{
|
||||||
std::string path = desired_version == 1 ? Common::GetV1TicketFileName(title_id) :
|
std::string path = desired_version == 1 ? Common::GetV1TicketFileName(title_id) :
|
||||||
Common::GetTicketFileName(title_id);
|
Common::GetTicketFileName(title_id);
|
||||||
|
@ -125,17 +125,17 @@ static std::vector<u64> GetTitlesInTitleOrImport(FS::FileSystem* fs, const std::
|
||||||
return title_ids;
|
return title_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u64> ESDevice::GetInstalledTitles() const
|
std::vector<u64> ESCore::GetInstalledTitles() const
|
||||||
{
|
{
|
||||||
return GetTitlesInTitleOrImport(m_ios.GetFS().get(), "/title");
|
return GetTitlesInTitleOrImport(m_ios.GetFS().get(), "/title");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u64> ESDevice::GetTitleImports() const
|
std::vector<u64> ESCore::GetTitleImports() const
|
||||||
{
|
{
|
||||||
return GetTitlesInTitleOrImport(m_ios.GetFS().get(), "/import");
|
return GetTitlesInTitleOrImport(m_ios.GetFS().get(), "/import");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u64> ESDevice::GetTitlesWithTickets() const
|
std::vector<u64> ESCore::GetTitlesWithTickets() const
|
||||||
{
|
{
|
||||||
const auto fs = m_ios.GetFS();
|
const auto fs = m_ios.GetFS();
|
||||||
const auto entries = fs->ReadDirectory(PID_KERNEL, PID_KERNEL, "/ticket");
|
const auto entries = fs->ReadDirectory(PID_KERNEL, PID_KERNEL, "/ticket");
|
||||||
|
@ -179,7 +179,7 @@ std::vector<u64> ESDevice::GetTitlesWithTickets() const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ES::Content>
|
std::vector<ES::Content>
|
||||||
ESDevice::GetStoredContentsFromTMD(const ES::TMDReader& tmd,
|
ESCore::GetStoredContentsFromTMD(const ES::TMDReader& tmd,
|
||||||
CheckContentHashes check_content_hashes) const
|
CheckContentHashes check_content_hashes) const
|
||||||
{
|
{
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
|
@ -216,7 +216,7 @@ ESDevice::GetStoredContentsFromTMD(const ES::TMDReader& tmd,
|
||||||
return stored_contents;
|
return stored_contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ESDevice::GetSharedContentsCount() const
|
u32 ESCore::GetSharedContentsCount() const
|
||||||
{
|
{
|
||||||
const auto entries = m_ios.GetFS()->ReadDirectory(PID_KERNEL, PID_KERNEL, "/shared1");
|
const auto entries = m_ios.GetFS()->ReadDirectory(PID_KERNEL, PID_KERNEL, "/shared1");
|
||||||
return static_cast<u32>(
|
return static_cast<u32>(
|
||||||
|
@ -226,9 +226,9 @@ u32 ESDevice::GetSharedContentsCount() const
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::array<u8, 20>> ESDevice::GetSharedContents() const
|
std::vector<std::array<u8, 20>> ESCore::GetSharedContents() const
|
||||||
{
|
{
|
||||||
const ES::SharedContentMap map{m_ios.GetFSDevice()};
|
const ES::SharedContentMap map{m_ios.GetFSCore()};
|
||||||
return map.GetHashes();
|
return map.GetHashes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ constexpr FS::Modes title_dir_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS
|
||||||
constexpr FS::Modes content_dir_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None};
|
constexpr FS::Modes content_dir_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None};
|
||||||
constexpr FS::Modes data_dir_modes{FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None};
|
constexpr FS::Modes data_dir_modes{FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None};
|
||||||
|
|
||||||
bool ESDevice::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
bool ESCore::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
||||||
{
|
{
|
||||||
const auto fs = m_ios.GetFS();
|
const auto fs = m_ios.GetFS();
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ bool ESDevice::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ES::UIDSys uid_sys{m_ios.GetFSDevice()};
|
ES::UIDSys uid_sys{m_ios.GetFSCore()};
|
||||||
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
|
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
|
||||||
if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success)
|
if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success)
|
||||||
{
|
{
|
||||||
|
@ -289,7 +289,7 @@ bool ESDevice::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESDevice::InitImport(const ES::TMDReader& tmd)
|
bool ESCore::InitImport(const ES::TMDReader& tmd)
|
||||||
{
|
{
|
||||||
if (!CreateTitleDirectories(tmd.GetTitleId(), tmd.GetGroupId()))
|
if (!CreateTitleDirectories(tmd.GetTitleId(), tmd.GetGroupId()))
|
||||||
return false;
|
return false;
|
||||||
|
@ -321,7 +321,7 @@ bool ESDevice::InitImport(const ES::TMDReader& tmd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESDevice::FinishImport(const ES::TMDReader& tmd)
|
bool ESCore::FinishImport(const ES::TMDReader& tmd)
|
||||||
{
|
{
|
||||||
const auto fs = m_ios.GetFS();
|
const auto fs = m_ios.GetFS();
|
||||||
const u64 title_id = tmd.GetTitleId();
|
const u64 title_id = tmd.GetTitleId();
|
||||||
|
@ -354,7 +354,7 @@ bool ESDevice::FinishImport(const ES::TMDReader& tmd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESDevice::WriteImportTMD(const ES::TMDReader& tmd)
|
bool ESCore::WriteImportTMD(const ES::TMDReader& tmd)
|
||||||
{
|
{
|
||||||
const auto fs = m_ios.GetFS();
|
const auto fs = m_ios.GetFS();
|
||||||
const std::string tmd_path = "/tmp/title.tmd";
|
const std::string tmd_path = "/tmp/title.tmd";
|
||||||
|
@ -369,7 +369,7 @@ bool ESDevice::WriteImportTMD(const ES::TMDReader& tmd)
|
||||||
return fs->Rename(PID_KERNEL, PID_KERNEL, tmd_path, dest) == FS::ResultCode::Success;
|
return fs->Rename(PID_KERNEL, PID_KERNEL, tmd_path, dest) == FS::ResultCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESDevice::FinishStaleImport(u64 title_id)
|
void ESCore::FinishStaleImport(u64 title_id)
|
||||||
{
|
{
|
||||||
const auto fs = m_ios.GetFS();
|
const auto fs = m_ios.GetFS();
|
||||||
const auto import_tmd = FindImportTMD(title_id);
|
const auto import_tmd = FindImportTMD(title_id);
|
||||||
|
@ -385,19 +385,19 @@ void ESDevice::FinishStaleImport(u64 title_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESDevice::FinishAllStaleImports()
|
void ESCore::FinishAllStaleImports()
|
||||||
{
|
{
|
||||||
const std::vector<u64> titles = GetTitleImports();
|
const std::vector<u64> titles = GetTitleImports();
|
||||||
for (const u64& title_id : titles)
|
for (const u64& title_id : titles)
|
||||||
FinishStaleImport(title_id);
|
FinishStaleImport(title_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ESDevice::GetContentPath(const u64 title_id, const ES::Content& content,
|
std::string ESCore::GetContentPath(const u64 title_id, const ES::Content& content,
|
||||||
Ticks ticks) const
|
Ticks ticks) const
|
||||||
{
|
{
|
||||||
if (content.IsShared())
|
if (content.IsShared())
|
||||||
{
|
{
|
||||||
ES::SharedContentMap content_map{m_ios.GetFSDevice()};
|
ES::SharedContentMap content_map{m_ios.GetFSCore()};
|
||||||
ticks.Add(content_map.GetTicks());
|
ticks.Add(content_map.GetTicks());
|
||||||
return content_map.GetFilenameFromSHA1(content.sha1).value_or("");
|
return content_map.GetFilenameFromSHA1(content.sha1).value_or("");
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ std::string ESDevice::GetContentPath(const u64 title_id, const ES::Content& cont
|
||||||
|
|
||||||
s32 ESDevice::WriteSystemFile(const std::string& path, const std::vector<u8>& data, Ticks ticks)
|
s32 ESDevice::WriteSystemFile(const std::string& path, const std::vector<u8>& data, Ticks ticks)
|
||||||
{
|
{
|
||||||
auto& fs = *m_ios.GetFSDevice();
|
auto& fs = GetEmulationKernel().GetFSCore();
|
||||||
const std::string tmp_path = "/tmp/" + PathToFileName(path);
|
const std::string tmp_path = "/tmp/" + PathToFileName(path);
|
||||||
|
|
||||||
auto result = fs.CreateFile(PID_KERNEL, PID_KERNEL, tmp_path, {},
|
auto result = fs.CreateFile(PID_KERNEL, PID_KERNEL, tmp_path, {},
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
namespace IOS::HLE
|
namespace IOS::HLE
|
||||||
{
|
{
|
||||||
s32 ESDevice::OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid, Ticks ticks)
|
s32 ESCore::OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid, Ticks ticks)
|
||||||
{
|
{
|
||||||
const u64 title_id = tmd.GetTitleId();
|
const u64 title_id = tmd.GetTitleId();
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ s32 ESDevice::OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const std::string path = GetContentPath(title_id, content, ticks);
|
const std::string path = GetContentPath(title_id, content, ticks);
|
||||||
auto fd = m_ios.GetFSDevice()->Open(PID_KERNEL, PID_KERNEL, path, FS::Mode::Read, {}, ticks);
|
auto fd = m_ios.GetFSCore().Open(PID_KERNEL, PID_KERNEL, path, FS::Mode::Read, {}, ticks);
|
||||||
if (fd.Get() < 0)
|
if (fd.Get() < 0)
|
||||||
return fd.Get();
|
return fd.Get();
|
||||||
|
|
||||||
|
@ -57,17 +57,17 @@ IPCReply ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const u32 content_index = memory.Read_U32(request.in_vectors[2].address);
|
const u32 content_index = memory.Read_U32(request.in_vectors[2].address);
|
||||||
// TODO: check the ticket view, check permissions.
|
// TODO: check the ticket view, check permissions.
|
||||||
|
|
||||||
const auto tmd = FindInstalledTMD(title_id, ticks);
|
const auto tmd = m_core.FindInstalledTMD(title_id, ticks);
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return FS_ENOENT;
|
return FS_ENOENT;
|
||||||
|
|
||||||
return OpenContent(tmd, content_index, uid, ticks);
|
return m_core.OpenContent(tmd, content_index, uid, ticks);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,24 +77,24 @@ IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& r
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u32 content_index = memory.Read_U32(request.in_vectors[0].address);
|
const u32 content_index = memory.Read_U32(request.in_vectors[0].address);
|
||||||
|
|
||||||
if (!m_title_context.active)
|
if (!m_core.m_title_context.active)
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
|
||||||
ES::UIDSys uid_map{m_ios.GetFSDevice()};
|
ES::UIDSys uid_map{GetEmulationKernel().GetFSCore()};
|
||||||
const u32 uid = uid_map.GetOrInsertUIDForTitle(m_title_context.tmd.GetTitleId());
|
const u32 uid = uid_map.GetOrInsertUIDForTitle(m_core.m_title_context.tmd.GetTitleId());
|
||||||
ticks.Add(uid_map.GetTicks());
|
ticks.Add(uid_map.GetTicks());
|
||||||
if (caller_uid != 0 && caller_uid != uid)
|
if (caller_uid != 0 && caller_uid != uid)
|
||||||
return ES_EACCES;
|
return ES_EACCES;
|
||||||
|
|
||||||
return OpenContent(m_title_context.tmd, content_index, caller_uid, ticks);
|
return m_core.OpenContent(m_core.m_title_context.tmd, content_index, caller_uid, ticks);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ESDevice::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid, Ticks ticks)
|
s32 ESCore::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid, Ticks ticks)
|
||||||
{
|
{
|
||||||
if (cfd >= m_content_table.size())
|
if (cfd >= m_content_table.size())
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -105,7 +105,7 @@ s32 ESDevice::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid, Ticks ticks)
|
||||||
if (!entry.m_opened)
|
if (!entry.m_opened)
|
||||||
return IPC_EINVAL;
|
return IPC_EINVAL;
|
||||||
|
|
||||||
return m_ios.GetFSDevice()->Read(entry.m_fd, buffer, size, {}, ticks);
|
return m_ios.GetFSCore().Read(entry.m_fd, buffer, size, {}, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
|
IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
|
||||||
|
@ -114,7 +114,7 @@ IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
||||||
const u32 size = request.io_vectors[0].size;
|
const u32 size = request.io_vectors[0].size;
|
||||||
|
@ -122,11 +122,11 @@ IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
|
||||||
|
|
||||||
INFO_LOG_FMT(IOS_ES, "ReadContent(uid={:#x}, cfd={}, size={}, addr={:08x})", uid, cfd, size,
|
INFO_LOG_FMT(IOS_ES, "ReadContent(uid={:#x}, cfd={}, size={}, addr={:08x})", uid, cfd, size,
|
||||||
addr);
|
addr);
|
||||||
return ReadContent(cfd, memory.GetPointer(addr), size, uid, ticks);
|
return m_core.ReadContent(cfd, memory.GetPointer(addr), size, uid, ticks);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ESDevice::CloseContent(u32 cfd, u32 uid, Ticks ticks)
|
s32 ESCore::CloseContent(u32 cfd, u32 uid, Ticks ticks)
|
||||||
{
|
{
|
||||||
if (cfd >= m_content_table.size())
|
if (cfd >= m_content_table.size())
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -137,7 +137,7 @@ s32 ESDevice::CloseContent(u32 cfd, u32 uid, Ticks ticks)
|
||||||
if (!entry.m_opened)
|
if (!entry.m_opened)
|
||||||
return IPC_EINVAL;
|
return IPC_EINVAL;
|
||||||
|
|
||||||
m_ios.GetFSDevice()->Close(entry.m_fd, ticks);
|
m_ios.GetFSCore().Close(entry.m_fd, ticks);
|
||||||
entry = {};
|
entry = {};
|
||||||
INFO_LOG_FMT(IOS_ES, "CloseContent: CFD {}", cfd);
|
INFO_LOG_FMT(IOS_ES, "CloseContent: CFD {}", cfd);
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
|
@ -149,14 +149,14 @@ IPCReply ESDevice::CloseContent(u32 uid, const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
||||||
return CloseContent(cfd, uid, ticks);
|
return m_core.CloseContent(cfd, uid, ticks);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ESDevice::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid, Ticks ticks)
|
s32 ESCore::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid, Ticks ticks)
|
||||||
{
|
{
|
||||||
if (cfd >= m_content_table.size())
|
if (cfd >= m_content_table.size())
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -167,7 +167,7 @@ s32 ESDevice::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid, Ticks tic
|
||||||
if (!entry.m_opened)
|
if (!entry.m_opened)
|
||||||
return IPC_EINVAL;
|
return IPC_EINVAL;
|
||||||
|
|
||||||
return m_ios.GetFSDevice()->Seek(entry.m_fd, offset, static_cast<FS::SeekMode>(mode), ticks);
|
return m_ios.GetFSCore().Seek(entry.m_fd, offset, static_cast<FS::SeekMode>(mode), ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
|
IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
|
||||||
|
@ -176,13 +176,13 @@ IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(3, 0))
|
if (!request.HasNumberOfValidVectors(3, 0))
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
||||||
const u32 offset = memory.Read_U32(request.in_vectors[1].address);
|
const u32 offset = memory.Read_U32(request.in_vectors[1].address);
|
||||||
const auto mode = static_cast<SeekMode>(memory.Read_U32(request.in_vectors[2].address));
|
const auto mode = static_cast<SeekMode>(memory.Read_U32(request.in_vectors[2].address));
|
||||||
|
|
||||||
return SeekContent(cfd, offset, mode, uid, ticks);
|
return m_core.SeekContent(cfd, offset, mode, uid, ticks);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} // namespace IOS::HLE
|
} // namespace IOS::HLE
|
||||||
|
|
|
@ -21,8 +21,8 @@ IPCReply ESDevice::GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlV
|
||||||
if (request.io_vectors[0].size != sizeof(u32) || !tmd.IsValid())
|
if (request.io_vectors[0].size != sizeof(u32) || !tmd.IsValid())
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
const u16 num_contents = static_cast<u16>(GetStoredContentsFromTMD(tmd).size());
|
const u16 num_contents = static_cast<u16>(m_core.GetStoredContentsFromTMD(tmd).size());
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.Write_U32(num_contents, request.io_vectors[0].address);
|
memory.Write_U32(num_contents, request.io_vectors[0].address);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ IPCReply ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVReque
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
if (request.in_vectors[1].size != sizeof(u32) ||
|
if (request.in_vectors[1].size != sizeof(u32) ||
|
||||||
request.io_vectors[0].size != memory.Read_U32(request.in_vectors[1].address) * sizeof(u32))
|
request.io_vectors[0].size != memory.Read_U32(request.in_vectors[1].address) * sizeof(u32))
|
||||||
|
@ -46,7 +46,7 @@ IPCReply ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVReque
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto contents = GetStoredContentsFromTMD(tmd);
|
const auto contents = m_core.GetStoredContentsFromTMD(tmd);
|
||||||
const u32 max_content_count = memory.Read_U32(request.in_vectors[1].address);
|
const u32 max_content_count = memory.Read_U32(request.in_vectors[1].address);
|
||||||
for (u32 i = 0; i < std::min(static_cast<u32>(contents.size()), max_content_count); ++i)
|
for (u32 i = 0; i < std::min(static_cast<u32>(contents.size()), max_content_count); ++i)
|
||||||
memory.Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));
|
memory.Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));
|
||||||
|
@ -59,10 +59,10 @@ IPCReply ESDevice::GetStoredContentsCount(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u64))
|
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u64))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(title_id);
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(FS_ENOENT);
|
return IPCReply(FS_ENOENT);
|
||||||
return GetStoredContentsCount(tmd, request);
|
return GetStoredContentsCount(tmd, request);
|
||||||
|
@ -73,10 +73,10 @@ IPCReply ESDevice::GetStoredContents(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(2, 1) || request.in_vectors[0].size != sizeof(u64))
|
if (!request.HasNumberOfValidVectors(2, 1) || request.in_vectors[0].size != sizeof(u64))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(title_id);
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(FS_ENOENT);
|
return IPCReply(FS_ENOENT);
|
||||||
return GetStoredContents(tmd, request);
|
return GetStoredContents(tmd, request);
|
||||||
|
@ -88,7 +88,7 @@ IPCReply ESDevice::GetTMDStoredContentsCount(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
|
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
||||||
return GetStoredContentsCount(ES::TMDReader{std::move(tmd_bytes)}, request);
|
return GetStoredContentsCount(ES::TMDReader{std::move(tmd_bytes)}, request);
|
||||||
|
@ -100,7 +100,7 @@ IPCReply ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
|
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
||||||
|
|
||||||
|
@ -109,11 +109,12 @@ IPCReply ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
std::vector<u8> cert_store;
|
std::vector<u8> cert_store;
|
||||||
ReturnCode ret = ReadCertStore(&cert_store);
|
ReturnCode ret = m_core.ReadCertStore(&cert_store);
|
||||||
if (ret != IPC_SUCCESS)
|
if (ret != IPC_SUCCESS)
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
|
|
||||||
ret = VerifyContainer(VerifyContainerType::TMD, VerifyMode::UpdateCertStore, tmd, cert_store);
|
ret = m_core.VerifyContainer(ESCore::VerifyContainerType::TMD,
|
||||||
|
ESCore::VerifyMode::UpdateCertStore, tmd, cert_store);
|
||||||
if (ret != IPC_SUCCESS)
|
if (ret != IPC_SUCCESS)
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
|
|
||||||
|
@ -125,7 +126,7 @@ IPCReply ESDevice::GetTitleCount(const std::vector<u64>& titles, const IOCtlVReq
|
||||||
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
|
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
|
memory.Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
|
||||||
|
|
||||||
|
@ -137,7 +138,7 @@ IPCReply ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest
|
||||||
if (!request.HasNumberOfValidVectors(1, 1))
|
if (!request.HasNumberOfValidVectors(1, 1))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const size_t max_count = memory.Read_U32(request.in_vectors[0].address);
|
const size_t max_count = memory.Read_U32(request.in_vectors[0].address);
|
||||||
for (size_t i = 0; i < std::min(max_count, titles.size()); i++)
|
for (size_t i = 0; i < std::min(max_count, titles.size()); i++)
|
||||||
|
@ -150,14 +151,14 @@ IPCReply ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest
|
||||||
|
|
||||||
IPCReply ESDevice::GetTitleCount(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetTitleCount(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
const std::vector<u64> titles = GetInstalledTitles();
|
const std::vector<u64> titles = m_core.GetInstalledTitles();
|
||||||
INFO_LOG_FMT(IOS_ES, "GetTitleCount: {} titles", titles.size());
|
INFO_LOG_FMT(IOS_ES, "GetTitleCount: {} titles", titles.size());
|
||||||
return GetTitleCount(titles, request);
|
return GetTitleCount(titles, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::GetTitles(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetTitles(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
return GetTitles(GetInstalledTitles(), request);
|
return GetTitles(m_core.GetInstalledTitles(), request);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
|
||||||
|
@ -165,10 +166,10 @@ IPCReply ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 1))
|
if (!request.HasNumberOfValidVectors(1, 1))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(title_id);
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(FS_ENOENT);
|
return IPCReply(FS_ENOENT);
|
||||||
|
|
||||||
|
@ -185,10 +186,10 @@ IPCReply ESDevice::GetStoredTMD(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(2, 1))
|
if (!request.HasNumberOfValidVectors(2, 1))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(title_id);
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(FS_ENOENT);
|
return IPCReply(FS_ENOENT);
|
||||||
|
|
||||||
|
@ -207,14 +208,14 @@ IPCReply ESDevice::GetStoredTMD(const IOCtlVRequest& request)
|
||||||
|
|
||||||
IPCReply ESDevice::GetOwnedTitleCount(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetOwnedTitleCount(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
const std::vector<u64> titles = GetTitlesWithTickets();
|
const std::vector<u64> titles = m_core.GetTitlesWithTickets();
|
||||||
INFO_LOG_FMT(IOS_ES, "GetOwnedTitleCount: {} titles", titles.size());
|
INFO_LOG_FMT(IOS_ES, "GetOwnedTitleCount: {} titles", titles.size());
|
||||||
return GetTitleCount(titles, request);
|
return GetTitleCount(titles, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::GetOwnedTitles(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetOwnedTitles(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
return GetTitles(GetTitlesWithTickets(), request);
|
return GetTitles(m_core.GetTitlesWithTickets(), request);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::GetBoot2Version(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetBoot2Version(const IOCtlVRequest& request)
|
||||||
|
@ -225,7 +226,7 @@ IPCReply ESDevice::GetBoot2Version(const IOCtlVRequest& request)
|
||||||
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");
|
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");
|
||||||
|
|
||||||
// as of 26/02/2012, this was latest bootmii version
|
// as of 26/02/2012, this was latest bootmii version
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.Write_U32(4, request.io_vectors[0].address);
|
memory.Write_U32(4, request.io_vectors[0].address);
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
|
@ -236,8 +237,8 @@ IPCReply ESDevice::GetSharedContentsCount(const IOCtlVRequest& request) const
|
||||||
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
const u32 count = GetSharedContentsCount();
|
const u32 count = m_core.GetSharedContentsCount();
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.Write_U32(count, request.io_vectors[0].address);
|
memory.Write_U32(count, request.io_vectors[0].address);
|
||||||
|
|
||||||
|
@ -250,13 +251,13 @@ IPCReply ESDevice::GetSharedContents(const IOCtlVRequest& request) const
|
||||||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const u32 max_count = memory.Read_U32(request.in_vectors[0].address);
|
const u32 max_count = memory.Read_U32(request.in_vectors[0].address);
|
||||||
if (request.io_vectors[0].size != 20 * max_count)
|
if (request.io_vectors[0].size != 20 * max_count)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
const std::vector<std::array<u8, 20>> hashes = GetSharedContents();
|
const std::vector<std::array<u8, 20>> hashes = m_core.GetSharedContents();
|
||||||
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
|
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
|
||||||
memory.CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
|
memory.CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ static ReturnCode WriteTicket(FS::FileSystem* fs, const ES::TicketReader& ticket
|
||||||
return file->Write(raw_ticket.data(), raw_ticket.size()) ? IPC_SUCCESS : ES_EIO;
|
return file->Write(raw_ticket.data(), raw_ticket.size()) ? IPC_SUCCESS : ES_EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESDevice::TitleImportExportContext::DoState(PointerWrap& p)
|
void ESCore::TitleImportExportContext::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
p.Do(valid);
|
p.Do(valid);
|
||||||
p.Do(key_handle);
|
p.Do(key_handle);
|
||||||
|
@ -50,7 +50,7 @@ void ESDevice::TitleImportExportContext::DoState(PointerWrap& p)
|
||||||
p.Do(content.buffer);
|
p.Do(content.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportTicket(const std::vector<u8>& ticket_bytes,
|
ReturnCode ESCore::ImportTicket(const std::vector<u8>& ticket_bytes,
|
||||||
const std::vector<u8>& cert_chain, TicketImportType type,
|
const std::vector<u8>& cert_chain, TicketImportType type,
|
||||||
VerifySignature verify_signature)
|
VerifySignature verify_signature)
|
||||||
{
|
{
|
||||||
|
@ -98,14 +98,14 @@ IPCReply ESDevice::ImportTicket(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(3, 0))
|
if (!request.HasNumberOfValidVectors(3, 0))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
std::vector<u8> bytes(request.in_vectors[0].size);
|
std::vector<u8> bytes(request.in_vectors[0].size);
|
||||||
memory.CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
memory.CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
std::vector<u8> cert_chain(request.in_vectors[1].size);
|
std::vector<u8> cert_chain(request.in_vectors[1].size);
|
||||||
memory.CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
memory.CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
||||||
return IPCReply(ImportTicket(bytes, cert_chain));
|
return IPCReply(m_core.ImportTicket(bytes, cert_chain));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::array<u8, 16> NULL_KEY{};
|
constexpr std::array<u8, 16> NULL_KEY{};
|
||||||
|
@ -132,14 +132,14 @@ static ReturnCode InitBackupKey(u64 tid, u32 title_flags, IOSC& iosc, IOSC::Hand
|
||||||
return ret == IPC_SUCCESS ? iosc.ImportSecretKey(*key, NULL_KEY.data(), PID_ES) : ret;
|
return ret == IPC_SUCCESS ? iosc.ImportSecretKey(*key, NULL_KEY.data(), PID_ES) : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ResetTitleImportContext(ESDevice::Context* context, IOSC& iosc)
|
static void ResetTitleImportContext(ESCore::Context* context, IOSC& iosc)
|
||||||
{
|
{
|
||||||
if (context->title_import_export.key_handle)
|
if (context->title_import_export.key_handle)
|
||||||
iosc.DeleteObject(context->title_import_export.key_handle, PID_ES);
|
iosc.DeleteObject(context->title_import_export.key_handle, PID_ES);
|
||||||
context->title_import_export = {};
|
context->title_import_export = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportTmd(Context& context, const std::vector<u8>& tmd_bytes,
|
ReturnCode ESCore::ImportTmd(Context& context, const std::vector<u8>& tmd_bytes,
|
||||||
u64 caller_title_id, u32 caller_title_flags)
|
u64 caller_title_id, u32 caller_title_flags)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(IOS_ES, "ImportTmd");
|
INFO_LOG_FMT(IOS_ES, "ImportTmd");
|
||||||
|
@ -191,13 +191,13 @@ IPCReply ESDevice::ImportTmd(Context& context, const IOCtlVRequest& request)
|
||||||
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
|
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
std::vector<u8> tmd(request.in_vectors[0].size);
|
std::vector<u8> tmd(request.in_vectors[0].size);
|
||||||
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
return IPCReply(ImportTmd(context, tmd, m_title_context.tmd.GetTitleId(),
|
return IPCReply(m_core.ImportTmd(context, tmd, m_core.m_title_context.tmd.GetTitleId(),
|
||||||
m_title_context.tmd.GetTitleFlags()));
|
m_core.m_title_context.tmd.GetTitleFlags()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ReturnCode InitTitleImportKey(const std::vector<u8>& ticket_bytes, IOSC& iosc,
|
static ReturnCode InitTitleImportKey(const std::vector<u8>& ticket_bytes, IOSC& iosc,
|
||||||
|
@ -217,7 +217,7 @@ static ReturnCode InitTitleImportKey(const std::vector<u8>& ticket_bytes, IOSC&
|
||||||
&ticket_bytes[offsetof(ES::Ticket, title_key)], PID_ES);
|
&ticket_bytes[offsetof(ES::Ticket, title_key)], PID_ES);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportTitleInit(Context& context, const std::vector<u8>& tmd_bytes,
|
ReturnCode ESCore::ImportTitleInit(Context& context, const std::vector<u8>& tmd_bytes,
|
||||||
const std::vector<u8>& cert_chain,
|
const std::vector<u8>& cert_chain,
|
||||||
VerifySignature verify_signature)
|
VerifySignature verify_signature)
|
||||||
{
|
{
|
||||||
|
@ -280,17 +280,17 @@ IPCReply ESDevice::ImportTitleInit(Context& context, const IOCtlVRequest& reques
|
||||||
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
|
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
std::vector<u8> tmd(request.in_vectors[0].size);
|
std::vector<u8> tmd(request.in_vectors[0].size);
|
||||||
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
std::vector<u8> certs(request.in_vectors[1].size);
|
std::vector<u8> certs(request.in_vectors[1].size);
|
||||||
memory.CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
memory.CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
||||||
return IPCReply(ImportTitleInit(context, tmd, certs));
|
return IPCReply(m_core.ImportTitleInit(context, tmd, certs));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportContentBegin(Context& context, u64 title_id, u32 content_id)
|
ReturnCode ESCore::ImportContentBegin(Context& context, u64 title_id, u32 content_id)
|
||||||
{
|
{
|
||||||
if (context.title_import_export.content.valid)
|
if (context.title_import_export.content.valid)
|
||||||
{
|
{
|
||||||
|
@ -338,15 +338,15 @@ IPCReply ESDevice::ImportContentBegin(Context& context, const IOCtlVRequest& req
|
||||||
if (!request.HasNumberOfValidVectors(2, 0))
|
if (!request.HasNumberOfValidVectors(2, 0))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
u32 content_id = memory.Read_U32(request.in_vectors[1].address);
|
u32 content_id = memory.Read_U32(request.in_vectors[1].address);
|
||||||
return IPCReply(ImportContentBegin(context, title_id, content_id));
|
return IPCReply(m_core.ImportContentBegin(context, title_id, content_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportContentData(Context& context, u32 content_fd, const u8* data,
|
ReturnCode ESCore::ImportContentData(Context& context, u32 content_fd, const u8* data,
|
||||||
u32 data_size)
|
u32 data_size)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(IOS_ES, "ImportContentData: content fd {:08x}, size {}", content_fd, data_size);
|
INFO_LOG_FMT(IOS_ES, "ImportContentData: content fd {:08x}, size {}", content_fd, data_size);
|
||||||
|
@ -360,12 +360,13 @@ IPCReply ESDevice::ImportContentData(Context& context, const IOCtlVRequest& requ
|
||||||
if (!request.HasNumberOfValidVectors(2, 0))
|
if (!request.HasNumberOfValidVectors(2, 0))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||||
u8* data_start = memory.GetPointer(request.in_vectors[1].address);
|
u8* data_start = memory.GetPointer(request.in_vectors[1].address);
|
||||||
return IPCReply(ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
|
return IPCReply(
|
||||||
|
m_core.ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckIfContentHashMatches(const std::vector<u8>& content, const ES::Content& info)
|
static bool CheckIfContentHashMatches(const std::vector<u8>& content, const ES::Content& info)
|
||||||
|
@ -378,7 +379,7 @@ static std::string GetImportContentPath(u64 title_id, u32 content_id)
|
||||||
return fmt::format("{}/content/{:08x}.app", Common::GetImportTitlePath(title_id), content_id);
|
return fmt::format("{}/content/{:08x}.app", Common::GetImportTitlePath(title_id), content_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportContentEnd(Context& context, u32 content_fd)
|
ReturnCode ESCore::ImportContentEnd(Context& context, u32 content_fd)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(IOS_ES, "ImportContentEnd: content fd {:08x}", content_fd);
|
INFO_LOG_FMT(IOS_ES, "ImportContentEnd: content fd {:08x}", content_fd);
|
||||||
|
|
||||||
|
@ -407,7 +408,7 @@ ReturnCode ESDevice::ImportContentEnd(Context& context, u32 content_fd)
|
||||||
std::string content_path;
|
std::string content_path;
|
||||||
if (content_info.IsShared())
|
if (content_info.IsShared())
|
||||||
{
|
{
|
||||||
ES::SharedContentMap shared_content{m_ios.GetFSDevice()};
|
ES::SharedContentMap shared_content{m_ios.GetFSCore()};
|
||||||
content_path = shared_content.AddSharedContent(content_info.sha1);
|
content_path = shared_content.AddSharedContent(content_info.sha1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -446,18 +447,18 @@ IPCReply ESDevice::ImportContentEnd(Context& context, const IOCtlVRequest& reque
|
||||||
if (!request.HasNumberOfValidVectors(1, 0))
|
if (!request.HasNumberOfValidVectors(1, 0))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||||
return IPCReply(ImportContentEnd(context, content_fd));
|
return IPCReply(m_core.ImportContentEnd(context, content_fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
|
static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
|
||||||
{
|
{
|
||||||
const u64 title_id = tmd.GetTitleId();
|
const u64 title_id = tmd.GetTitleId();
|
||||||
const std::vector<ES::Content> contents = tmd.GetContents();
|
const std::vector<ES::Content> contents = tmd.GetContents();
|
||||||
const ES::SharedContentMap shared_content_map{ios.GetFSDevice()};
|
const ES::SharedContentMap shared_content_map{ios.GetFSCore()};
|
||||||
return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) {
|
return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) {
|
||||||
if (content.IsOptional())
|
if (content.IsOptional())
|
||||||
return true;
|
return true;
|
||||||
|
@ -472,7 +473,7 @@ static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportTitleDone(Context& context)
|
ReturnCode ESCore::ImportTitleDone(Context& context)
|
||||||
{
|
{
|
||||||
if (!context.title_import_export.valid || context.title_import_export.content.valid)
|
if (!context.title_import_export.valid || context.title_import_export.content.valid)
|
||||||
{
|
{
|
||||||
|
@ -512,10 +513,10 @@ IPCReply ESDevice::ImportTitleDone(Context& context, const IOCtlVRequest& reques
|
||||||
if (!request.HasNumberOfValidVectors(0, 0))
|
if (!request.HasNumberOfValidVectors(0, 0))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
return IPCReply(ImportTitleDone(context));
|
return IPCReply(m_core.ImportTitleDone(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ImportTitleCancel(Context& context)
|
ReturnCode ESCore::ImportTitleCancel(Context& context)
|
||||||
{
|
{
|
||||||
// The TMD buffer can exist without a valid title import context.
|
// The TMD buffer can exist without a valid title import context.
|
||||||
if (context.title_import_export.tmd.GetBytes().empty() ||
|
if (context.title_import_export.tmd.GetBytes().empty() ||
|
||||||
|
@ -538,7 +539,7 @@ IPCReply ESDevice::ImportTitleCancel(Context& context, const IOCtlVRequest& requ
|
||||||
if (!request.HasNumberOfValidVectors(0, 0))
|
if (!request.HasNumberOfValidVectors(0, 0))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
return IPCReply(ImportTitleCancel(context));
|
return IPCReply(m_core.ImportTitleCancel(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CanDeleteTitle(u64 title_id)
|
static bool CanDeleteTitle(u64 title_id)
|
||||||
|
@ -547,7 +548,7 @@ static bool CanDeleteTitle(u64 title_id)
|
||||||
return static_cast<u32>(title_id >> 32) != 0x00000001 || static_cast<u32>(title_id) > 0x101;
|
return static_cast<u32>(title_id >> 32) != 0x00000001 || static_cast<u32>(title_id) > 0x101;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::DeleteTitle(u64 title_id)
|
ReturnCode ESCore::DeleteTitle(u64 title_id)
|
||||||
{
|
{
|
||||||
if (!CanDeleteTitle(title_id))
|
if (!CanDeleteTitle(title_id))
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -561,14 +562,14 @@ IPCReply ESDevice::DeleteTitle(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
return IPCReply(DeleteTitle(title_id));
|
return IPCReply(m_core.DeleteTitle(title_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::DeleteTicket(const u8* ticket_view)
|
ReturnCode ESCore::DeleteTicket(const u8* ticket_view)
|
||||||
{
|
{
|
||||||
const auto fs = m_ios.GetFS();
|
const auto fs = m_ios.GetFS();
|
||||||
const u64 title_id = Common::swap64(ticket_view + offsetof(ES::TicketView, title_id));
|
const u64 title_id = Common::swap64(ticket_view + offsetof(ES::TicketView, title_id));
|
||||||
|
@ -622,12 +623,12 @@ IPCReply ESDevice::DeleteTicket(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
return IPCReply(DeleteTicket(memory.GetPointer(request.in_vectors[0].address)));
|
return IPCReply(m_core.DeleteTicket(memory.GetPointer(request.in_vectors[0].address)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::DeleteTitleContent(u64 title_id) const
|
ReturnCode ESCore::DeleteTitleContent(u64 title_id) const
|
||||||
{
|
{
|
||||||
if (!CanDeleteTitle(title_id))
|
if (!CanDeleteTitle(title_id))
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -651,12 +652,12 @@ IPCReply ESDevice::DeleteTitleContent(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
return IPCReply(DeleteTitleContent(memory.Read_U64(request.in_vectors[0].address)));
|
return IPCReply(m_core.DeleteTitleContent(memory.Read_U64(request.in_vectors[0].address)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::DeleteContent(u64 title_id, u32 content_id) const
|
ReturnCode ESCore::DeleteContent(u64 title_id, u32 content_id) const
|
||||||
{
|
{
|
||||||
if (!CanDeleteTitle(title_id))
|
if (!CanDeleteTitle(title_id))
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -682,13 +683,13 @@ IPCReply ESDevice::DeleteContent(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
return IPCReply(DeleteContent(memory.Read_U64(request.in_vectors[0].address),
|
return IPCReply(m_core.DeleteContent(memory.Read_U64(request.in_vectors[0].address),
|
||||||
memory.Read_U32(request.in_vectors[1].address)));
|
memory.Read_U32(request.in_vectors[1].address)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u32 tmd_size,
|
ReturnCode ESCore::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u32 tmd_size,
|
||||||
u64 caller_title_id, u32 caller_title_flags)
|
u64 caller_title_id, u32 caller_title_flags)
|
||||||
{
|
{
|
||||||
// No concurrent title import/export is allowed.
|
// No concurrent title import/export is allowed.
|
||||||
|
@ -722,19 +723,19 @@ IPCReply ESDevice::ExportTitleInit(Context& context, const IOCtlVRequest& reques
|
||||||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8)
|
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
u8* tmd_bytes = memory.GetPointer(request.io_vectors[0].address);
|
u8* tmd_bytes = memory.GetPointer(request.io_vectors[0].address);
|
||||||
const u32 tmd_size = request.io_vectors[0].size;
|
const u32 tmd_size = request.io_vectors[0].size;
|
||||||
|
|
||||||
return IPCReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
|
return IPCReply(m_core.ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
|
||||||
m_title_context.tmd.GetTitleId(),
|
m_core.m_title_context.tmd.GetTitleId(),
|
||||||
m_title_context.tmd.GetTitleFlags()));
|
m_core.m_title_context.tmd.GetTitleFlags()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ExportContentBegin(Context& context, u64 title_id, u32 content_id)
|
ReturnCode ESCore::ExportContentBegin(Context& context, u64 title_id, u32 content_id)
|
||||||
{
|
{
|
||||||
context.title_import_export.content = {};
|
context.title_import_export.content = {};
|
||||||
if (!context.title_import_export.valid ||
|
if (!context.title_import_export.valid ||
|
||||||
|
@ -771,16 +772,16 @@ IPCReply ESDevice::ExportContentBegin(Context& context, const IOCtlVRequest& req
|
||||||
request.in_vectors[1].size != 4)
|
request.in_vectors[1].size != 4)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const u32 content_id = memory.Read_U32(request.in_vectors[1].address);
|
const u32 content_id = memory.Read_U32(request.in_vectors[1].address);
|
||||||
|
|
||||||
return IPCReply(ExportContentBegin(context, title_id, content_id));
|
return IPCReply(m_core.ExportContentBegin(context, title_id, content_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ExportContentData(Context& context, u32 content_fd, u8* data, u32 data_size)
|
ReturnCode ESCore::ExportContentData(Context& context, u32 content_fd, u8* data, u32 data_size)
|
||||||
{
|
{
|
||||||
if (!context.title_import_export.valid || !context.title_import_export.content.valid || !data ||
|
if (!context.title_import_export.valid || !context.title_import_export.content.valid || !data ||
|
||||||
data_size == 0)
|
data_size == 0)
|
||||||
|
@ -822,17 +823,17 @@ IPCReply ESDevice::ExportContentData(Context& context, const IOCtlVRequest& requ
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||||
u8* data = memory.GetPointer(request.io_vectors[0].address);
|
u8* data = memory.GetPointer(request.io_vectors[0].address);
|
||||||
const u32 bytes_to_read = request.io_vectors[0].size;
|
const u32 bytes_to_read = request.io_vectors[0].size;
|
||||||
|
|
||||||
return IPCReply(ExportContentData(context, content_fd, data, bytes_to_read));
|
return IPCReply(m_core.ExportContentData(context, content_fd, data, bytes_to_read));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ExportContentEnd(Context& context, u32 content_fd)
|
ReturnCode ESCore::ExportContentEnd(Context& context, u32 content_fd)
|
||||||
{
|
{
|
||||||
if (!context.title_import_export.valid || !context.title_import_export.content.valid)
|
if (!context.title_import_export.valid || !context.title_import_export.content.valid)
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -844,14 +845,14 @@ IPCReply ESDevice::ExportContentEnd(Context& context, const IOCtlVRequest& reque
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4)
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||||
return IPCReply(ExportContentEnd(context, content_fd));
|
return IPCReply(m_core.ExportContentEnd(context, content_fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::ExportTitleDone(Context& context)
|
ReturnCode ESCore::ExportTitleDone(Context& context)
|
||||||
{
|
{
|
||||||
ResetTitleImportContext(&context, m_ios.GetIOSC());
|
ResetTitleImportContext(&context, m_ios.GetIOSC());
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
|
@ -859,12 +860,12 @@ ReturnCode ESDevice::ExportTitleDone(Context& context)
|
||||||
|
|
||||||
IPCReply ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& request)
|
IPCReply ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
return IPCReply(ExportTitleDone(context));
|
return IPCReply(m_core.ExportTitleDone(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::DeleteSharedContent(const std::array<u8, 20>& sha1) const
|
ReturnCode ESCore::DeleteSharedContent(const std::array<u8, 20>& sha1) const
|
||||||
{
|
{
|
||||||
ES::SharedContentMap map{m_ios.GetFSDevice()};
|
ES::SharedContentMap map{m_ios.GetFSCore()};
|
||||||
const auto content_path = map.GetFilenameFromSHA1(sha1);
|
const auto content_path = map.GetFilenameFromSHA1(sha1);
|
||||||
if (!content_path)
|
if (!content_path)
|
||||||
return ES_EINVAL;
|
return ES_EINVAL;
|
||||||
|
@ -905,10 +906,10 @@ IPCReply ESDevice::DeleteSharedContent(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sha1.size())
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sha1.size())
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
memory.CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
memory.CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
return IPCReply(DeleteSharedContent(sha1));
|
return IPCReply(m_core.DeleteSharedContent(sha1));
|
||||||
}
|
}
|
||||||
} // namespace IOS::HLE
|
} // namespace IOS::HLE
|
||||||
|
|
|
@ -41,12 +41,12 @@ IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 1))
|
if (!request.HasNumberOfValidVectors(1, 1))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
|
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
|
||||||
|
|
||||||
const ES::TicketReader ticket = FindSignedTicket(TitleID);
|
const ES::TicketReader ticket = m_core.FindSignedTicket(TitleID);
|
||||||
u32 view_count = ticket.IsValid() ? static_cast<u32>(ticket.GetNumberOfTickets()) : 0;
|
u32 view_count = ticket.IsValid() ? static_cast<u32>(ticket.GetNumberOfTickets()) : 0;
|
||||||
|
|
||||||
if (!IsEmulated(TitleID))
|
if (!IsEmulated(TitleID))
|
||||||
|
@ -54,7 +54,7 @@ IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
|
||||||
view_count = 0;
|
view_count = 0;
|
||||||
ERROR_LOG_FMT(IOS_ES, "GetViewCount: Dolphin doesn't emulate IOS title {:016x}", TitleID);
|
ERROR_LOG_FMT(IOS_ES, "GetViewCount: Dolphin doesn't emulate IOS title {:016x}", TitleID);
|
||||||
}
|
}
|
||||||
else if (ShouldReturnFakeViewsForIOSes(TitleID, m_title_context))
|
else if (ShouldReturnFakeViewsForIOSes(TitleID, m_core.m_title_context))
|
||||||
{
|
{
|
||||||
view_count = 1;
|
view_count = 1;
|
||||||
WARN_LOG_FMT(IOS_ES, "GetViewCount: Faking IOS title {:016x} being present", TitleID);
|
WARN_LOG_FMT(IOS_ES, "GetViewCount: Faking IOS title {:016x} being present", TitleID);
|
||||||
|
@ -72,13 +72,13 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(2, 1))
|
if (!request.HasNumberOfValidVectors(2, 1))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
|
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const u32 maxViews = memory.Read_U32(request.in_vectors[1].address);
|
const u32 maxViews = memory.Read_U32(request.in_vectors[1].address);
|
||||||
|
|
||||||
const ES::TicketReader ticket = FindSignedTicket(TitleID);
|
const ES::TicketReader ticket = m_core.FindSignedTicket(TitleID);
|
||||||
|
|
||||||
if (!IsEmulated(TitleID))
|
if (!IsEmulated(TitleID))
|
||||||
{
|
{
|
||||||
|
@ -94,7 +94,7 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
|
||||||
ticket_view.data(), ticket_view.size());
|
ticket_view.data(), ticket_view.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ShouldReturnFakeViewsForIOSes(TitleID, m_title_context))
|
else if (ShouldReturnFakeViewsForIOSes(TitleID, m_core.m_title_context))
|
||||||
{
|
{
|
||||||
memory.Memset(request.io_vectors[0].address, 0, sizeof(ES::TicketView));
|
memory.Memset(request.io_vectors[0].address, 0, sizeof(ES::TicketView));
|
||||||
WARN_LOG_FMT(IOS_ES, "GetViews: Faking IOS title {:016x} being present", TitleID);
|
WARN_LOG_FMT(IOS_ES, "GetViews: Faking IOS title {:016x} being present", TitleID);
|
||||||
|
@ -105,7 +105,7 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ESDevice::GetTicketFromView(const u8* ticket_view, u8* ticket, u32* ticket_size,
|
ReturnCode ESCore::GetTicketFromView(const u8* ticket_view, u8* ticket, u32* ticket_size,
|
||||||
std::optional<u8> desired_version) const
|
std::optional<u8> desired_version) const
|
||||||
{
|
{
|
||||||
const u64 title_id = Common::swap64(&ticket_view[offsetof(ES::TicketView, title_id)]);
|
const u64 title_id = Common::swap64(&ticket_view[offsetof(ES::TicketView, title_id)]);
|
||||||
|
@ -160,10 +160,11 @@ IPCReply ESDevice::GetV0TicketFromView(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
return IPCReply(GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
|
return IPCReply(m_core.GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
|
||||||
memory.GetPointer(request.io_vectors[0].address), nullptr, 0));
|
memory.GetPointer(request.io_vectors[0].address),
|
||||||
|
nullptr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
|
||||||
|
@ -176,9 +177,9 @@ IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
const ReturnCode ret = GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
|
const ReturnCode ret = m_core.GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
|
||||||
nullptr, &ticket_size, std::nullopt);
|
nullptr, &ticket_size, std::nullopt);
|
||||||
memory.Write_U32(ticket_size, request.io_vectors[0].address);
|
memory.Write_U32(ticket_size, request.io_vectors[0].address);
|
||||||
return IPCReply(ret);
|
return IPCReply(ret);
|
||||||
|
@ -193,16 +194,16 @@ IPCReply ESDevice::GetTicketFromView(const IOCtlVRequest& request)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
u32 ticket_size = memory.Read_U32(request.in_vectors[1].address);
|
u32 ticket_size = memory.Read_U32(request.in_vectors[1].address);
|
||||||
if (ticket_size != request.io_vectors[0].size)
|
if (ticket_size != request.io_vectors[0].size)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
return IPCReply(GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
|
return IPCReply(m_core.GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
|
||||||
memory.GetPointer(request.io_vectors[0].address), &ticket_size,
|
memory.GetPointer(request.io_vectors[0].address),
|
||||||
std::nullopt));
|
&ticket_size, std::nullopt));
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
|
||||||
|
@ -210,11 +211,11 @@ IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 1))
|
if (!request.HasNumberOfValidVectors(1, 1))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
|
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(TitleID);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(TitleID);
|
||||||
|
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(FS_ENOENT);
|
return IPCReply(FS_ENOENT);
|
||||||
|
@ -228,7 +229,7 @@ IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
|
||||||
|
|
||||||
IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
|
IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
if (!request.HasNumberOfValidVectors(2, 1) ||
|
if (!request.HasNumberOfValidVectors(2, 1) ||
|
||||||
|
@ -240,7 +241,7 @@ IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
const ES::TMDReader tmd = m_core.FindInstalledTMD(title_id);
|
||||||
|
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return IPCReply(FS_ENOENT);
|
return IPCReply(FS_ENOENT);
|
||||||
|
@ -267,7 +268,7 @@ IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
|
||||||
if (request.io_vectors[0].size != sizeof(u32))
|
if (request.io_vectors[0].size != sizeof(u32))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const bool has_tmd = request.in_vectors[0].size != 0;
|
const bool has_tmd = request.in_vectors[0].size != 0;
|
||||||
|
@ -289,10 +290,10 @@ IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If no TMD was passed in and no title is active, IOS returns -1017.
|
// If no TMD was passed in and no title is active, IOS returns -1017.
|
||||||
if (!m_title_context.active)
|
if (!m_core.m_title_context.active)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
tmd_view_size = m_title_context.tmd.GetRawView().size();
|
tmd_view_size = m_core.m_title_context.tmd.GetRawView().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
memory.Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
|
memory.Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
|
||||||
|
@ -308,7 +309,7 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
|
||||||
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
|
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
// Check whether the TMD view size is consistent.
|
// Check whether the TMD view size is consistent.
|
||||||
|
@ -335,10 +336,10 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If no TMD was passed in and no title is active, IOS returns -1017.
|
// If no TMD was passed in and no title is active, IOS returns -1017.
|
||||||
if (!m_title_context.active)
|
if (!m_core.m_title_context.active)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
tmd_view = m_title_context.tmd.GetRawView();
|
tmd_view = m_core.m_title_context.tmd.GetRawView();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmd_view.size() > request.io_vectors[0].size)
|
if (tmd_view.size() > request.io_vectors[0].size)
|
||||||
|
@ -362,7 +363,7 @@ IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
|
||||||
if (!has_ticket_vector && request.in_vectors[0].size != 0)
|
if (!has_ticket_vector && request.in_vectors[0].size != 0)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
std::vector<u8> view;
|
std::vector<u8> view;
|
||||||
|
@ -371,10 +372,10 @@ IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
|
||||||
// Of course, this returns -1017 if no title is active and no ticket is passed.
|
// Of course, this returns -1017 if no title is active and no ticket is passed.
|
||||||
if (!has_ticket_vector)
|
if (!has_ticket_vector)
|
||||||
{
|
{
|
||||||
if (!m_title_context.active)
|
if (!m_core.m_title_context.active)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
view = m_title_context.ticket.GetRawTicketView(0);
|
view = m_core.m_title_context.ticket.GetRawTicketView(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -394,12 +395,12 @@ IPCReply ESDevice::DIGetTMDSize(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
if (!m_title_context.active)
|
if (!m_core.m_title_context.active)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
memory.Write_U32(static_cast<u32>(m_title_context.tmd.GetBytes().size()),
|
memory.Write_U32(static_cast<u32>(m_core.m_title_context.tmd.GetBytes().size()),
|
||||||
request.io_vectors[0].address);
|
request.io_vectors[0].address);
|
||||||
return IPCReply(IPC_SUCCESS);
|
return IPCReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -409,17 +410,17 @@ IPCReply ESDevice::DIGetTMD(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const u32 tmd_size = memory.Read_U32(request.in_vectors[0].address);
|
const u32 tmd_size = memory.Read_U32(request.in_vectors[0].address);
|
||||||
if (tmd_size != request.io_vectors[0].size)
|
if (tmd_size != request.io_vectors[0].size)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
if (!m_title_context.active)
|
if (!m_core.m_title_context.active)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
||||||
const std::vector<u8>& tmd_bytes = m_title_context.tmd.GetBytes();
|
const std::vector<u8>& tmd_bytes = m_core.m_title_context.tmd.GetBytes();
|
||||||
|
|
||||||
if (static_cast<u32>(tmd_bytes.size()) > tmd_size)
|
if (static_cast<u32>(tmd_bytes.size()) > tmd_size)
|
||||||
return IPCReply(ES_EINVAL);
|
return IPCReply(ES_EINVAL);
|
||||||
|
|
|
@ -83,7 +83,7 @@ constexpr SystemTimers::TimeBaseTick GetFreeClusterCheckTbTicks()
|
||||||
|
|
||||||
constexpr size_t CLUSTER_DATA_SIZE = 0x4000;
|
constexpr size_t CLUSTER_DATA_SIZE = 0x4000;
|
||||||
|
|
||||||
FSDevice::FSDevice(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
|
FSCore::FSCore(Kernel& ios) : m_ios(ios)
|
||||||
{
|
{
|
||||||
if (ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, "/tmp") == ResultCode::Success)
|
if (ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, "/tmp") == ResultCode::Success)
|
||||||
{
|
{
|
||||||
|
@ -92,14 +92,23 @@ FSDevice::FSDevice(Kernel& ios, const std::string& device_name) : Device(ios, de
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSCore::~FSCore() = default;
|
||||||
|
|
||||||
|
FSDevice::FSDevice(EmulationKernel& ios, FSCore& core, const std::string& device_name)
|
||||||
|
: EmulationDevice(ios, device_name), m_core(core)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FSDevice::~FSDevice() = default;
|
||||||
|
|
||||||
void FSDevice::DoState(PointerWrap& p)
|
void FSDevice::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
Device::DoState(p);
|
Device::DoState(p);
|
||||||
p.Do(m_dirty_cache);
|
p.Do(m_core.m_dirty_cache);
|
||||||
p.Do(m_cache_chain_index);
|
p.Do(m_core.m_cache_chain_index);
|
||||||
p.Do(m_cache_fd);
|
p.Do(m_core.m_cache_fd);
|
||||||
p.Do(m_next_fd);
|
p.Do(m_core.m_next_fd);
|
||||||
p.Do(m_fd_map);
|
p.Do(m_core.m_fd_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@ -161,13 +170,14 @@ static IPCReply GetReplyForSuperblockOperation(int ios_version, ResultCode resul
|
||||||
std::optional<IPCReply> FSDevice::Open(const OpenRequest& request)
|
std::optional<IPCReply> FSDevice::Open(const OpenRequest& request)
|
||||||
{
|
{
|
||||||
return MakeIPCReply([&](Ticks t) {
|
return MakeIPCReply([&](Ticks t) {
|
||||||
return Open(request.uid, request.gid, request.path, static_cast<Mode>(request.flags & 3),
|
return m_core
|
||||||
|
.Open(request.uid, request.gid, request.path, static_cast<Mode>(request.flags & 3),
|
||||||
request.fd, t)
|
request.fd, t)
|
||||||
.Release();
|
.Release();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FSDevice::ScopedFd FSDevice::Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode,
|
FSCore::ScopedFd FSCore::Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode,
|
||||||
std::optional<u32> ipc_fd, Ticks ticks)
|
std::optional<u32> ipc_fd, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
@ -200,10 +210,10 @@ FSDevice::ScopedFd FSDevice::Open(FS::Uid uid, FS::Gid gid, const std::string& p
|
||||||
|
|
||||||
std::optional<IPCReply> FSDevice::Close(u32 fd)
|
std::optional<IPCReply> FSDevice::Close(u32 fd)
|
||||||
{
|
{
|
||||||
return MakeIPCReply([&](Ticks t) { return Close(static_cast<u64>(fd), t); });
|
return MakeIPCReply([&](Ticks t) { return m_core.Close(static_cast<u64>(fd), t); });
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 FSDevice::Close(u64 fd, Ticks ticks)
|
s32 FSCore::Close(u64 fd, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
|
||||||
|
@ -232,7 +242,7 @@ s32 FSDevice::Close(u64 fd, Ticks ticks)
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 FSDevice::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size)
|
u64 FSCore::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size)
|
||||||
{
|
{
|
||||||
if (HasCacheForFile(fd, offset))
|
if (HasCacheForFile(fd, offset))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -246,7 +256,7 @@ u64 FSDevice::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size)
|
||||||
return ticks;
|
return ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 FSDevice::SimulateFlushFileCache()
|
u64 FSCore::SimulateFlushFileCache()
|
||||||
{
|
{
|
||||||
if (!m_cache_fd.has_value() || !m_dirty_cache)
|
if (!m_cache_fd.has_value() || !m_dirty_cache)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -256,7 +266,7 @@ u64 FSDevice::SimulateFlushFileCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate parts of the FS read/write logic to estimate ticks for file operations correctly.
|
// Simulate parts of the FS read/write logic to estimate ticks for file operations correctly.
|
||||||
u64 FSDevice::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command,
|
u64 FSCore::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command,
|
||||||
u32 size)
|
u32 size)
|
||||||
{
|
{
|
||||||
u64 ticks = 0;
|
u64 ticks = 0;
|
||||||
|
@ -304,7 +314,7 @@ u64 FSDevice::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommand
|
||||||
return ticks;
|
return ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const
|
bool FSCore::HasCacheForFile(u64 fd, u32 offset) const
|
||||||
{
|
{
|
||||||
const u16 chain_index = static_cast<u16>(offset / CLUSTER_DATA_SIZE);
|
const u16 chain_index = static_cast<u16>(offset / CLUSTER_DATA_SIZE);
|
||||||
return m_cache_fd == fd && m_cache_chain_index == chain_index;
|
return m_cache_fd == fd && m_cache_chain_index == chain_index;
|
||||||
|
@ -313,13 +323,14 @@ bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const
|
||||||
std::optional<IPCReply> FSDevice::Read(const ReadWriteRequest& request)
|
std::optional<IPCReply> FSDevice::Read(const ReadWriteRequest& request)
|
||||||
{
|
{
|
||||||
return MakeIPCReply([&](Ticks t) {
|
return MakeIPCReply([&](Ticks t) {
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
return Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
|
return m_core.Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer,
|
||||||
|
t);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_addr, Ticks ticks)
|
s32 FSCore::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_addr, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
|
||||||
|
@ -343,14 +354,14 @@ s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_add
|
||||||
std::optional<IPCReply> FSDevice::Write(const ReadWriteRequest& request)
|
std::optional<IPCReply> FSDevice::Write(const ReadWriteRequest& request)
|
||||||
{
|
{
|
||||||
return MakeIPCReply([&](Ticks t) {
|
return MakeIPCReply([&](Ticks t) {
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
return Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
|
return m_core.Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer,
|
||||||
|
t);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 FSDevice::Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buffer_addr,
|
s32 FSCore::Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buffer_addr, Ticks ticks)
|
||||||
Ticks ticks)
|
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
|
||||||
|
@ -374,11 +385,11 @@ s32 FSDevice::Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buf
|
||||||
std::optional<IPCReply> FSDevice::Seek(const SeekRequest& request)
|
std::optional<IPCReply> FSDevice::Seek(const SeekRequest& request)
|
||||||
{
|
{
|
||||||
return MakeIPCReply([&](Ticks t) {
|
return MakeIPCReply([&](Ticks t) {
|
||||||
return Seek(request.fd, request.offset, HLE::FS::SeekMode(request.mode), t);
|
return m_core.Seek(request.fd, request.offset, HLE::FS::SeekMode(request.mode), t);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 FSDevice::Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks)
|
s32 FSCore::Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
|
||||||
|
@ -422,14 +433,11 @@ struct ISFSFileStats
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static Result<T> GetParams(const IOCtlRequest& request)
|
static Result<T> GetParams(Memory::MemoryManager& memory, const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
if (request.buffer_in_size < sizeof(T))
|
if (request.buffer_in_size < sizeof(T))
|
||||||
return ResultCode::Invalid;
|
return ResultCode::Invalid;
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
|
||||||
auto& memory = system.GetMemory();
|
|
||||||
|
|
||||||
T params;
|
T params;
|
||||||
memory.CopyFromEmu(¶ms, request.buffer_in, sizeof(params));
|
memory.CopyFromEmu(¶ms, request.buffer_in, sizeof(params));
|
||||||
return params;
|
return params;
|
||||||
|
@ -437,8 +445,8 @@ static Result<T> GetParams(const IOCtlRequest& request)
|
||||||
|
|
||||||
std::optional<IPCReply> FSDevice::IOCtl(const IOCtlRequest& request)
|
std::optional<IPCReply> FSDevice::IOCtl(const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
const auto it = m_fd_map.find(request.fd);
|
const auto it = m_core.m_fd_map.find(request.fd);
|
||||||
if (it == m_fd_map.end())
|
if (it == m_core.m_fd_map.end())
|
||||||
return IPCReply(ConvertResult(ResultCode::Invalid));
|
return IPCReply(ConvertResult(ResultCode::Invalid));
|
||||||
|
|
||||||
switch (request.request)
|
switch (request.request)
|
||||||
|
@ -472,8 +480,8 @@ std::optional<IPCReply> FSDevice::IOCtl(const IOCtlRequest& request)
|
||||||
|
|
||||||
std::optional<IPCReply> FSDevice::IOCtlV(const IOCtlVRequest& request)
|
std::optional<IPCReply> FSDevice::IOCtlV(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
const auto it = m_fd_map.find(request.fd);
|
const auto it = m_core.m_fd_map.find(request.fd);
|
||||||
if (it == m_fd_map.end())
|
if (it == m_core.m_fd_map.end())
|
||||||
return IPCReply(ConvertResult(ResultCode::Invalid));
|
return IPCReply(ConvertResult(ResultCode::Invalid));
|
||||||
|
|
||||||
switch (request.request)
|
switch (request.request)
|
||||||
|
@ -506,7 +514,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
|
||||||
if (!stats)
|
if (!stats)
|
||||||
return IPCReply(ConvertResult(stats.Error()));
|
return IPCReply(ConvertResult(stats.Error()));
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
ISFSNandStats out;
|
ISFSNandStats out;
|
||||||
|
@ -523,7 +531,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
|
||||||
|
|
||||||
IPCReply FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request)
|
IPCReply FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
const auto params = GetParams<ISFSParams>(request);
|
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||||
if (!params)
|
if (!params)
|
||||||
return GetFSReply(ConvertResult(params.Error()));
|
return GetFSReply(ConvertResult(params.Error()));
|
||||||
|
|
||||||
|
@ -541,7 +549,7 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ
|
||||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
u32 file_list_address, file_count_address, max_count;
|
u32 file_list_address, file_count_address, max_count;
|
||||||
|
@ -592,7 +600,7 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ
|
||||||
|
|
||||||
IPCReply FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request)
|
IPCReply FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
const auto params = GetParams<ISFSParams>(request);
|
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||||
if (!params)
|
if (!params)
|
||||||
return GetFSReply(ConvertResult(params.Error()));
|
return GetFSReply(ConvertResult(params.Error()));
|
||||||
|
|
||||||
|
@ -607,7 +615,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
|
||||||
if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams))
|
if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams))
|
||||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const std::string path = memory.GetString(request.buffer_in, 64);
|
const std::string path = memory.GetString(request.buffer_in, 64);
|
||||||
|
@ -629,7 +637,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
|
||||||
return GetFSReply(IPC_SUCCESS, ticks);
|
return GetFSReply(IPC_SUCCESS, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
FS::ResultCode FSDevice::DeleteFile(FS::Uid uid, FS::Gid gid, const std::string& path, Ticks ticks)
|
FS::ResultCode FSCore::DeleteFile(FS::Uid uid, FS::Gid gid, const std::string& path, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
|
||||||
|
@ -644,15 +652,16 @@ IPCReply FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
|
||||||
if (request.buffer_in_size < 64)
|
if (request.buffer_in_size < 64)
|
||||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const std::string path = memory.GetString(request.buffer_in, 64);
|
const std::string path = memory.GetString(request.buffer_in, 64);
|
||||||
return MakeIPCReply(
|
return MakeIPCReply([&](Ticks ticks) {
|
||||||
[&](Ticks ticks) { return ConvertResult(DeleteFile(handle.uid, handle.gid, path, ticks)); });
|
return ConvertResult(m_core.DeleteFile(handle.uid, handle.gid, path, ticks));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FS::ResultCode FSDevice::RenameFile(FS::Uid uid, FS::Gid gid, const std::string& old_path,
|
FS::ResultCode FSCore::RenameFile(FS::Uid uid, FS::Gid gid, const std::string& old_path,
|
||||||
const std::string& new_path, Ticks ticks)
|
const std::string& new_path, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
@ -668,17 +677,17 @@ IPCReply FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
|
||||||
if (request.buffer_in_size < 64 * 2)
|
if (request.buffer_in_size < 64 * 2)
|
||||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const std::string old_path = memory.GetString(request.buffer_in, 64);
|
const std::string old_path = memory.GetString(request.buffer_in, 64);
|
||||||
const std::string new_path = memory.GetString(request.buffer_in + 64, 64);
|
const std::string new_path = memory.GetString(request.buffer_in + 64, 64);
|
||||||
return MakeIPCReply([&](Ticks ticks) {
|
return MakeIPCReply([&](Ticks ticks) {
|
||||||
return ConvertResult(RenameFile(handle.uid, handle.gid, old_path, new_path, ticks));
|
return ConvertResult(m_core.RenameFile(handle.uid, handle.gid, old_path, new_path, ticks));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FS::ResultCode FSDevice::CreateFile(FS::Uid uid, FS::Gid gid, const std::string& path,
|
FS::ResultCode FSCore::CreateFile(FS::Uid uid, FS::Gid gid, const std::string& path,
|
||||||
FS::FileAttribute attribute, FS::Modes modes, Ticks ticks)
|
FS::FileAttribute attribute, FS::Modes modes, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
|
@ -691,18 +700,18 @@ FS::ResultCode FSDevice::CreateFile(FS::Uid uid, FS::Gid gid, const std::string&
|
||||||
|
|
||||||
IPCReply FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request)
|
IPCReply FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
const auto params = GetParams<ISFSParams>(request);
|
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||||
if (!params)
|
if (!params)
|
||||||
return GetFSReply(ConvertResult(params.Error()));
|
return GetFSReply(ConvertResult(params.Error()));
|
||||||
return MakeIPCReply([&](Ticks ticks) {
|
return MakeIPCReply([&](Ticks ticks) {
|
||||||
return ConvertResult(
|
return ConvertResult(
|
||||||
CreateFile(handle.uid, handle.gid, params->path, params->attribute, params->modes));
|
m_core.CreateFile(handle.uid, handle.gid, params->path, params->attribute, params->modes));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCReply FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request)
|
IPCReply FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
const auto params = GetParams<ISFSParams>(request);
|
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||||
if (!params)
|
if (!params)
|
||||||
return GetFSReply(ConvertResult(params.Error()));
|
return GetFSReply(ConvertResult(params.Error()));
|
||||||
|
|
||||||
|
@ -718,11 +727,11 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques
|
||||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||||
|
|
||||||
return MakeIPCReply([&](Ticks ticks) {
|
return MakeIPCReply([&](Ticks ticks) {
|
||||||
const Result<FileStatus> status = GetFileStatus(request.fd, ticks);
|
const Result<FileStatus> status = m_core.GetFileStatus(request.fd, ticks);
|
||||||
if (!status)
|
if (!status)
|
||||||
return ConvertResult(status.Error());
|
return ConvertResult(status.Error());
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
ISFSFileStats out;
|
ISFSFileStats out;
|
||||||
|
@ -733,7 +742,7 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FS::Result<FS::FileStatus> FSDevice::GetFileStatus(u64 fd, Ticks ticks)
|
FS::Result<FS::FileStatus> FSCore::GetFileStatus(u64 fd, Ticks ticks)
|
||||||
{
|
{
|
||||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||||
const auto& handle = m_fd_map[fd];
|
const auto& handle = m_fd_map[fd];
|
||||||
|
@ -753,7 +762,7 @@ IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
|
||||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = GetSystem();
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
const std::string directory = memory.GetString(request.in_vectors[0].address, 64);
|
const std::string directory = memory.GetString(request.in_vectors[0].address, 64);
|
||||||
|
|
|
@ -20,13 +20,22 @@ namespace IOS::HLE
|
||||||
{
|
{
|
||||||
constexpr FS::Fd INVALID_FD = 0xffffffff;
|
constexpr FS::Fd INVALID_FD = 0xffffffff;
|
||||||
|
|
||||||
class FSDevice : public Device
|
class FSDevice;
|
||||||
|
|
||||||
|
class FSCore final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit FSCore(Kernel& ios);
|
||||||
|
FSCore(const FSCore& other) = delete;
|
||||||
|
FSCore(FSCore&& other) = delete;
|
||||||
|
FSCore& operator=(const FSCore& other) = delete;
|
||||||
|
FSCore& operator=(FSCore&& other) = delete;
|
||||||
|
~FSCore();
|
||||||
|
|
||||||
class ScopedFd
|
class ScopedFd
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopedFd(FSDevice* fs, s64 fd, Ticks tick_tracker = {})
|
ScopedFd(FSCore* fs, s64 fd, Ticks tick_tracker = {})
|
||||||
: m_fs{fs}, m_fd{fd}, m_tick_tracker{tick_tracker}
|
: m_fs{fs}, m_fd{fd}, m_tick_tracker{tick_tracker}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -46,13 +55,11 @@ public:
|
||||||
s64 Release() { return std::exchange(m_fd, -1); }
|
s64 Release() { return std::exchange(m_fd, -1); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FSDevice* m_fs{};
|
FSCore* m_fs{};
|
||||||
s64 m_fd = -1;
|
s64 m_fd = -1;
|
||||||
Ticks m_tick_tracker{};
|
Ticks m_tick_tracker{};
|
||||||
};
|
};
|
||||||
|
|
||||||
FSDevice(Kernel& ios, const std::string& device_name);
|
|
||||||
|
|
||||||
// These are the equivalent of the IPC command handlers so IPC overhead is included
|
// These are the equivalent of the IPC command handlers so IPC overhead is included
|
||||||
// in timing calculations.
|
// in timing calculations.
|
||||||
ScopedFd Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode,
|
ScopedFd Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode,
|
||||||
|
@ -78,16 +85,6 @@ public:
|
||||||
|
|
||||||
std::shared_ptr<FS::FileSystem> GetFS() const { return m_ios.GetFS(); }
|
std::shared_ptr<FS::FileSystem> GetFS() const { return m_ios.GetFS(); }
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
|
||||||
|
|
||||||
std::optional<IPCReply> Open(const OpenRequest& request) override;
|
|
||||||
std::optional<IPCReply> Close(u32 fd) override;
|
|
||||||
std::optional<IPCReply> Read(const ReadWriteRequest& request) override;
|
|
||||||
std::optional<IPCReply> Write(const ReadWriteRequest& request) override;
|
|
||||||
std::optional<IPCReply> Seek(const SeekRequest& request) override;
|
|
||||||
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
|
|
||||||
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Handle
|
struct Handle
|
||||||
{
|
{
|
||||||
|
@ -99,6 +96,40 @@ private:
|
||||||
bool superblock_flush_needed = false;
|
bool superblock_flush_needed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
u64 EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, u32 size);
|
||||||
|
u64 SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size);
|
||||||
|
u64 SimulateFlushFileCache();
|
||||||
|
bool HasCacheForFile(u64 fd, u32 offset) const;
|
||||||
|
|
||||||
|
Kernel& m_ios;
|
||||||
|
|
||||||
|
bool m_dirty_cache = false;
|
||||||
|
u16 m_cache_chain_index = 0;
|
||||||
|
std::optional<u64> m_cache_fd;
|
||||||
|
// The first 0x18 IDs are reserved for the PPC.
|
||||||
|
u64 m_next_fd = 0x18;
|
||||||
|
std::map<u64, Handle> m_fd_map;
|
||||||
|
|
||||||
|
friend class FSDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FSDevice final : public EmulationDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FSDevice(EmulationKernel& ios, FSCore& core, const std::string& device_name);
|
||||||
|
~FSDevice();
|
||||||
|
|
||||||
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
|
std::optional<IPCReply> Open(const OpenRequest& request) override;
|
||||||
|
std::optional<IPCReply> Close(u32 fd) override;
|
||||||
|
std::optional<IPCReply> Read(const ReadWriteRequest& request) override;
|
||||||
|
std::optional<IPCReply> Write(const ReadWriteRequest& request) override;
|
||||||
|
std::optional<IPCReply> Seek(const SeekRequest& request) override;
|
||||||
|
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
|
||||||
|
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
|
||||||
|
|
||||||
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ISFS_IOCTL_FORMAT = 1,
|
ISFS_IOCTL_FORMAT = 1,
|
||||||
|
@ -116,6 +147,8 @@ private:
|
||||||
ISFS_IOCTL_SHUTDOWN = 13,
|
ISFS_IOCTL_SHUTDOWN = 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Handle = FSCore::Handle;
|
||||||
|
|
||||||
IPCReply Format(const Handle& handle, const IOCtlRequest& request);
|
IPCReply Format(const Handle& handle, const IOCtlRequest& request);
|
||||||
IPCReply GetStats(const Handle& handle, const IOCtlRequest& request);
|
IPCReply GetStats(const Handle& handle, const IOCtlRequest& request);
|
||||||
IPCReply CreateDirectory(const Handle& handle, const IOCtlRequest& request);
|
IPCReply CreateDirectory(const Handle& handle, const IOCtlRequest& request);
|
||||||
|
@ -130,16 +163,6 @@ private:
|
||||||
IPCReply GetUsage(const Handle& handle, const IOCtlVRequest& request);
|
IPCReply GetUsage(const Handle& handle, const IOCtlVRequest& request);
|
||||||
IPCReply Shutdown(const Handle& handle, const IOCtlRequest& request);
|
IPCReply Shutdown(const Handle& handle, const IOCtlRequest& request);
|
||||||
|
|
||||||
u64 EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, u32 size);
|
FSCore& m_core;
|
||||||
u64 SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size);
|
|
||||||
u64 SimulateFlushFileCache();
|
|
||||||
bool HasCacheForFile(u64 fd, u32 offset) const;
|
|
||||||
|
|
||||||
bool m_dirty_cache = false;
|
|
||||||
u16 m_cache_chain_index = 0;
|
|
||||||
std::optional<u64> m_cache_fd;
|
|
||||||
// The first 0x18 IDs are reserved for the PPC.
|
|
||||||
u64 m_next_fd = 0x18;
|
|
||||||
std::map<u64, Handle> m_fd_map;
|
|
||||||
};
|
};
|
||||||
} // namespace IOS::HLE
|
} // namespace IOS::HLE
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -300,17 +299,15 @@ Kernel::Kernel(IOSC::ConsoleType console_type) : m_iosc(console_type)
|
||||||
if (m_is_responsible_for_nand_root)
|
if (m_is_responsible_for_nand_root)
|
||||||
Core::InitializeWiiRoot(false);
|
Core::InitializeWiiRoot(false);
|
||||||
|
|
||||||
AddCoreDevices();
|
m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects());
|
||||||
|
ASSERT(m_fs);
|
||||||
|
|
||||||
|
m_fs_core = std::make_unique<FSCore>(*this);
|
||||||
|
m_es_core = std::make_unique<ESCore>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::~Kernel()
|
Kernel::~Kernel()
|
||||||
{
|
{
|
||||||
{
|
|
||||||
std::lock_guard lock(m_device_map_mutex);
|
|
||||||
m_device_map.clear();
|
|
||||||
m_socket_manager.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_is_responsible_for_nand_root)
|
if (m_is_responsible_for_nand_root)
|
||||||
Core::ShutdownWiiRoot();
|
Core::ShutdownWiiRoot();
|
||||||
}
|
}
|
||||||
|
@ -333,13 +330,23 @@ EmulationKernel::EmulationKernel(Core::System& system, u64 title_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddCoreDevices();
|
m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects());
|
||||||
|
ASSERT(m_fs);
|
||||||
|
|
||||||
|
m_fs_core = std::make_unique<FSCore>(*this);
|
||||||
|
AddDevice(std::make_unique<FSDevice>(*this, *m_fs_core, "/dev/fs"));
|
||||||
|
m_es_core = std::make_unique<ESCore>(*this);
|
||||||
|
AddDevice(std::make_unique<ESDevice>(*this, *m_es_core, "/dev/es"));
|
||||||
|
|
||||||
AddStaticDevices();
|
AddStaticDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
EmulationKernel::~EmulationKernel()
|
EmulationKernel::~EmulationKernel()
|
||||||
{
|
{
|
||||||
Core::System::GetInstance().GetCoreTiming().RemoveAllEvents(s_event_enqueue);
|
Core::System::GetInstance().GetCoreTiming().RemoveAllEvents(s_event_enqueue);
|
||||||
|
|
||||||
|
m_device_map.clear();
|
||||||
|
m_socket_manager.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The title ID is a u64 where the first 32 bits are used for the title type.
|
// The title ID is a u64 where the first 32 bits are used for the title type.
|
||||||
|
@ -355,12 +362,22 @@ std::shared_ptr<FS::FileSystem> Kernel::GetFS()
|
||||||
return m_fs;
|
return m_fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<FSDevice> Kernel::GetFSDevice()
|
FSCore& Kernel::GetFSCore()
|
||||||
|
{
|
||||||
|
return *m_fs_core;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<FSDevice> EmulationKernel::GetFSDevice()
|
||||||
{
|
{
|
||||||
return std::static_pointer_cast<FSDevice>(m_device_map.at("/dev/fs"));
|
return std::static_pointer_cast<FSDevice>(m_device_map.at("/dev/fs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ESDevice> Kernel::GetES()
|
ESCore& Kernel::GetESCore()
|
||||||
|
{
|
||||||
|
return *m_es_core;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ESDevice> EmulationKernel::GetESDevice()
|
||||||
{
|
{
|
||||||
return std::static_pointer_cast<ESDevice>(m_device_map.at("/dev/es"));
|
return std::static_pointer_cast<ESDevice>(m_device_map.at("/dev/es"));
|
||||||
}
|
}
|
||||||
|
@ -372,51 +389,51 @@ std::shared_ptr<WiiSockMan> EmulationKernel::GetSocketManager()
|
||||||
|
|
||||||
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
|
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
|
||||||
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
|
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
|
||||||
void Kernel::SetUidForPPC(u32 uid)
|
void EmulationKernel::SetUidForPPC(u32 uid)
|
||||||
{
|
{
|
||||||
m_ppc_uid = uid;
|
m_ppc_uid = uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Kernel::GetUidForPPC() const
|
u32 EmulationKernel::GetUidForPPC() const
|
||||||
{
|
{
|
||||||
return m_ppc_uid;
|
return m_ppc_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::SetGidForPPC(u16 gid)
|
void EmulationKernel::SetGidForPPC(u16 gid)
|
||||||
{
|
{
|
||||||
m_ppc_gid = gid;
|
m_ppc_gid = gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 Kernel::GetGidForPPC() const
|
u16 EmulationKernel::GetGidForPPC() const
|
||||||
{
|
{
|
||||||
return m_ppc_gid;
|
return m_ppc_gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<u8> ReadBootContent(FSDevice* fs, const std::string& path, size_t max_size,
|
static std::vector<u8> ReadBootContent(FSCore& fs, const std::string& path, size_t max_size,
|
||||||
Ticks ticks = {})
|
Ticks ticks = {})
|
||||||
{
|
{
|
||||||
const auto fd = fs->Open(0, 0, path, FS::Mode::Read, {}, ticks);
|
const auto fd = fs.Open(0, 0, path, FS::Mode::Read, {}, ticks);
|
||||||
if (fd.Get() < 0)
|
if (fd.Get() < 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const size_t file_size = fs->GetFileStatus(fd.Get(), ticks)->size;
|
const size_t file_size = fs.GetFileStatus(fd.Get(), ticks)->size;
|
||||||
if (max_size != 0 && file_size > max_size)
|
if (max_size != 0 && file_size > max_size)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::vector<u8> buffer(file_size);
|
std::vector<u8> buffer(file_size);
|
||||||
if (!fs->Read(fd.Get(), buffer.data(), buffer.size(), ticks))
|
if (!fs.Read(fd.Get(), buffer.data(), buffer.size(), ticks))
|
||||||
return {};
|
return {};
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This corresponds to syscall 0x41, which loads a binary from the NAND and bootstraps the PPC.
|
// This corresponds to syscall 0x41, which loads a binary from the NAND and bootstraps the PPC.
|
||||||
// Unlike 0x42, IOS will set up some constants in memory before booting the PPC.
|
// Unlike 0x42, IOS will set up some constants in memory before booting the PPC.
|
||||||
bool Kernel::BootstrapPPC(Core::System& system, const std::string& boot_content_path)
|
bool EmulationKernel::BootstrapPPC(Core::System& system, const std::string& boot_content_path)
|
||||||
{
|
{
|
||||||
// Seeking and processing overhead is ignored as most time is spent reading from the NAND.
|
// Seeking and processing overhead is ignored as most time is spent reading from the NAND.
|
||||||
u64 ticks = 0;
|
u64 ticks = 0;
|
||||||
|
|
||||||
const DolReader dol{ReadBootContent(GetFSDevice().get(), boot_content_path, 0, &ticks)};
|
const DolReader dol{ReadBootContent(GetFSCore(), boot_content_path, 0, &ticks)};
|
||||||
|
|
||||||
if (!dol.IsValid())
|
if (!dol.IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
@ -485,7 +502,7 @@ static constexpr SystemTimers::TimeBaseTick GetIOSBootTicks(u32 version)
|
||||||
// Passing a boot content path is optional because we do not require IOSes
|
// Passing a boot content path is optional because we do not require IOSes
|
||||||
// to be installed at the moment. If one is passed, the boot binary must exist
|
// to be installed at the moment. If one is passed, the boot binary must exist
|
||||||
// on the NAND, or the call will fail like on a Wii.
|
// on the NAND, or the call will fail like on a Wii.
|
||||||
bool Kernel::BootIOS(Core::System& system, const u64 ios_title_id, HangPPC hang_ppc,
|
bool EmulationKernel::BootIOS(Core::System& system, const u64 ios_title_id, HangPPC hang_ppc,
|
||||||
const std::string& boot_content_path)
|
const std::string& boot_content_path)
|
||||||
{
|
{
|
||||||
// IOS suspends regular PPC<->ARM IPC before loading a new IOS.
|
// IOS suspends regular PPC<->ARM IPC before loading a new IOS.
|
||||||
|
@ -497,7 +514,7 @@ bool Kernel::BootIOS(Core::System& system, const u64 ios_title_id, HangPPC hang_
|
||||||
// Load the ARM binary to memory (if possible).
|
// Load the ARM binary to memory (if possible).
|
||||||
// Because we do not actually emulate the Starlet, only load the sections that are in MEM1.
|
// Because we do not actually emulate the Starlet, only load the sections that are in MEM1.
|
||||||
|
|
||||||
ARMBinary binary{ReadBootContent(GetFSDevice().get(), boot_content_path, 0xB00000)};
|
ARMBinary binary{ReadBootContent(GetFSCore(), boot_content_path, 0xB00000)};
|
||||||
if (!binary.IsValid())
|
if (!binary.IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -522,7 +539,7 @@ bool Kernel::BootIOS(Core::System& system, const u64 ios_title_id, HangPPC hang_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::InitIPC()
|
void EmulationKernel::InitIPC()
|
||||||
{
|
{
|
||||||
if (!Core::IsRunning())
|
if (!Core::IsRunning())
|
||||||
return;
|
return;
|
||||||
|
@ -531,26 +548,14 @@ void Kernel::InitIPC()
|
||||||
GenerateAck(0);
|
GenerateAck(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::AddDevice(std::unique_ptr<Device> device)
|
void EmulationKernel::AddDevice(std::unique_ptr<Device> device)
|
||||||
{
|
{
|
||||||
ASSERT(device->GetDeviceType() == Device::DeviceType::Static);
|
ASSERT(device->GetDeviceType() == Device::DeviceType::Static);
|
||||||
m_device_map.insert_or_assign(device->GetDeviceName(), std::move(device));
|
m_device_map.insert_or_assign(device->GetDeviceName(), std::move(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::AddCoreDevices()
|
|
||||||
{
|
|
||||||
m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects());
|
|
||||||
ASSERT(m_fs);
|
|
||||||
|
|
||||||
std::lock_guard lock(m_device_map_mutex);
|
|
||||||
AddDevice(std::make_unique<FSDevice>(*this, "/dev/fs"));
|
|
||||||
AddDevice(std::make_unique<ESDevice>(*this, "/dev/es"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulationKernel::AddStaticDevices()
|
void EmulationKernel::AddStaticDevices()
|
||||||
{
|
{
|
||||||
std::lock_guard lock(m_device_map_mutex);
|
|
||||||
|
|
||||||
const Feature features = GetFeatures(GetVersion());
|
const Feature features = GetFeatures(GetVersion());
|
||||||
|
|
||||||
// Dolphin-specific device for letting homebrew access and alter emulator state.
|
// Dolphin-specific device for letting homebrew access and alter emulator state.
|
||||||
|
@ -637,16 +642,10 @@ s32 EmulationKernel::GetFreeDeviceID()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Device> Kernel::GetDeviceByName(std::string_view device_name)
|
|
||||||
{
|
|
||||||
std::lock_guard lock(m_device_map_mutex);
|
|
||||||
const auto iterator = m_device_map.find(device_name);
|
|
||||||
return iterator != m_device_map.end() ? iterator->second : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Device> EmulationKernel::GetDeviceByName(std::string_view device_name)
|
std::shared_ptr<Device> EmulationKernel::GetDeviceByName(std::string_view device_name)
|
||||||
{
|
{
|
||||||
return Kernel::GetDeviceByName(device_name);
|
const auto iterator = m_device_map.find(device_name);
|
||||||
|
return iterator != m_device_map.end() ? iterator->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the FD for the newly opened device (on success) or an error code.
|
// Returns the FD for the newly opened device (on success) or an error code.
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
@ -33,7 +32,9 @@ class FileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
|
class ESCore;
|
||||||
class ESDevice;
|
class ESDevice;
|
||||||
|
class FSCore;
|
||||||
class FSDevice;
|
class FSDevice;
|
||||||
class WiiSockMan;
|
class WiiSockMan;
|
||||||
|
|
||||||
|
@ -122,18 +123,9 @@ public:
|
||||||
// These are *always* part of the IOS kernel and always available.
|
// These are *always* part of the IOS kernel and always available.
|
||||||
// They are also the only available resource managers even before loading any module.
|
// They are also the only available resource managers even before loading any module.
|
||||||
std::shared_ptr<FS::FileSystem> GetFS();
|
std::shared_ptr<FS::FileSystem> GetFS();
|
||||||
std::shared_ptr<FSDevice> GetFSDevice();
|
FSCore& GetFSCore();
|
||||||
std::shared_ptr<ESDevice> GetES();
|
ESCore& GetESCore();
|
||||||
|
|
||||||
void SetUidForPPC(u32 uid);
|
|
||||||
u32 GetUidForPPC() const;
|
|
||||||
void SetGidForPPC(u16 gid);
|
|
||||||
u16 GetGidForPPC() const;
|
|
||||||
|
|
||||||
bool BootstrapPPC(Core::System& system, const std::string& boot_content_path);
|
|
||||||
bool BootIOS(Core::System& system, u64 ios_title_id, HangPPC hang_ppc = HangPPC::No,
|
|
||||||
const std::string& boot_content_path = {});
|
|
||||||
void InitIPC();
|
|
||||||
u32 GetVersion() const;
|
u32 GetVersion() const;
|
||||||
|
|
||||||
IOSC& GetIOSC();
|
IOSC& GetIOSC();
|
||||||
|
@ -141,26 +133,11 @@ public:
|
||||||
protected:
|
protected:
|
||||||
explicit Kernel(u64 title_id);
|
explicit Kernel(u64 title_id);
|
||||||
|
|
||||||
void AddDevice(std::unique_ptr<Device> device);
|
std::unique_ptr<FSCore> m_fs_core;
|
||||||
void AddCoreDevices();
|
std::unique_ptr<ESCore> m_es_core;
|
||||||
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
|
|
||||||
|
|
||||||
bool m_is_responsible_for_nand_root = false;
|
bool m_is_responsible_for_nand_root = false;
|
||||||
u64 m_title_id = 0;
|
u64 m_title_id = 0;
|
||||||
static constexpr u8 IPC_MAX_FDS = 0x18;
|
|
||||||
std::map<std::string, std::shared_ptr<Device>, std::less<>> m_device_map;
|
|
||||||
std::mutex m_device_map_mutex;
|
|
||||||
// TODO: make this fdmap per process.
|
|
||||||
std::array<std::shared_ptr<Device>, IPC_MAX_FDS> m_fdmap;
|
|
||||||
|
|
||||||
u32 m_ppc_uid = 0;
|
|
||||||
u16 m_ppc_gid = 0;
|
|
||||||
|
|
||||||
using IPCMsgQueue = std::deque<u32>;
|
|
||||||
IPCMsgQueue m_request_queue; // ppc -> arm
|
|
||||||
IPCMsgQueue m_reply_queue; // arm -> ppc
|
|
||||||
u64 m_last_reply_time = 0;
|
|
||||||
bool m_ipc_paused = false;
|
|
||||||
|
|
||||||
IOSC m_iosc;
|
IOSC m_iosc;
|
||||||
std::shared_ptr<FS::FileSystem> m_fs;
|
std::shared_ptr<FS::FileSystem> m_fs;
|
||||||
|
@ -178,6 +155,9 @@ public:
|
||||||
// This only works for devices which are part of the device map.
|
// This only works for devices which are part of the device map.
|
||||||
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
|
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
|
||||||
|
|
||||||
|
std::shared_ptr<FSDevice> GetFSDevice();
|
||||||
|
std::shared_ptr<ESDevice> GetESDevice();
|
||||||
|
|
||||||
void DoState(PointerWrap& p);
|
void DoState(PointerWrap& p);
|
||||||
void UpdateDevices();
|
void UpdateDevices();
|
||||||
void UpdateWantDeterminism(bool new_want_determinism);
|
void UpdateWantDeterminism(bool new_want_determinism);
|
||||||
|
@ -191,17 +171,43 @@ public:
|
||||||
void EnqueueIPCReply(const Request& request, s32 return_value, s64 cycles_in_future = 0,
|
void EnqueueIPCReply(const Request& request, s32 return_value, s64 cycles_in_future = 0,
|
||||||
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
||||||
|
|
||||||
|
void SetUidForPPC(u32 uid);
|
||||||
|
u32 GetUidForPPC() const;
|
||||||
|
void SetGidForPPC(u16 gid);
|
||||||
|
u16 GetGidForPPC() const;
|
||||||
|
|
||||||
|
bool BootstrapPPC(Core::System& system, const std::string& boot_content_path);
|
||||||
|
bool BootIOS(Core::System& system, u64 ios_title_id, HangPPC hang_ppc = HangPPC::No,
|
||||||
|
const std::string& boot_content_path = {});
|
||||||
|
void InitIPC();
|
||||||
|
|
||||||
Core::System& GetSystem() const { return m_system; }
|
Core::System& GetSystem() const { return m_system; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& m_system;
|
|
||||||
|
|
||||||
void ExecuteIPCCommand(u32 address);
|
void ExecuteIPCCommand(u32 address);
|
||||||
std::optional<IPCReply> HandleIPCCommand(const Request& request);
|
std::optional<IPCReply> HandleIPCCommand(const Request& request);
|
||||||
|
|
||||||
|
void AddDevice(std::unique_ptr<Device> device);
|
||||||
|
|
||||||
void AddStaticDevices();
|
void AddStaticDevices();
|
||||||
s32 GetFreeDeviceID();
|
s32 GetFreeDeviceID();
|
||||||
std::optional<IPCReply> OpenDevice(OpenRequest& request);
|
std::optional<IPCReply> OpenDevice(OpenRequest& request);
|
||||||
|
|
||||||
|
Core::System& m_system;
|
||||||
|
|
||||||
|
static constexpr u8 IPC_MAX_FDS = 0x18;
|
||||||
|
std::map<std::string, std::shared_ptr<Device>, std::less<>> m_device_map;
|
||||||
|
// TODO: make this fdmap per process.
|
||||||
|
std::array<std::shared_ptr<Device>, IPC_MAX_FDS> m_fdmap;
|
||||||
|
|
||||||
|
u32 m_ppc_uid = 0;
|
||||||
|
u16 m_ppc_gid = 0;
|
||||||
|
|
||||||
|
using IPCMsgQueue = std::deque<u32>;
|
||||||
|
IPCMsgQueue m_request_queue; // ppc -> arm
|
||||||
|
IPCMsgQueue m_reply_queue; // arm -> ppc
|
||||||
|
u64 m_last_reply_time = 0;
|
||||||
|
bool m_ipc_paused = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used for controlling and accessing an IOS instance that is tied to emulation.
|
// Used for controlling and accessing an IOS instance that is tied to emulation.
|
||||||
|
|
|
@ -165,7 +165,8 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
|
||||||
memory.CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
|
memory.CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
|
||||||
m_tmd.SetBytes(std::move(tmd_bytes));
|
m_tmd.SetBytes(std::move(tmd_bytes));
|
||||||
|
|
||||||
const ES::TicketReader ticket = m_ios.GetES()->FindSignedTicket(m_tmd.GetTitleId());
|
const ES::TicketReader ticket =
|
||||||
|
GetEmulationKernel().GetESCore().FindSignedTicket(m_tmd.GetTitleId());
|
||||||
if (!ticket.IsValid())
|
if (!ticket.IsValid())
|
||||||
{
|
{
|
||||||
return_error_code = -11028;
|
return_error_code = -11028;
|
||||||
|
@ -385,14 +386,14 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_INIT");
|
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_INIT");
|
||||||
u64 tid;
|
u64 tid;
|
||||||
if (GetEmulationKernel().GetES()->GetTitleId(&tid) < 0)
|
if (GetEmulationKernel().GetESCore().GetTitleId(&tid) < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(IOS_WFS, "IOCTL_WFSI_INIT: Could not get title id.");
|
ERROR_LOG_FMT(IOS_WFS, "IOCTL_WFSI_INIT: Could not get title id.");
|
||||||
return_error_code = IPC_EINVAL;
|
return_error_code = IPC_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ES::TMDReader tmd = GetEmulationKernel().GetES()->FindInstalledTMD(tid);
|
const ES::TMDReader tmd = GetEmulationKernel().GetESCore().FindInstalledTMD(tid);
|
||||||
SetCurrentTitleIdAndGroupId(tmd.GetTitleId(), tmd.GetGroupId());
|
SetCurrentTitleIdAndGroupId(tmd.GetTitleId(), tmd.GetGroupId());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1720,7 +1720,7 @@ std::optional<SaveSyncInfo> NetPlayServer::CollectSaveSyncInfo()
|
||||||
if (m_settings.savedata_sync_all_wii)
|
if (m_settings.savedata_sync_all_wii)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
for (const u64 title : ios.GetES()->GetInstalledTitles())
|
for (const u64 title : ios.GetESCore().GetInstalledTitles())
|
||||||
{
|
{
|
||||||
auto save = WiiSave::MakeNandStorage(sync_info.configured_fs.get(), title);
|
auto save = WiiSave::MakeNandStorage(sync_info.configured_fs.get(), title);
|
||||||
if (save && save->ReadHeader().has_value() && save->ReadBkHeader().has_value() &&
|
if (save && save->ReadHeader().has_value() && save->ReadBkHeader().has_value() &&
|
||||||
|
|
|
@ -416,7 +416,7 @@ void CleanUpWiiFileSystemContents(const BootSessionData& boot_session_data)
|
||||||
// cleanup process.
|
// cleanup process.
|
||||||
const bool copy_all = !netplay_settings || netplay_settings->savedata_sync_all_wii;
|
const bool copy_all = !netplay_settings || netplay_settings->savedata_sync_all_wii;
|
||||||
for (const u64 title_id :
|
for (const u64 title_id :
|
||||||
(copy_all ? ios->GetES()->GetInstalledTitles() : boot_session_data.GetWiiSyncTitles()))
|
(copy_all ? ios->GetESCore().GetInstalledTitles() : boot_session_data.GetWiiSyncTitles()))
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(CORE, "Wii FS Cleanup: Copying {0:016x}.", title_id);
|
INFO_LOG_FMT(CORE, "Wii FS Cleanup: Copying {0:016x}.", title_id);
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
namespace WiiUtils
|
namespace WiiUtils
|
||||||
{
|
{
|
||||||
static bool ImportWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad,
|
static bool ImportWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad,
|
||||||
IOS::HLE::ESDevice::VerifySignature verify_signature)
|
IOS::HLE::ESCore::VerifySignature verify_signature)
|
||||||
{
|
{
|
||||||
if (!wad.GetTicket().IsValid() || !wad.GetTMD().IsValid())
|
if (!wad.GetTicket().IsValid() || !wad.GetTMD().IsValid())
|
||||||
{
|
{
|
||||||
|
@ -58,19 +58,19 @@ static bool ImportWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad,
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto tmd = wad.GetTMD();
|
const auto tmd = wad.GetTMD();
|
||||||
const auto es = ios.GetES();
|
auto& es = ios.GetESCore();
|
||||||
const auto fs = ios.GetFS();
|
const auto fs = ios.GetFS();
|
||||||
|
|
||||||
IOS::HLE::ESDevice::Context context;
|
IOS::HLE::ESCore::Context context;
|
||||||
IOS::HLE::ReturnCode ret;
|
IOS::HLE::ReturnCode ret;
|
||||||
|
|
||||||
// Ensure the common key index is correct, as it's checked by IOS.
|
// Ensure the common key index is correct, as it's checked by IOS.
|
||||||
IOS::ES::TicketReader ticket = wad.GetTicketWithFixedCommonKey();
|
IOS::ES::TicketReader ticket = wad.GetTicketWithFixedCommonKey();
|
||||||
|
|
||||||
while ((ret = es->ImportTicket(ticket.GetBytes(), wad.GetCertificateChain(),
|
while ((ret = es.ImportTicket(ticket.GetBytes(), wad.GetCertificateChain(),
|
||||||
IOS::HLE::ESDevice::TicketImportType::Unpersonalised,
|
IOS::HLE::ESCore::TicketImportType::Unpersonalised,
|
||||||
verify_signature)) < 0 ||
|
verify_signature)) < 0 ||
|
||||||
(ret = es->ImportTitleInit(context, tmd.GetBytes(), wad.GetCertificateChain(),
|
(ret = es.ImportTitleInit(context, tmd.GetBytes(), wad.GetCertificateChain(),
|
||||||
verify_signature)) < 0)
|
verify_signature)) < 0)
|
||||||
{
|
{
|
||||||
if (ret != IOS::HLE::IOSC_FAIL_CHECKVALUE)
|
if (ret != IOS::HLE::IOSC_FAIL_CHECKVALUE)
|
||||||
|
@ -87,9 +87,9 @@ static bool ImportWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad,
|
||||||
{
|
{
|
||||||
const std::vector<u8> data = wad.GetContent(content.index);
|
const std::vector<u8> data = wad.GetContent(content.index);
|
||||||
|
|
||||||
if (es->ImportContentBegin(context, title_id, content.id) < 0 ||
|
if (es.ImportContentBegin(context, title_id, content.id) < 0 ||
|
||||||
es->ImportContentData(context, 0, data.data(), static_cast<u32>(data.size())) < 0 ||
|
es.ImportContentData(context, 0, data.data(), static_cast<u32>(data.size())) < 0 ||
|
||||||
es->ImportContentEnd(context, 0) < 0)
|
es.ImportContentEnd(context, 0) < 0)
|
||||||
{
|
{
|
||||||
PanicAlertFmtT("WAD installation failed: Could not import content {0:08x}.", content.id);
|
PanicAlertFmtT("WAD installation failed: Could not import content {0:08x}.", content.id);
|
||||||
return false;
|
return false;
|
||||||
|
@ -98,8 +98,8 @@ static bool ImportWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad,
|
||||||
return true;
|
return true;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if ((contents_imported && es->ImportTitleDone(context) < 0) ||
|
if ((contents_imported && es.ImportTitleDone(context) < 0) ||
|
||||||
(!contents_imported && es->ImportTitleCancel(context) < 0))
|
(!contents_imported && es.ImportTitleCancel(context) < 0))
|
||||||
{
|
{
|
||||||
PanicAlertFmtT("WAD installation failed: Could not finalise title import.");
|
PanicAlertFmtT("WAD installation failed: Could not finalise title import.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -151,8 +151,8 @@ bool InstallWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad, InstallType
|
||||||
const u64 title_id = wad.GetTMD().GetTitleId();
|
const u64 title_id = wad.GetTMD().GetTitleId();
|
||||||
|
|
||||||
// Skip the install if the WAD is already installed.
|
// Skip the install if the WAD is already installed.
|
||||||
const auto installed_contents = ios.GetES()->GetStoredContentsFromTMD(
|
const auto installed_contents = ios.GetESCore().GetStoredContentsFromTMD(
|
||||||
wad.GetTMD(), IOS::HLE::ESDevice::CheckContentHashes::Yes);
|
wad.GetTMD(), IOS::HLE::ESCore::CheckContentHashes::Yes);
|
||||||
if (wad.GetTMD().GetContents() == installed_contents)
|
if (wad.GetTMD().GetContents() == installed_contents)
|
||||||
{
|
{
|
||||||
// Clear the "temporary title ID" flag in case the user tries to permanently install a title
|
// Clear the "temporary title ID" flag in case the user tries to permanently install a title
|
||||||
|
@ -164,7 +164,7 @@ bool InstallWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad, InstallType
|
||||||
|
|
||||||
// If a different version is currently installed, warn the user to make sure
|
// If a different version is currently installed, warn the user to make sure
|
||||||
// they don't overwrite the current version by mistake.
|
// they don't overwrite the current version by mistake.
|
||||||
const IOS::ES::TMDReader installed_tmd = ios.GetES()->FindInstalledTMD(title_id);
|
const IOS::ES::TMDReader installed_tmd = ios.GetESCore().FindInstalledTMD(title_id);
|
||||||
const bool has_another_version =
|
const bool has_another_version =
|
||||||
installed_tmd.IsValid() && installed_tmd.GetTitleVersion() != wad.GetTMD().GetTitleVersion();
|
installed_tmd.IsValid() && installed_tmd.GetTitleVersion() != wad.GetTMD().GetTitleVersion();
|
||||||
if (has_another_version &&
|
if (has_another_version &&
|
||||||
|
@ -178,10 +178,10 @@ bool InstallWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad, InstallType
|
||||||
|
|
||||||
// Delete a previous temporary title, if it exists.
|
// Delete a previous temporary title, if it exists.
|
||||||
if (previous_temporary_title_id)
|
if (previous_temporary_title_id)
|
||||||
ios.GetES()->DeleteTitleContent(previous_temporary_title_id);
|
ios.GetESCore().DeleteTitleContent(previous_temporary_title_id);
|
||||||
|
|
||||||
// A lot of people use fakesigned WADs, so disable signature checking when installing a WAD.
|
// A lot of people use fakesigned WADs, so disable signature checking when installing a WAD.
|
||||||
if (!ImportWAD(ios, wad, IOS::HLE::ESDevice::VerifySignature::No))
|
if (!ImportWAD(ios, wad, IOS::HLE::ESCore::VerifySignature::No))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Keep track of the title ID so this title can be removed to make room for any future install.
|
// Keep track of the title ID so this title can be removed to make room for any future install.
|
||||||
|
@ -207,7 +207,7 @@ bool InstallWAD(const std::string& wad_path)
|
||||||
bool UninstallTitle(u64 title_id)
|
bool UninstallTitle(u64 title_id)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
return ios.GetES()->DeleteTitleContent(title_id) == IOS::HLE::IPC_SUCCESS;
|
return ios.GetESCore().DeleteTitleContent(title_id) == IOS::HLE::IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsTitleInstalled(u64 title_id)
|
bool IsTitleInstalled(u64 title_id)
|
||||||
|
@ -266,7 +266,7 @@ IOS::ES::TMDReader FindBackupTMD(IOS::HLE::FS::FileSystem& fs, u64 title_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EnsureTMDIsImported(IOS::HLE::FS::FileSystem& fs, IOS::HLE::ESDevice& es, u64 title_id)
|
bool EnsureTMDIsImported(IOS::HLE::FS::FileSystem& fs, IOS::HLE::ESCore& es, u64 title_id)
|
||||||
{
|
{
|
||||||
if (IsTMDImported(fs, title_id))
|
if (IsTMDImported(fs, title_id))
|
||||||
return true;
|
return true;
|
||||||
|
@ -275,7 +275,7 @@ bool EnsureTMDIsImported(IOS::HLE::FS::FileSystem& fs, IOS::HLE::ESDevice& es, u
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IOS::HLE::ESDevice::Context context;
|
IOS::HLE::ESCore::Context context;
|
||||||
context.uid = IOS::SYSMENU_UID;
|
context.uid = IOS::SYSMENU_UID;
|
||||||
context.gid = IOS::SYSMENU_GID;
|
context.gid = IOS::SYSMENU_GID;
|
||||||
const auto import_result =
|
const auto import_result =
|
||||||
|
@ -308,7 +308,7 @@ protected:
|
||||||
std::string SystemUpdater::GetDeviceRegion()
|
std::string SystemUpdater::GetDeviceRegion()
|
||||||
{
|
{
|
||||||
// Try to determine the region from an installed system menu.
|
// Try to determine the region from an installed system menu.
|
||||||
const auto tmd = m_ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
|
const auto tmd = m_ios.GetESCore().FindInstalledTMD(Titles::SYSTEM_MENU);
|
||||||
if (tmd.IsValid())
|
if (tmd.IsValid())
|
||||||
{
|
{
|
||||||
const DiscIO::Region region = tmd.GetRegion();
|
const DiscIO::Region region = tmd.GetRegion();
|
||||||
|
@ -325,7 +325,7 @@ std::string SystemUpdater::GetDeviceRegion()
|
||||||
std::string SystemUpdater::GetDeviceId()
|
std::string SystemUpdater::GetDeviceId()
|
||||||
{
|
{
|
||||||
u32 ios_device_id;
|
u32 ios_device_id;
|
||||||
if (m_ios.GetES()->GetDeviceId(&ios_device_id) < 0)
|
if (m_ios.GetESCore().GetDeviceId(&ios_device_id) < 0)
|
||||||
return "";
|
return "";
|
||||||
return std::to_string((u64(1) << 32) | ios_device_id);
|
return std::to_string((u64(1) << 32) | ios_device_id);
|
||||||
}
|
}
|
||||||
|
@ -417,10 +417,10 @@ OnlineSystemUpdater::ParseTitlesResponse(const std::vector<u8>& response) const
|
||||||
|
|
||||||
bool OnlineSystemUpdater::ShouldInstallTitle(const TitleInfo& title)
|
bool OnlineSystemUpdater::ShouldInstallTitle(const TitleInfo& title)
|
||||||
{
|
{
|
||||||
const auto es = m_ios.GetES();
|
const auto& es = m_ios.GetESCore();
|
||||||
const auto installed_tmd = es->FindInstalledTMD(title.id);
|
const auto installed_tmd = es.FindInstalledTMD(title.id);
|
||||||
return !(installed_tmd.IsValid() && installed_tmd.GetTitleVersion() >= title.version &&
|
return !(installed_tmd.IsValid() && installed_tmd.GetTitleVersion() >= title.version &&
|
||||||
es->GetStoredContentsFromTMD(installed_tmd).size() == installed_tmd.GetNumContents());
|
es.GetStoredContentsFromTMD(installed_tmd).size() == installed_tmd.GetNumContents());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const char* GET_SYSTEM_TITLES_REQUEST_PAYLOAD = R"(<?xml version="1.0" encoding="UTF-8"?>
|
constexpr const char* GET_SYSTEM_TITLES_REQUEST_PAYLOAD = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
@ -545,8 +545,8 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||||
|
|
||||||
// Import the ticket.
|
// Import the ticket.
|
||||||
IOS::HLE::ReturnCode ret = IOS::HLE::IPC_SUCCESS;
|
IOS::HLE::ReturnCode ret = IOS::HLE::IPC_SUCCESS;
|
||||||
const auto es = m_ios.GetES();
|
auto& es = m_ios.GetESCore();
|
||||||
if ((ret = es->ImportTicket(ticket.first, ticket.second)) < 0)
|
if ((ret = es.ImportTicket(ticket.first, ticket.second)) < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CORE, "Failed to import ticket: error {}", static_cast<u32>(ret));
|
ERROR_LOG_FMT(CORE, "Failed to import ticket: error {}", static_cast<u32>(ret));
|
||||||
return UpdateResult::ImportFailed;
|
return UpdateResult::ImportFailed;
|
||||||
|
@ -564,7 +564,7 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||||
const u64 ios_id = tmd.first.GetIOSId();
|
const u64 ios_id = tmd.first.GetIOSId();
|
||||||
if (ios_id != 0 && IOS::ES::IsTitleType(ios_id, IOS::ES::TitleType::System))
|
if (ios_id != 0 && IOS::ES::IsTitleType(ios_id, IOS::ES::TitleType::System))
|
||||||
{
|
{
|
||||||
if (!es->FindInstalledTMD(ios_id).IsValid())
|
if (!es.FindInstalledTMD(ios_id).IsValid())
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(CORE, "Importing required system title {:016x} first", ios_id);
|
WARN_LOG_FMT(CORE, "Importing required system title {:016x} first", ios_id);
|
||||||
const UpdateResult res = InstallTitleFromNUS(prefix_url, {ios_id, 0}, updated_titles);
|
const UpdateResult res = InstallTitleFromNUS(prefix_url, {ios_id, 0}, updated_titles);
|
||||||
|
@ -577,15 +577,15 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the title import.
|
// Initialise the title import.
|
||||||
IOS::HLE::ESDevice::Context context;
|
IOS::HLE::ESCore::Context context;
|
||||||
if ((ret = es->ImportTitleInit(context, tmd.first.GetBytes(), tmd.second)) < 0)
|
if ((ret = es.ImportTitleInit(context, tmd.first.GetBytes(), tmd.second)) < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CORE, "Failed to initialise title import: error {}", static_cast<u32>(ret));
|
ERROR_LOG_FMT(CORE, "Failed to initialise title import: error {}", static_cast<u32>(ret));
|
||||||
return UpdateResult::ImportFailed;
|
return UpdateResult::ImportFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now download and install contents listed in the TMD.
|
// Now download and install contents listed in the TMD.
|
||||||
const std::vector<IOS::ES::Content> stored_contents = es->GetStoredContentsFromTMD(tmd.first);
|
const std::vector<IOS::ES::Content> stored_contents = es.GetStoredContentsFromTMD(tmd.first);
|
||||||
const UpdateResult import_result = [&]() {
|
const UpdateResult import_result = [&]() {
|
||||||
for (const IOS::ES::Content& content : tmd.first.GetContents())
|
for (const IOS::ES::Content& content : tmd.first.GetContents())
|
||||||
{
|
{
|
||||||
|
@ -598,7 +598,7 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||||
if (is_already_installed)
|
if (is_already_installed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((ret = es->ImportContentBegin(context, title.id, content.id)) < 0)
|
if ((ret = es.ImportContentBegin(context, title.id, content.id)) < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CORE, "Failed to initialise import for content {:08x}: error {}", content.id,
|
ERROR_LOG_FMT(CORE, "Failed to initialise import for content {:08x}: error {}", content.id,
|
||||||
static_cast<u32>(ret));
|
static_cast<u32>(ret));
|
||||||
|
@ -612,8 +612,8 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||||
return UpdateResult::DownloadFailed;
|
return UpdateResult::DownloadFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (es->ImportContentData(context, 0, data->data(), static_cast<u32>(data->size())) < 0 ||
|
if (es.ImportContentData(context, 0, data->data(), static_cast<u32>(data->size())) < 0 ||
|
||||||
es->ImportContentEnd(context, 0) < 0)
|
es.ImportContentEnd(context, 0) < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CORE, "Failed to import content {:08x}", content.id);
|
ERROR_LOG_FMT(CORE, "Failed to import content {:08x}", content.id);
|
||||||
return UpdateResult::ImportFailed;
|
return UpdateResult::ImportFailed;
|
||||||
|
@ -623,8 +623,8 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||||
}();
|
}();
|
||||||
const bool all_contents_imported = import_result == UpdateResult::Succeeded;
|
const bool all_contents_imported = import_result == UpdateResult::Succeeded;
|
||||||
|
|
||||||
if ((all_contents_imported && (ret = es->ImportTitleDone(context)) < 0) ||
|
if ((all_contents_imported && (ret = es.ImportTitleDone(context)) < 0) ||
|
||||||
(!all_contents_imported && (ret = es->ImportTitleCancel(context)) < 0))
|
(!all_contents_imported && (ret = es.ImportTitleCancel(context)) < 0))
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CORE, "Failed to finalise title import: error {}", static_cast<u32>(ret));
|
ERROR_LOG_FMT(CORE, "Failed to finalise title import: error {}", static_cast<u32>(ret));
|
||||||
return UpdateResult::ImportFailed;
|
return UpdateResult::ImportFailed;
|
||||||
|
@ -742,7 +742,8 @@ UpdateResult DiscSystemUpdater::DoDiscUpdate()
|
||||||
|
|
||||||
// Do not allow mismatched regions, because installing an update will automatically change
|
// Do not allow mismatched regions, because installing an update will automatically change
|
||||||
// the Wii's region and may result in semi/full system menu bricks.
|
// the Wii's region and may result in semi/full system menu bricks.
|
||||||
const IOS::ES::TMDReader system_menu_tmd = m_ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
|
const IOS::ES::TMDReader system_menu_tmd =
|
||||||
|
m_ios.GetESCore().FindInstalledTMD(Titles::SYSTEM_MENU);
|
||||||
if (system_menu_tmd.IsValid() && m_volume->GetRegion() != system_menu_tmd.GetRegion())
|
if (system_menu_tmd.IsValid() && m_volume->GetRegion() != system_menu_tmd.GetRegion())
|
||||||
return UpdateResult::RegionMismatch;
|
return UpdateResult::RegionMismatch;
|
||||||
|
|
||||||
|
@ -826,8 +827,8 @@ UpdateResult DiscSystemUpdater::ProcessEntry(u32 type, std::bitset<32> attrs,
|
||||||
if (type != 2 && type != 3 && type != 6 && type != 7)
|
if (type != 2 && type != 3 && type != 6 && type != 7)
|
||||||
return UpdateResult::AlreadyUpToDate;
|
return UpdateResult::AlreadyUpToDate;
|
||||||
|
|
||||||
const IOS::ES::TMDReader tmd = m_ios.GetES()->FindInstalledTMD(title.id);
|
const IOS::ES::TMDReader tmd = m_ios.GetESCore().FindInstalledTMD(title.id);
|
||||||
const IOS::ES::TicketReader ticket = m_ios.GetES()->FindSignedTicket(title.id);
|
const IOS::ES::TicketReader ticket = m_ios.GetESCore().FindSignedTicket(title.id);
|
||||||
|
|
||||||
// Optional titles can be skipped if the ticket is present, even when the title isn't installed.
|
// Optional titles can be skipped if the ticket is present, even when the title isn't installed.
|
||||||
if (attrs.test(16) && ticket.IsValid())
|
if (attrs.test(16) && ticket.IsValid())
|
||||||
|
@ -846,7 +847,7 @@ UpdateResult DiscSystemUpdater::ProcessEntry(u32 type, std::bitset<32> attrs,
|
||||||
return UpdateResult::DiscReadFailed;
|
return UpdateResult::DiscReadFailed;
|
||||||
}
|
}
|
||||||
const DiscIO::VolumeWAD wad{std::move(blob)};
|
const DiscIO::VolumeWAD wad{std::move(blob)};
|
||||||
const bool success = ImportWAD(m_ios, wad, IOS::HLE::ESDevice::VerifySignature::Yes);
|
const bool success = ImportWAD(m_ios, wad, IOS::HLE::ESCore::VerifySignature::Yes);
|
||||||
return success ? UpdateResult::Succeeded : UpdateResult::ImportFailed;
|
return success ? UpdateResult::Succeeded : UpdateResult::ImportFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +866,7 @@ UpdateResult DoDiscUpdate(UpdateCallback update_callback, const std::string& ima
|
||||||
static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
|
static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
|
||||||
{
|
{
|
||||||
NANDCheckResult result;
|
NANDCheckResult result;
|
||||||
const auto es = ios.GetES();
|
const auto& es = ios.GetESCore();
|
||||||
|
|
||||||
// Check for NANDs that were used with old Dolphin versions.
|
// Check for NANDs that were used with old Dolphin versions.
|
||||||
const std::string sys_replace_path =
|
const std::string sys_replace_path =
|
||||||
|
@ -892,7 +893,7 @@ static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
|
||||||
result.bad = true;
|
result.bad = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const u64 title_id : es->GetInstalledTitles())
|
for (const u64 title_id : es.GetInstalledTitles())
|
||||||
{
|
{
|
||||||
const std::string title_dir = Common::GetTitlePath(title_id, Common::FROM_CONFIGURED_ROOT);
|
const std::string title_dir = Common::GetTitlePath(title_id, Common::FROM_CONFIGURED_ROOT);
|
||||||
const std::string content_dir = title_dir + "/content";
|
const std::string content_dir = title_dir + "/content";
|
||||||
|
@ -912,7 +913,7 @@ static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for incomplete title installs (missing ticket, TMD or contents).
|
// Check for incomplete title installs (missing ticket, TMD or contents).
|
||||||
const auto ticket = es->FindSignedTicket(title_id);
|
const auto ticket = es.FindSignedTicket(title_id);
|
||||||
if (!IOS::ES::IsDiscTitle(title_id) && !ticket.IsValid())
|
if (!IOS::ES::IsDiscTitle(title_id) && !ticket.IsValid())
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CORE, "CheckNAND: Missing ticket for title {:016x}", title_id);
|
ERROR_LOG_FMT(CORE, "CheckNAND: Missing ticket for title {:016x}", title_id);
|
||||||
|
@ -923,7 +924,7 @@ static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
|
||||||
result.bad = true;
|
result.bad = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto tmd = es->FindInstalledTMD(title_id);
|
const auto tmd = es.FindInstalledTMD(title_id);
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
{
|
{
|
||||||
if (File::ScanDirectoryTree(content_dir, false).children.empty())
|
if (File::ScanDirectoryTree(content_dir, false).children.empty())
|
||||||
|
@ -943,7 +944,7 @@ static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto installed_contents = es->GetStoredContentsFromTMD(tmd);
|
const auto installed_contents = es.GetStoredContentsFromTMD(tmd);
|
||||||
const bool is_installed = std::any_of(installed_contents.begin(), installed_contents.end(),
|
const bool is_installed = std::any_of(installed_contents.begin(), installed_contents.end(),
|
||||||
[](const auto& content) { return !content.IsShared(); });
|
[](const auto& content) { return !content.IsShared(); });
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class VolumeWAD;
|
||||||
namespace IOS::HLE
|
namespace IOS::HLE
|
||||||
{
|
{
|
||||||
class BluetoothEmuDevice;
|
class BluetoothEmuDevice;
|
||||||
class ESDevice;
|
class ESCore;
|
||||||
class Kernel;
|
class Kernel;
|
||||||
} // namespace IOS::HLE
|
} // namespace IOS::HLE
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ IOS::ES::TMDReader FindBackupTMD(IOS::HLE::FS::FileSystem& fs, u64 title_id);
|
||||||
// Checks if there's a title.tmd imported for the given title ID. If there is not, we attempt to
|
// Checks if there's a title.tmd imported for the given title ID. If there is not, we attempt to
|
||||||
// re-import it from the TMDs stored in /title/00000001/00000002/data/tmds.sys.
|
// re-import it from the TMDs stored in /title/00000001/00000002/data/tmds.sys.
|
||||||
// Returns true if, after this function call, we have an imported title.tmd, or false if not.
|
// Returns true if, after this function call, we have an imported title.tmd, or false if not.
|
||||||
bool EnsureTMDIsImported(IOS::HLE::FS::FileSystem& fs, IOS::HLE::ESDevice& es, u64 title_id);
|
bool EnsureTMDIsImported(IOS::HLE::FS::FileSystem& fs, IOS::HLE::ESCore& es, u64 title_id);
|
||||||
|
|
||||||
enum class UpdateResult
|
enum class UpdateResult
|
||||||
{
|
{
|
||||||
|
|
|
@ -578,16 +578,16 @@ bool VolumeVerifier::CheckPartition(const Partition& partition)
|
||||||
const auto console_type =
|
const auto console_type =
|
||||||
IsDebugSigned() ? IOS::HLE::IOSC::ConsoleType::RVT : IOS::HLE::IOSC::ConsoleType::Retail;
|
IsDebugSigned() ? IOS::HLE::IOSC::ConsoleType::RVT : IOS::HLE::IOSC::ConsoleType::Retail;
|
||||||
IOS::HLE::Kernel ios(console_type);
|
IOS::HLE::Kernel ios(console_type);
|
||||||
const auto es = ios.GetES();
|
auto& es = ios.GetESCore();
|
||||||
const std::vector<u8>& cert_chain = m_volume.GetCertificateChain(partition);
|
const std::vector<u8>& cert_chain = m_volume.GetCertificateChain(partition);
|
||||||
|
|
||||||
if (IOS::HLE::IPC_SUCCESS !=
|
if (IOS::HLE::IPC_SUCCESS !=
|
||||||
es->VerifyContainer(IOS::HLE::ESDevice::VerifyContainerType::Ticket,
|
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::Ticket,
|
||||||
IOS::HLE::ESDevice::VerifyMode::DoNotUpdateCertStore,
|
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore,
|
||||||
m_volume.GetTicket(partition), cert_chain) ||
|
m_volume.GetTicket(partition), cert_chain) ||
|
||||||
IOS::HLE::IPC_SUCCESS !=
|
IOS::HLE::IPC_SUCCESS !=
|
||||||
es->VerifyContainer(IOS::HLE::ESDevice::VerifyContainerType::TMD,
|
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::TMD,
|
||||||
IOS::HLE::ESDevice::VerifyMode::DoNotUpdateCertStore,
|
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore,
|
||||||
m_volume.GetTMD(partition), cert_chain))
|
m_volume.GetTMD(partition), cert_chain))
|
||||||
{
|
{
|
||||||
AddProblem(Severity::Low,
|
AddProblem(Severity::Low,
|
||||||
|
@ -982,12 +982,12 @@ void VolumeVerifier::CheckMisc()
|
||||||
if (m_volume.GetVolumeType() == Platform::WiiWAD)
|
if (m_volume.GetVolumeType() == Platform::WiiWAD)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios(m_ticket.GetConsoleType());
|
IOS::HLE::Kernel ios(m_ticket.GetConsoleType());
|
||||||
const auto es = ios.GetES();
|
auto& es = ios.GetESCore();
|
||||||
const std::vector<u8>& cert_chain = m_volume.GetCertificateChain(PARTITION_NONE);
|
const std::vector<u8>& cert_chain = m_volume.GetCertificateChain(PARTITION_NONE);
|
||||||
|
|
||||||
if (IOS::HLE::IPC_SUCCESS !=
|
if (IOS::HLE::IPC_SUCCESS !=
|
||||||
es->VerifyContainer(IOS::HLE::ESDevice::VerifyContainerType::Ticket,
|
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::Ticket,
|
||||||
IOS::HLE::ESDevice::VerifyMode::DoNotUpdateCertStore, m_ticket,
|
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore, m_ticket,
|
||||||
cert_chain))
|
cert_chain))
|
||||||
{
|
{
|
||||||
// i18n: "Ticket" here is a kind of digital authorization to use a certain title (e.g. a game)
|
// i18n: "Ticket" here is a kind of digital authorization to use a certain title (e.g. a game)
|
||||||
|
@ -995,8 +995,8 @@ void VolumeVerifier::CheckMisc()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IOS::HLE::IPC_SUCCESS !=
|
if (IOS::HLE::IPC_SUCCESS !=
|
||||||
es->VerifyContainer(IOS::HLE::ESDevice::VerifyContainerType::TMD,
|
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::TMD,
|
||||||
IOS::HLE::ESDevice::VerifyMode::DoNotUpdateCertStore, tmd, cert_chain))
|
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore, tmd, cert_chain))
|
||||||
{
|
{
|
||||||
AddProblem(
|
AddProblem(
|
||||||
Severity::Medium,
|
Severity::Medium,
|
||||||
|
|
|
@ -1011,7 +1011,7 @@ void MenuBar::UpdateToolsMenu(bool emulation_started)
|
||||||
if (!emulation_started)
|
if (!emulation_started)
|
||||||
{
|
{
|
||||||
IOS::HLE::Kernel ios;
|
IOS::HLE::Kernel ios;
|
||||||
const auto tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
|
const auto tmd = ios.GetESCore().FindInstalledTMD(Titles::SYSTEM_MENU);
|
||||||
|
|
||||||
const QString sysmenu_version =
|
const QString sysmenu_version =
|
||||||
tmd.IsValid() ? QString::fromStdString(
|
tmd.IsValid() ? QString::fromStdString(
|
||||||
|
|
Loading…
Reference in New Issue