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/FileUtil.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
|
#include "Core/IOS/ES/ES.h"
|
||||||
#include "Core/IOS/ES/Formats.h"
|
#include "Core/IOS/ES/Formats.h"
|
||||||
#include "Core/IOS/WFS/WFSSRV.h"
|
#include "Core/IOS/WFS/WFSSRV.h"
|
||||||
#include "DiscIO/NANDContentLoader.h"
|
#include "DiscIO/NANDContentLoader.h"
|
||||||
|
@ -215,8 +216,13 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFSI_INIT:
|
case IOCTL_WFSI_INIT:
|
||||||
// Nothing to do.
|
|
||||||
INFO_LOG(IOS, "IOCTL_WFSI_INIT");
|
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;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFSI_SET_DEVICE_NAME:
|
case IOCTL_WFSI_SET_DEVICE_NAME:
|
||||||
|
@ -235,6 +241,51 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
|
|
||||||
break;
|
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:
|
default:
|
||||||
// TODO(wfs): Should be returning an error. However until we have
|
// TODO(wfs): Should be returning an error. However until we have
|
||||||
// everything properly stubbed it's easier to simulate the methods
|
// everything properly stubbed it's easier to simulate the methods
|
||||||
|
|
|
@ -52,9 +52,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;
|
||||||
|
|
||||||
ARCUnpacker m_arc_unpacker;
|
ARCUnpacker m_arc_unpacker;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
WFSI_ENOENT = -12000,
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IOCTL_WFSI_PREPARE_DEVICE = 0x02,
|
IOCTL_WFSI_PREPARE_DEVICE = 0x02,
|
||||||
|
@ -74,6 +80,8 @@ private:
|
||||||
IOCTL_WFSI_FINALIZE_PROFILE = 0x88,
|
IOCTL_WFSI_FINALIZE_PROFILE = 0x88,
|
||||||
|
|
||||||
IOCTL_WFSI_APPLY_TITLE_PROFILE = 0x89,
|
IOCTL_WFSI_APPLY_TITLE_PROFILE = 0x89,
|
||||||
|
|
||||||
|
IOCTL_WFSI_LOAD_DOL = 0x90,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // namespace Device
|
} // namespace Device
|
||||||
|
|
|
@ -44,6 +44,20 @@ IPCCommandResult WFSSRV::IOCtl(const IOCtlRequest& request)
|
||||||
INFO_LOG(IOS, "IOCTL_WFS_INIT");
|
INFO_LOG(IOS, "IOCTL_WFS_INIT");
|
||||||
break;
|
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:
|
case IOCTL_WFS_DEVICE_INFO:
|
||||||
INFO_LOG(IOS, "IOCTL_WFS_DEVICE_INFO");
|
INFO_LOG(IOS, "IOCTL_WFS_DEVICE_INFO");
|
||||||
Memory::Write_U64(16ull << 30, request.buffer_out); // 16GB storage.
|
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:
|
case IOCTL_WFS_ATTACH_DETACH:
|
||||||
INFO_LOG(IOS, "IOCTL_WFS_ATTACH_DETACH(%u)", request.request);
|
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);
|
// Leave hanging, but we need to acknowledge the request at shutdown time.
|
||||||
Memory::Write_U32(0, request.buffer_out + 8);
|
m_hanging.push_back(request.address);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
|
|
||||||
// TODO(wfs): Globbing is not really implemented, we just fake the one case
|
// TODO(wfs): Globbing is not really implemented, we just fake the one case
|
||||||
|
|
|
@ -38,8 +38,10 @@ private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IOCTL_WFS_INIT = 0x02,
|
IOCTL_WFS_INIT = 0x02,
|
||||||
|
IOCTL_WFS_SHUTDOWN = 0x03,
|
||||||
IOCTL_WFS_DEVICE_INFO = 0x04,
|
IOCTL_WFS_DEVICE_INFO = 0x04,
|
||||||
IOCTL_WFS_GET_DEVICE_NAME = 0x05,
|
IOCTL_WFS_GET_DEVICE_NAME = 0x05,
|
||||||
|
IOCTL_WFS_UNMOUNT_VOLUME = 0x06,
|
||||||
IOCTL_WFS_FLUSH = 0x0a,
|
IOCTL_WFS_FLUSH = 0x0a,
|
||||||
IOCTL_WFS_GLOB_START = 0x0d,
|
IOCTL_WFS_GLOB_START = 0x0d,
|
||||||
IOCTL_WFS_GLOB_NEXT = 0x0e,
|
IOCTL_WFS_GLOB_NEXT = 0x0e,
|
||||||
|
@ -75,6 +77,10 @@ private:
|
||||||
};
|
};
|
||||||
std::vector<FileDescriptor> m_fds;
|
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);
|
FileDescriptor* FindFileDescriptor(u16 fd);
|
||||||
u16 GetNewFileDescriptor();
|
u16 GetNewFileDescriptor();
|
||||||
void ReleaseFileDescriptor(u16 fd);
|
void ReleaseFileDescriptor(u16 fd);
|
||||||
|
|
Loading…
Reference in New Issue