IPCCommandResult ES::ImportTitleDone(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(0, 0)) return GetDefaultReply(ES_EINVAL); return GetDefaultReply(ImportTitleDone(context)); }
IPCCommandResult NetIPTop::HandleSetSockOptRequest(const IOCtlRequest& request) { u32 fd = Memory::Read_U32(request.buffer_in); u32 level = Memory::Read_U32(request.buffer_in + 4); u32 optname = Memory::Read_U32(request.buffer_in + 8); u32 optlen = Memory::Read_U32(request.buffer_in + 0xc); u8 optval[20]; optlen = std::min(optlen, (u32)sizeof(optval)); Memory::CopyFromEmu(optval, request.buffer_in + 0x10, optlen); INFO_LOG(IOS_NET, "IOCTL_SO_SETSOCKOPT(%08x, %08x, %08x, %08x) " "BufferIn: (%08x, %i), BufferOut: (%08x, %i)" "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx " "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx", fd, level, optname, optlen, request.buffer_in, request.buffer_in_size, request.buffer_out, request.buffer_out_size, optval[0], optval[1], optval[2], optval[3], optval[4], optval[5], optval[6], optval[7], optval[8], optval[9], optval[10], optval[11], optval[12], optval[13], optval[14], optval[15], optval[16], optval[17], optval[18], optval[19]); // TODO: bug booto about this, 0x2005 most likely timeout related, default value on Wii is , // 0x2001 is most likely tcpnodelay if (level == 6 && (optname == 0x2005 || optname == 0x2001)) return GetDefaultReply(0); // Do the level/optname translation int nat_level = MapWiiSockOptLevelToNative(level); int nat_optname = MapWiiSockOptNameToNative(optname); int ret = setsockopt(WiiSockMan::GetInstance().GetHostSocket(fd), nat_level, nat_optname, (char*)optval, optlen); return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false)); }
IPCCommandResult ES::DeleteSharedContent(const IOCtlVRequest& request) { std::array<u8, 20> sha1; if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sha1.size()) return GetDefaultReply(ES_EINVAL); Memory::CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size); return GetDefaultReply(DeleteSharedContent(sha1)); }
IPCCommandResult ES::DeleteTitle(const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8) return GetDefaultReply(ES_EINVAL); const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); return GetDefaultReply(DeleteTitle(title_id)); }
IPCCommandResult ES::ExportContentEnd(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4) return GetDefaultReply(ES_EINVAL); const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address); return GetDefaultReply(ExportContentEnd(context, content_fd)); }
IPCCommandResult ES::DeleteTicket(const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(IOS::ES::TicketView)) { return GetDefaultReply(ES_EINVAL); } return GetDefaultReply(DeleteTicket(Memory::GetPointer(request.in_vectors[0].address))); }
IPCCommandResult ES::ImportContentBegin(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0)) return GetDefaultReply(ES_EINVAL); u64 title_id = Memory::Read_U64(request.in_vectors[0].address); u32 content_id = Memory::Read_U32(request.in_vectors[1].address); return GetDefaultReply(ImportContentBegin(context, title_id, content_id)); }
IPCCommandResult ES::GetTitleCount(const std::vector<u64>& titles, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4) return GetDefaultReply(ES_EINVAL); Memory::Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address); return GetDefaultReply(IPC_SUCCESS); }
IPCCommandResult ES::DeleteContent(const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != sizeof(u64) || request.in_vectors[1].size != sizeof(u32)) { return GetDefaultReply(ES_EINVAL); } return GetDefaultReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address), Memory::Read_U32(request.in_vectors[1].address))); }
IPCCommandResult ES::ImportContentData(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0)) return GetDefaultReply(ES_EINVAL); u32 content_fd = Memory::Read_U32(request.in_vectors[0].address); u8* data_start = Memory::GetPointer(request.in_vectors[1].address); return GetDefaultReply( ImportContentData(context, content_fd, data_start, request.in_vectors[1].size)); }
IPCCommandResult ES::ExportTitleInit(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8) return GetDefaultReply(ES_EINVAL); const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); u8* tmd_bytes = Memory::GetPointer(request.io_vectors[0].address); const u32 tmd_size = request.io_vectors[0].size; return GetDefaultReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size)); }
IPCCommandResult ES::GetStoredContents(const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 1) || request.in_vectors[0].size != sizeof(u64)) return GetDefaultReply(ES_EINVAL); const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); const IOS::ES::TMDReader tmd = FindInstalledTMD(title_id); if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); return GetStoredContents(tmd, request); }
IPCCommandResult ES::GetBoot2Version(const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(0, 1)) return GetDefaultReply(ES_EINVAL); INFO_LOG(IOS_ES, "IOCTL_ES_GETBOOT2VERSION"); // as of 26/02/2012, this was latest bootmii version Memory::Write_U32(4, request.io_vectors[0].address); return GetDefaultReply(IPC_SUCCESS); }
IPCCommandResult ES::GetSharedContentsCount(const IOCtlVRequest& request) const { if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32)) return GetDefaultReply(ES_EINVAL); const u32 count = GetSharedContentsCount(); Memory::Write_U32(count, request.io_vectors[0].address); INFO_LOG(IOS_ES, "GetSharedContentsCount: %u contents", count); return GetDefaultReply(IPC_SUCCESS); }
IPCCommandResult ES::ImportTmd(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); if (!IOS::ES::IsValidTMDSize(request.in_vectors[0].size)) return GetDefaultReply(ES_EINVAL); std::vector<u8> tmd(request.in_vectors[0].size); Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size); return GetDefaultReply(ImportTmd(context, tmd)); }
IPCCommandResult STMEventHook::IOCtl(const IOCtlRequest& request) { if (request.request != IOCTL_STM_EVENTHOOK) return GetDefaultReply(IPC_EINVAL); if (s_event_hook_request) return GetDefaultReply(IPC_EEXIST); // IOCTL_STM_EVENTHOOK waits until the reset button or power button is pressed. s_event_hook_request = std::make_unique<IOCtlRequest>(request.address); return GetNoReply(); }
// Used by the GetStoredContents ioctlvs. This assumes that the first output vector // is used for the content count (u32). IPCCommandResult ES::GetStoredContentsCount(const IOS::ES::TMDReader& tmd, const IOCtlVRequest& request) { if (request.io_vectors[0].size != sizeof(u32) || !tmd.IsValid()) return GetDefaultReply(ES_EINVAL); const u16 num_contents = static_cast<u16>(GetStoredContentsFromTMD(tmd).size()); Memory::Write_U32(num_contents, request.io_vectors[0].address); INFO_LOG(IOS_ES, "GetStoredContentsCount (0x%x): %u content(s) for %016" PRIx64, request.request, num_contents, tmd.GetTitleId()); return GetDefaultReply(IPC_SUCCESS); }
IPCCommandResult ES::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1)) return GetDefaultReply(ES_EINVAL); const size_t max_count = Memory::Read_U32(request.in_vectors[0].address); for (size_t i = 0; i < std::min(max_count, titles.size()); i++) { Memory::Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * sizeof(u64)); INFO_LOG(IOS_ES, " title %016" PRIx64, titles[i]); } return GetDefaultReply(IPC_SUCCESS); }
IPCCommandResult USBHost::HandleTransfer(std::shared_ptr<USB::Device> device, u32 request, std::function<s32()> submit) const { if (!device) return GetDefaultReply(IPC_ENOENT); const s32 ret = submit(); if (ret == IPC_SUCCESS) return GetNoReply(); ERROR_LOG(IOS_USB, "[%04x:%04x] Failed to submit transfer (request %u): %s", device->GetVid(), device->GetPid(), request, device->GetErrorName(ret).c_str()); return GetDefaultReply(ret <= 0 ? ret : IPC_EINVAL); }
IPCCommandResult ES::ExportContentData(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 4 || request.io_vectors[0].size == 0) { return GetDefaultReply(ES_EINVAL); } const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address); u8* data = Memory::GetPointer(request.io_vectors[0].address); const u32 bytes_to_read = request.io_vectors[0].size; return GetDefaultReply(ExportContentData(context, content_fd, data, bytes_to_read)); }
IPCCommandResult FileIO::IOCtl(const IOCtlRequest& request) { DEBUG_LOG(IOS_FILEIO, "FileIO: IOCtl (Device=%s)", m_name.c_str()); s32 return_value = IPC_SUCCESS; switch (request.request) { case ISFS_IOCTL_GETFILESTATS: { if (m_file->IsOpen()) { DEBUG_LOG(IOS_FILEIO, "File: %s, Length: %" PRIu64 ", Pos: %i", m_name.c_str(), m_file->GetSize(), m_SeekPos); Memory::Write_U32(static_cast<u32>(m_file->GetSize()), request.buffer_out); Memory::Write_U32(m_SeekPos, request.buffer_out + 4); } else { return_value = FS_ENOENT; } } break; default: request.Log(GetDeviceName(), LogTypes::IOS_FILEIO, LogTypes::LERROR); } return GetDefaultReply(return_value); }
IPCCommandResult ES::GetSharedContents(const IOCtlVRequest& request) const { if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32)) return GetDefaultReply(ES_EINVAL); const u32 max_count = Memory::Read_U32(request.in_vectors[0].address); if (request.io_vectors[0].size != 20 * max_count) return GetDefaultReply(ES_EINVAL); const std::vector<std::array<u8, 20>> hashes = GetSharedContents(); const u32 count = std::min(static_cast<u32>(hashes.size()), max_count); Memory::CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count); INFO_LOG(IOS_ES, "GetSharedContents: %u contents (%u requested)", count, max_count); return GetDefaultReply(IPC_SUCCESS); }
IPCCommandResult CWII_IPC_HLE_Device_di::Close(u32 _CommandAddress, bool _bForce) { if (!_bForce) Memory::Write_U32(0, _CommandAddress + 4); m_Active = false; return GetDefaultReply(); }
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_base::IOCtl(u32 command_address) { // NeoGamma (homebrew) is known to use this path. ERROR_LOG(WII_IPC_WIIMOTE, "Bad IOCtl to /dev/usb/oh1/57e/305"); Memory::Write_U32(FS_EINVAL, command_address + 4); return GetDefaultReply(); }
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) { m_Mode = _Mode; u32 ReturnValue = 0; static const char* const Modes[] = {"Unk Mode", "Read only", "Write only", "Read and Write"}; m_filepath = HLE_IPC_BuildFilename(m_Name); // The file must exist before we can open it // It should be created by ISFS_CreateFile, not here if (File::Exists(m_filepath) && !File::IsDirectory(m_filepath)) { INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_Name.c_str(), Modes[_Mode], _Mode); OpenFile(); ReturnValue = m_DeviceID; } else { WARN_LOG(WII_IPC_FILEIO, "FileIO: Open (%s) failed - File doesn't exist %s", Modes[_Mode], m_filepath.c_str()); ReturnValue = FS_FILE_NOT_EXIST; } if (_CommandAddress) Memory::Write_U32(ReturnValue, _CommandAddress + 4); m_Active = true; return GetDefaultReply(); }
IPCCommandResult CWII_IPC_HLE_Device_hid::Open(u32 _CommandAddress, u32 _Mode) { DEBUG_LOG(WII_IPC_HID, "HID::Open"); m_Active = true; Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); return GetDefaultReply(); }
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress) { u32 ReturnValue = FS_EACCESS; const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Write data from this memory address const u32 Size = Memory::Read_U32(_CommandAddress + 0x10); if (m_file->IsOpen()) { if (m_Mode == ISFS_OPEN_READ) { WARN_LOG(WII_IPC_FILEIO, "FileIO: Attempted to write 0x%x bytes from 0x%08x to a read-only file %s", Size, Address, m_Name.c_str()); } else { INFO_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", Size, Address, m_Name.c_str()); m_file->Seek(m_SeekPos, SEEK_SET); // File might be opened twice, need to seek before we write if (m_file->WriteBytes(Memory::GetPointer(Address), Size)) { ReturnValue = Size; m_SeekPos += Size; } } } else { ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could not be opened or does not exist", m_Name.c_str(), Address, Size); ReturnValue = FS_FILE_NOT_EXIST; } Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); return GetDefaultReply(); }
IPCCommandResult FileIO::Write(const ReadWriteRequest& request) { s32 return_value = FS_EACCESS; if (m_file->IsOpen()) { if (m_Mode == IOS_OPEN_READ) { WARN_LOG(IOS_FILEIO, "FileIO: Attempted to write 0x%x bytes from 0x%08x to a read-only file %s", request.size, request.buffer, m_name.c_str()); } else { DEBUG_LOG(IOS_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", request.size, request.buffer, m_name.c_str()); m_file->Seek(m_SeekPos, SEEK_SET); // File might be opened twice, need to seek before we write if (m_file->WriteBytes(Memory::GetPointer(request.buffer), request.size)) { return_value = request.size; m_SeekPos += request.size; } } } else { ERROR_LOG(IOS_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could " "not be opened or does not exist", m_name.c_str(), request.buffer, request.size); return_value = FS_ENOENT; } return GetDefaultReply(return_value); }
IPCCommandResult SDIOSlot0::IOCtl(const IOCtlRequest& request) { Memory::Memset(request.buffer_out, 0, request.buffer_out_size); switch (request.request) { case IOCTL_WRITEHCR: return WriteHCRegister(request); case IOCTL_READHCR: return ReadHCRegister(request); case IOCTL_RESETCARD: return ResetCard(request); case IOCTL_SETCLK: return SetClk(request); case IOCTL_SENDCMD: return SendCommand(request); case IOCTL_GETSTATUS: return GetStatus(request); case IOCTL_GETOCR: return GetOCRegister(request); default: ERROR_LOG(IOS_SD, "Unknown SD IOCtl command (0x%08x)", request.request); break; } return GetDefaultReply(IPC_SUCCESS); }
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress) { // PPC sending commands SIOCtlVBuffer CommandBuffer(_CommandAddress); // Prepare the out buffer(s) with zeros as a safety precaution // to avoid returning bad values for (const auto& buffer : CommandBuffer.PayloadBuffer) Memory::Memset(buffer.m_Address, 0, buffer.m_Size); u32 ReturnValue = 0; switch (CommandBuffer.Parameter) { case IOCTLV_SENDCMD: DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address)); ReturnValue = ExecuteCommand( CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size, CommandBuffer.InBuffer[1].m_Address, CommandBuffer.InBuffer[1].m_Size, CommandBuffer.PayloadBuffer[0].m_Address, CommandBuffer.PayloadBuffer[0].m_Size); break; default: ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", CommandBuffer.Parameter); break; } // DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, // CommandBuffer.NumberPayloadBuffer, LogTypes::WII_IPC_SD); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); return GetDefaultReply(); }