WFSI: More work to support patching: split off current_tid/gid and import_tid/gid
This commit is contained in:
parent
aa445806a5
commit
db24c94c6e
|
@ -21,6 +21,20 @@
|
||||||
#include "Core/IOS/WFS/WFSSRV.h"
|
#include "Core/IOS/WFS/WFSSRV.h"
|
||||||
#include "DiscIO/NANDContentLoader.h"
|
#include "DiscIO/NANDContentLoader.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::string TitleIdStr(u64 tid)
|
||||||
|
{
|
||||||
|
return StringFromFormat("%c%c%c%c", static_cast<char>(tid >> 24), static_cast<char>(tid >> 16),
|
||||||
|
static_cast<char>(tid >> 8), static_cast<char>(tid));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GroupIdStr(u16 gid)
|
||||||
|
{
|
||||||
|
return StringFromFormat("%c%c", gid >> 8, gid & 0xFF);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace IOS
|
namespace IOS
|
||||||
{
|
{
|
||||||
namespace HLE
|
namespace HLE
|
||||||
|
@ -87,6 +101,24 @@ WFSI::WFSI(Kernel& ios, const std::string& device_name) : Device(ios, device_nam
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WFSI::SetCurrentTitleIdAndGroupId(u64 tid, u16 gid)
|
||||||
|
{
|
||||||
|
m_current_title_id = tid;
|
||||||
|
m_current_group_id = gid;
|
||||||
|
|
||||||
|
m_current_title_id_str = TitleIdStr(tid);
|
||||||
|
m_current_group_id_str = GroupIdStr(gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WFSI::SetImportTitleIdAndGroupId(u64 tid, u16 gid)
|
||||||
|
{
|
||||||
|
m_import_title_id = tid;
|
||||||
|
m_import_group_id = gid;
|
||||||
|
|
||||||
|
m_import_title_id_str = TitleIdStr(tid);
|
||||||
|
m_import_group_id_str = GroupIdStr(gid);
|
||||||
|
}
|
||||||
|
|
||||||
IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
s32 return_error_code = IPC_SUCCESS;
|
s32 return_error_code = IPC_SUCCESS;
|
||||||
|
@ -98,7 +130,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
u32 tmd_addr = Memory::Read_U32(request.buffer_in);
|
u32 tmd_addr = Memory::Read_U32(request.buffer_in);
|
||||||
u32 tmd_size = Memory::Read_U32(request.buffer_in + 4);
|
u32 tmd_size = Memory::Read_U32(request.buffer_in + 4);
|
||||||
|
|
||||||
m_patch_type = Memory::Read_U32(request.buffer_in + 32);
|
m_patch_type = static_cast<PatchType>(Memory::Read_U32(request.buffer_in + 32));
|
||||||
m_continue_install = Memory::Read_U32(request.buffer_in + 36);
|
m_continue_install = Memory::Read_U32(request.buffer_in + 36);
|
||||||
|
|
||||||
INFO_LOG(IOS_WFS, "IOCTL_WFSI_PREPARE_DEVICE: patch type %d, continue install: %s",
|
INFO_LOG(IOS_WFS, "IOCTL_WFSI_PREPARE_DEVICE: patch type %d, continue install: %s",
|
||||||
|
@ -126,13 +158,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
memcpy(m_aes_key, ticket.GetTitleKey(m_ios.GetIOSC()).data(), sizeof(m_aes_key));
|
memcpy(m_aes_key, ticket.GetTitleKey(m_ios.GetIOSC()).data(), sizeof(m_aes_key));
|
||||||
mbedtls_aes_setkey_dec(&m_aes_ctx, m_aes_key, 128);
|
mbedtls_aes_setkey_dec(&m_aes_ctx, m_aes_key, 128);
|
||||||
|
|
||||||
m_title_id = m_tmd.GetTitleId();
|
SetImportTitleIdAndGroupId(m_tmd.GetTitleId(), m_tmd.GetGroupId());
|
||||||
m_title_id_str = StringFromFormat(
|
|
||||||
"%c%c%c%c", static_cast<char>(m_title_id >> 24), static_cast<char>(m_title_id >> 16),
|
|
||||||
static_cast<char>(m_title_id >> 8), static_cast<char>(m_title_id));
|
|
||||||
m_group_id = m_tmd.GetGroupId();
|
|
||||||
m_group_id_str = StringFromFormat("%c%c", m_group_id >> 8, m_group_id & 0xFF);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,15 +245,16 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
case IOCTL_WFSI_FINALIZE_TITLE_INSTALL:
|
case IOCTL_WFSI_FINALIZE_TITLE_INSTALL:
|
||||||
{
|
{
|
||||||
// TODO(wfs): Handle patches.
|
// TODO(wfs): Handle patches.
|
||||||
std::string title_install_dir =
|
std::string title_install_dir = StringFromFormat("/vol/%s/_install/%s", m_device_name.c_str(),
|
||||||
StringFromFormat("/vol/%s/_install/%s", m_device_name.c_str(), m_title_id_str.c_str());
|
m_import_title_id_str.c_str());
|
||||||
std::string title_final_dir = StringFromFormat("/vol/%s/title/%s/%s", m_device_name.c_str(),
|
std::string title_final_dir =
|
||||||
m_group_id_str.c_str(), m_title_id_str.c_str());
|
StringFromFormat("/vol/%s/title/%s/%s", m_device_name.c_str(),
|
||||||
|
m_import_group_id_str.c_str(), m_import_title_id_str.c_str());
|
||||||
File::Rename(WFS::NativePath(title_install_dir), WFS::NativePath(title_final_dir));
|
File::Rename(WFS::NativePath(title_install_dir), WFS::NativePath(title_final_dir));
|
||||||
|
|
||||||
std::string tmd_path =
|
std::string tmd_path = StringFromFormat("/vol/%s/title/%s/%s/meta/%016" PRIx64 ".tmd",
|
||||||
StringFromFormat("/vol/%s/title/%s/%s/meta/%016" PRIx64 ".tmd", m_device_name.c_str(),
|
m_device_name.c_str(), m_import_group_id_str.c_str(),
|
||||||
m_group_id_str.c_str(), m_title_id_str.c_str(), m_title_id);
|
m_import_title_id_str.c_str(), m_import_title_id);
|
||||||
File::IOFile tmd_file(WFS::NativePath(tmd_path), "wb");
|
File::IOFile tmd_file(WFS::NativePath(tmd_path), "wb");
|
||||||
tmd_file.WriteBytes(m_tmd.GetBytes().data(), m_tmd.GetBytes().size());
|
tmd_file.WriteBytes(m_tmd.GetBytes().data(), m_tmd.GetBytes().size());
|
||||||
break;
|
break;
|
||||||
|
@ -247,19 +274,16 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
case IOCTL_WFSI_INIT:
|
case IOCTL_WFSI_INIT:
|
||||||
{
|
{
|
||||||
INFO_LOG(IOS_WFS, "IOCTL_WFSI_INIT");
|
INFO_LOG(IOS_WFS, "IOCTL_WFSI_INIT");
|
||||||
if (GetIOS()->GetES()->GetTitleId(&m_title_id) < 0)
|
u64 tid;
|
||||||
|
if (GetIOS()->GetES()->GetTitleId(&tid) < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG(IOS_WFS, "IOCTL_WFSI_INIT: Could not get title id.");
|
ERROR_LOG(IOS_WFS, "IOCTL_WFSI_INIT: Could not get title id.");
|
||||||
return_error_code = IPC_EINVAL;
|
return_error_code = IPC_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m_title_id_str = StringFromFormat(
|
|
||||||
"%c%c%c%c", static_cast<char>(m_title_id >> 24), static_cast<char>(m_title_id >> 16),
|
|
||||||
static_cast<char>(m_title_id >> 8), static_cast<char>(m_title_id));
|
|
||||||
|
|
||||||
IOS::ES::TMDReader tmd = GetIOS()->GetES()->FindInstalledTMD(m_title_id);
|
IOS::ES::TMDReader tmd = GetIOS()->GetES()->FindInstalledTMD(tid);
|
||||||
m_group_id = tmd.GetGroupId();
|
SetCurrentTitleIdAndGroupId(tmd.GetTitleId(), tmd.GetGroupId());
|
||||||
m_group_id_str = StringFromFormat("%c%c", m_group_id >> 8, m_group_id & 0xFF);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,29 +296,40 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
INFO_LOG(IOS_WFS, "IOCTL_WFSI_APPLY_TITLE_PROFILE");
|
INFO_LOG(IOS_WFS, "IOCTL_WFSI_APPLY_TITLE_PROFILE");
|
||||||
|
|
||||||
std::string install_directory = StringFromFormat("/vol/%s/_install", m_device_name.c_str());
|
if (m_patch_type == NOT_A_PATCH)
|
||||||
if (!m_continue_install && File::IsDirectory(WFS::NativePath(install_directory)))
|
|
||||||
{
|
{
|
||||||
File::DeleteDirRecursively(WFS::NativePath(install_directory));
|
std::string install_directory = StringFromFormat("/vol/%s/_install", m_device_name.c_str());
|
||||||
|
if (!m_continue_install && File::IsDirectory(WFS::NativePath(install_directory)))
|
||||||
|
{
|
||||||
|
File::DeleteDirRecursively(WFS::NativePath(install_directory));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_base_extract_path = StringFromFormat("%s/%s/content", install_directory.c_str(),
|
||||||
|
m_import_title_id_str.c_str());
|
||||||
|
File::CreateFullPath(WFS::NativePath(m_base_extract_path));
|
||||||
|
File::CreateDir(WFS::NativePath(m_base_extract_path));
|
||||||
|
|
||||||
|
for (auto dir : {"work", "meta", "save"})
|
||||||
|
{
|
||||||
|
std::string path = StringFromFormat("%s/%s/%s", install_directory.c_str(),
|
||||||
|
m_import_title_id_str.c_str(), dir);
|
||||||
|
File::CreateDir(WFS::NativePath(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string group_path = StringFromFormat("/vol/%s/title/%s", m_device_name.c_str(),
|
||||||
|
m_import_group_id_str.c_str());
|
||||||
|
File::CreateFullPath(WFS::NativePath(group_path));
|
||||||
|
File::CreateDir(WFS::NativePath(group_path));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
m_base_extract_path =
|
|
||||||
StringFromFormat("%s/%s/content", install_directory.c_str(), m_title_id_str.c_str());
|
|
||||||
File::CreateFullPath(WFS::NativePath(m_base_extract_path));
|
|
||||||
File::CreateDir(WFS::NativePath(m_base_extract_path));
|
|
||||||
|
|
||||||
for (auto dir : {"work", "meta", "save"})
|
|
||||||
{
|
{
|
||||||
std::string path =
|
m_base_extract_path =
|
||||||
StringFromFormat("%s/%s/%s", install_directory.c_str(), m_title_id_str.c_str(), dir);
|
StringFromFormat("/vol/%s/title/%s/%s/_patch/content", m_device_name.c_str(),
|
||||||
File::CreateDir(WFS::NativePath(path));
|
m_current_group_id_str.c_str(), m_current_title_id_str.c_str());
|
||||||
|
File::CreateFullPath(WFS::NativePath(m_base_extract_path));
|
||||||
|
File::CreateDir(WFS::NativePath(m_base_extract_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string group_path =
|
|
||||||
StringFromFormat("/vol/%s/title/%s", m_device_name.c_str(), m_group_id_str.c_str());
|
|
||||||
File::CreateFullPath(WFS::NativePath(group_path));
|
|
||||||
File::CreateDir(WFS::NativePath(group_path));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +340,8 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
INFO_LOG(IOS, "IOCTL_WFSI_GET_TMD: subtitle ID %016" PRIx64, subtitle_id);
|
INFO_LOG(IOS, "IOCTL_WFSI_GET_TMD: subtitle ID %016" PRIx64, subtitle_id);
|
||||||
|
|
||||||
u32 tmd_size;
|
u32 tmd_size;
|
||||||
return_error_code = GetTmd(m_group_id, m_title_id, subtitle_id, address, &tmd_size);
|
return_error_code =
|
||||||
|
GetTmd(m_current_group_id, m_current_title_id, subtitle_id, address, &tmd_size);
|
||||||
Memory::Write_U32(tmd_size, request.buffer_out);
|
Memory::Write_U32(tmd_size, request.buffer_out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -334,8 +370,9 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
|
|
||||||
case IOCTL_WFSI_LOAD_DOL:
|
case IOCTL_WFSI_LOAD_DOL:
|
||||||
{
|
{
|
||||||
std::string path = StringFromFormat("/vol/%s/title/%s/%s/content", m_device_name.c_str(),
|
std::string path =
|
||||||
m_group_id_str.c_str(), m_title_id_str.c_str());
|
StringFromFormat("/vol/%s/title/%s/%s/content", m_device_name.c_str(),
|
||||||
|
m_current_group_id_str.c_str(), m_current_title_id_str.c_str());
|
||||||
|
|
||||||
u32 dol_addr = Memory::Read_U32(request.buffer_in + 0x18);
|
u32 dol_addr = Memory::Read_U32(request.buffer_in + 0x18);
|
||||||
u32 max_dol_size = Memory::Read_U32(request.buffer_in + 0x14);
|
u32 max_dol_size = Memory::Read_U32(request.buffer_in + 0x14);
|
||||||
|
@ -406,10 +443,9 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
|
|
||||||
u32 WFSI::GetTmd(u16 group_id, u32 title_id, u64 subtitle_id, u32 address, u32* size) const
|
u32 WFSI::GetTmd(u16 group_id, u32 title_id, u64 subtitle_id, u32 address, u32* size) const
|
||||||
{
|
{
|
||||||
// TODO(wfs): This is using a separate copy of tid/gid in wfssrv. Why?
|
|
||||||
std::string path =
|
std::string path =
|
||||||
StringFromFormat("/vol/%s/title/%s/%s/meta/%016" PRIx64 ".tmd", m_device_name.c_str(),
|
StringFromFormat("/vol/%s/title/%s/%s/meta/%016" PRIx64 ".tmd", m_device_name.c_str(),
|
||||||
m_group_id_str.c_str(), m_title_id_str.c_str(), subtitle_id);
|
GroupIdStr(group_id).c_str(), TitleIdStr(title_id).c_str(), subtitle_id);
|
||||||
File::IOFile fp(WFS::NativePath(path), "rb");
|
File::IOFile fp(WFS::NativePath(path), "rb");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,6 +45,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 GetTmd(u16 group_id, u32 title_id, u64 subtitle_id, u32 address, u32* size) const;
|
u32 GetTmd(u16 group_id, u32 title_id, u64 subtitle_id, u32 address, u32* size) const;
|
||||||
|
|
||||||
|
void SetCurrentTitleIdAndGroupId(u64 tid, u16 gid);
|
||||||
|
void SetImportTitleIdAndGroupId(u64 tid, u16 gid);
|
||||||
|
|
||||||
std::string m_device_name;
|
std::string m_device_name;
|
||||||
|
|
||||||
mbedtls_aes_context m_aes_ctx;
|
mbedtls_aes_context m_aes_ctx;
|
||||||
|
@ -53,10 +57,15 @@ private:
|
||||||
|
|
||||||
IOS::ES::TMDReader m_tmd;
|
IOS::ES::TMDReader m_tmd;
|
||||||
std::string m_base_extract_path;
|
std::string m_base_extract_path;
|
||||||
u64 m_title_id;
|
|
||||||
std::string m_title_id_str;
|
u64 m_current_title_id;
|
||||||
u16 m_group_id;
|
std::string m_current_title_id_str;
|
||||||
std::string m_group_id_str;
|
u16 m_current_group_id;
|
||||||
|
std::string m_current_group_id_str;
|
||||||
|
u64 m_import_title_id;
|
||||||
|
std::string m_import_title_id_str;
|
||||||
|
u16 m_import_group_id;
|
||||||
|
std::string m_import_group_id_str;
|
||||||
|
|
||||||
// Set on PREPARE_DEVICE when the next profile application should not delete
|
// Set on PREPARE_DEVICE when the next profile application should not delete
|
||||||
// temporary install files.
|
// temporary install files.
|
||||||
|
@ -64,7 +73,13 @@ private:
|
||||||
|
|
||||||
// Set on PREPARE_DEVICE to indicate that the install is a patch and not a
|
// Set on PREPARE_DEVICE to indicate that the install is a patch and not a
|
||||||
// standalone title.
|
// standalone title.
|
||||||
u32 m_patch_type = 0;
|
enum PatchType
|
||||||
|
{
|
||||||
|
NOT_A_PATCH,
|
||||||
|
PATCH_TYPE_1,
|
||||||
|
PATCH_TYPE_2,
|
||||||
|
};
|
||||||
|
PatchType m_patch_type = NOT_A_PATCH;
|
||||||
|
|
||||||
ARCUnpacker m_arc_unpacker;
|
ARCUnpacker m_arc_unpacker;
|
||||||
|
|
||||||
|
@ -97,6 +112,8 @@ private:
|
||||||
|
|
||||||
IOCTL_WFSI_LOAD_DOL = 0x90,
|
IOCTL_WFSI_LOAD_DOL = 0x90,
|
||||||
|
|
||||||
|
IOCTL_WFSI_FINALIZE_PATCH_INSTALL = 0x91,
|
||||||
|
|
||||||
IOCTL_WFSI_CHECK_HAS_SPACE = 0x95,
|
IOCTL_WFSI_CHECK_HAS_SPACE = 0x95,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue