WFS: Fix shutdown behavior with long hanging requests.

This commit is contained in:
Pierre Bourdon 2017-08-05 03:24:00 +02:00
parent 385f063be1
commit f0ba0f617f
4 changed files with 83 additions and 4 deletions

View File

@ -15,6 +15,7 @@
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/WFS/WFSSRV.h"
#include "DiscIO/NANDContentLoader.h"
@ -215,8 +216,13 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
break;
case IOCTL_WFSI_INIT:
// Nothing to do.
INFO_LOG(IOS, "IOCTL_WFSI_INIT");
if (GetIOS()->GetES()->GetTitleId(&m_title_id) < 0)
{
ERROR_LOG(IOS, "IOCTL_WFSI_INIT: Could not get title id.");
return_error_code = IPC_EINVAL;
break;
}
break;
case IOCTL_WFSI_SET_DEVICE_NAME:
@ -235,6 +241,51 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
break;
case IOCTL_WFSI_LOAD_DOL:
{
std::string path = StringFromFormat(
"/vol/%s/_install/%c%c%c%c/content", m_device_name.c_str(),
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));
u32 dol_addr = Memory::Read_U32(request.buffer_in + 0x18);
u32 max_dol_size = Memory::Read_U32(request.buffer_in + 0x14);
u16 dol_extension_id = Memory::Read_U16(request.buffer_in + 0x1e);
if (dol_extension_id == 0)
{
path += "/default.dol";
}
else
{
path += StringFromFormat("/extension%d.dol", dol_extension_id);
}
INFO_LOG(IOS, "IOCTL_WFSI_LOAD_DOL: loading %s at address %08x (size %d)", path.c_str(),
dol_addr, max_dol_size);
File::IOFile fp(WFS::NativePath(path), "rb");
if (!fp)
{
WARN_LOG(IOS, "IOCTL_WFSI_LOAD_DOL: no such file or directory: %s", path.c_str());
return_error_code = WFSI_ENOENT;
break;
}
u32 real_dol_size = fp.GetSize();
if (dol_addr == 0)
{
// Write the expected size to the size parameter, in the input.
Memory::Write_U32(real_dol_size, request.buffer_in + 0x14);
}
else
{
fp.ReadBytes(Memory::GetPointer(dol_addr), max_dol_size);
}
Memory::Write_U32(real_dol_size, request.buffer_out);
break;
}
default:
// TODO(wfs): Should be returning an error. However until we have
// everything properly stubbed it's easier to simulate the methods

View File

@ -52,9 +52,15 @@ private:
IOS::ES::TMDReader m_tmd;
std::string m_base_extract_path;
u64 m_title_id;
ARCUnpacker m_arc_unpacker;
enum
{
WFSI_ENOENT = -12000,
};
enum
{
IOCTL_WFSI_PREPARE_DEVICE = 0x02,
@ -74,6 +80,8 @@ private:
IOCTL_WFSI_FINALIZE_PROFILE = 0x88,
IOCTL_WFSI_APPLY_TITLE_PROFILE = 0x89,
IOCTL_WFSI_LOAD_DOL = 0x90,
};
};
} // namespace Device

View File

@ -44,6 +44,20 @@ IPCCommandResult WFSSRV::IOCtl(const IOCtlRequest& request)
INFO_LOG(IOS, "IOCTL_WFS_INIT");
break;
case IOCTL_WFS_SHUTDOWN:
INFO_LOG(IOS, "IOCTL_WFS_SHUTDOWN");
// Close all hanging attach/detach ioctls with an appropriate error code.
for (auto address : m_hanging)
{
IOCtlRequest hanging_request{address};
Memory::Write_U32(0x80000000, hanging_request.buffer_out);
Memory::Write_U32(0, hanging_request.buffer_out + 4);
Memory::Write_U32(0, hanging_request.buffer_out + 8);
m_ios.EnqueueIPCReply(hanging_request, 0);
}
break;
case IOCTL_WFS_DEVICE_INFO:
INFO_LOG(IOS, "IOCTL_WFS_DEVICE_INFO");
Memory::Write_U64(16ull << 30, request.buffer_out); // 16GB storage.
@ -68,9 +82,9 @@ IPCCommandResult WFSSRV::IOCtl(const IOCtlRequest& request)
case IOCTL_WFS_ATTACH_DETACH:
INFO_LOG(IOS, "IOCTL_WFS_ATTACH_DETACH(%u)", request.request);
Memory::Write_U32(1, request.buffer_out);
Memory::Write_U32(0, request.buffer_out + 4);
Memory::Write_U32(0, request.buffer_out + 8);
// Leave hanging, but we need to acknowledge the request at shutdown time.
m_hanging.push_back(request.address);
return GetNoReply();
// TODO(wfs): Globbing is not really implemented, we just fake the one case

View File

@ -38,8 +38,10 @@ private:
enum
{
IOCTL_WFS_INIT = 0x02,
IOCTL_WFS_SHUTDOWN = 0x03,
IOCTL_WFS_DEVICE_INFO = 0x04,
IOCTL_WFS_GET_DEVICE_NAME = 0x05,
IOCTL_WFS_UNMOUNT_VOLUME = 0x06,
IOCTL_WFS_FLUSH = 0x0a,
IOCTL_WFS_GLOB_START = 0x0d,
IOCTL_WFS_GLOB_NEXT = 0x0e,
@ -75,6 +77,10 @@ private:
};
std::vector<FileDescriptor> m_fds;
// List of addresses of IPC requests left hanging that need closing at
// shutdown time.
std::vector<u32> m_hanging;
FileDescriptor* FindFileDescriptor(u16 fd);
u16 GetNewFileDescriptor();
void ReleaseFileDescriptor(u16 fd);