WFSI: Implement install finalization.

This commit is contained in:
Pierre Bourdon 2017-08-16 06:10:11 +02:00
parent 88580b8d5f
commit e6e00f6c8d
2 changed files with 40 additions and 4 deletions

View File

@ -98,6 +98,8 @@ 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_continue_install = Memory::Read_U32(request.buffer_in + 36);
INFO_LOG(IOS_WFS, "IOCTL_WFSI_PREPARE_DEVICE"); INFO_LOG(IOS_WFS, "IOCTL_WFSI_PREPARE_DEVICE");
constexpr u32 MAX_TMD_SIZE = 0x4000; constexpr u32 MAX_TMD_SIZE = 0x4000;
@ -122,6 +124,13 @@ 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();
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;
} }
@ -205,6 +214,23 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
break; break;
} }
case IOCTL_WFSI_FINALIZE_IMPORT:
{
// TODO(wfs): Handle patches.
std::string title_install_dir =
StringFromFormat("/vol/%s/_install/%s", m_device_name.c_str(), m_title_id_str.c_str());
std::string title_final_dir = StringFromFormat("/vol/%s/title/%s/%s", m_device_name.c_str(),
m_group_id_str.c_str(), m_title_id_str.c_str());
File::Rename(WFS::NativePath(title_install_dir), WFS::NativePath(title_final_dir));
std::string tmd_path =
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(), m_title_id);
File::IOFile tmd_file(WFS::NativePath(tmd_path), "wb");
tmd_file.WriteBytes(m_tmd.GetBytes().data(), m_tmd.GetBytes().size());
break;
}
case IOCTL_WFSI_DELETE_TITLE: case IOCTL_WFSI_DELETE_TITLE:
// Bytes 0-4: ?? // Bytes 0-4: ??
// Bytes 4-8: game id // Bytes 4-8: game id
@ -226,8 +252,8 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
break; break;
} }
m_title_id_str = StringFromFormat( m_title_id_str = StringFromFormat(
"%c%c%c%c", static_cast<char>(m_title_id >> 56), static_cast<char>(m_title_id >> 48), "%c%c%c%c", static_cast<char>(m_title_id >> 24), static_cast<char>(m_title_id >> 16),
static_cast<char>(m_title_id >> 40), static_cast<char>(m_title_id >> 32)); 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(m_title_id);
m_group_id = tmd.GetGroupId(); m_group_id = tmd.GetGroupId();
@ -241,10 +267,11 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
break; break;
case IOCTL_WFSI_APPLY_TITLE_PROFILE: case IOCTL_WFSI_APPLY_TITLE_PROFILE:
{
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()); std::string install_directory = StringFromFormat("/vol/%s/_install", m_device_name.c_str());
if (File::IsDirectory(WFS::NativePath(install_directory))) if (!m_continue_install && File::IsDirectory(WFS::NativePath(install_directory)))
{ {
File::DeleteDirRecursively(WFS::NativePath(install_directory)); File::DeleteDirRecursively(WFS::NativePath(install_directory));
} }
@ -252,19 +279,22 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
m_base_extract_path = m_base_extract_path =
StringFromFormat("%s/%s/content", install_directory.c_str(), m_title_id_str.c_str()); StringFromFormat("%s/%s/content", install_directory.c_str(), m_title_id_str.c_str());
File::CreateFullPath(WFS::NativePath(m_base_extract_path)); File::CreateFullPath(WFS::NativePath(m_base_extract_path));
File::CreateDir(WFS::NativePath(m_base_extract_path));
for (auto dir : {"work", "meta", "save"}) for (auto dir : {"work", "meta", "save"})
{ {
std::string path = std::string path =
StringFromFormat("%s/%s/%s", install_directory.c_str(), m_title_id_str.c_str(), dir); StringFromFormat("%s/%s/%s", install_directory.c_str(), m_title_id_str.c_str(), dir);
File::CreateFullPath(WFS::NativePath(path)); File::CreateDir(WFS::NativePath(path));
} }
std::string group_path = std::string group_path =
StringFromFormat("/vol/%s/title/%s", m_device_name.c_str(), m_group_id_str.c_str()); StringFromFormat("/vol/%s/title/%s", m_device_name.c_str(), m_group_id_str.c_str());
File::CreateFullPath(WFS::NativePath(group_path)); File::CreateFullPath(WFS::NativePath(group_path));
File::CreateDir(WFS::NativePath(group_path));
break; break;
}
case IOCTL_WFSI_GET_TMD: case IOCTL_WFSI_GET_TMD:
{ {

View File

@ -58,6 +58,10 @@ private:
u16 m_group_id; u16 m_group_id;
std::string m_group_id_str; std::string m_group_id_str;
// Set on PREPARE_DEVICE when the next profile application should not delete
// temporary install files.
u32 m_continue_install = 0;
ARCUnpacker m_arc_unpacker; ARCUnpacker m_arc_unpacker;
enum enum
@ -73,6 +77,8 @@ private:
IOCTL_WFSI_IMPORT_CONTENT = 0x04, IOCTL_WFSI_IMPORT_CONTENT = 0x04,
IOCTL_WFSI_FINALIZE_CONTENT = 0x05, IOCTL_WFSI_FINALIZE_CONTENT = 0x05,
IOCTL_WFSI_FINALIZE_IMPORT = 0x06,
IOCTL_WFSI_DELETE_TITLE = 0x17, IOCTL_WFSI_DELETE_TITLE = 0x17,
IOCTL_WFSI_IMPORT_TITLE = 0x2f, IOCTL_WFSI_IMPORT_TITLE = 0x2f,