WFS: Fix shutdown behavior with long hanging requests.
This commit is contained in:
parent
385f063be1
commit
f0ba0f617f
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue