/* Submit a bulk request to an endpoint */ int UhsSubmitBulkRequest(int uhs_handle, uint32_t if_handle, uint8_t endpoint, int direction, void *buffer, int length, int timeout) { /* Symbol loading */ unsigned int coreinit_handle; OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); void* (*memset)(void *buffer, int value, unsigned length); int (*IOS_Ioctlv)(int fd, int request, int cnt_in, int cnt_out, struct iovec *vecbuf); OSDynLoad_FindExport(coreinit_handle, false, "memset", &memset); OSDynLoad_FindExport(coreinit_handle, false, "IOS_Ioctlv", &IOS_Ioctlv); /* Allocate and fill in the request buffer */ char reqbuf[0xa1]; memset(&reqbuf[0], 0, sizeof(reqbuf)); *((uint32_t*)&reqbuf[0x00]) = if_handle; reqbuf[0x04] = endpoint; *((uint32_t*)&reqbuf[0x05]) = timeout; *((uint32_t*)&reqbuf[0x09]) = 3; *((uint32_t*)&reqbuf[0x0d]) = direction; *((uint32_t*)&reqbuf[0x11]) = length; /* Allocate and fill in the I/O vectors */ struct iovec vecbuf[2]; memset(&vecbuf[0], 0, sizeof(struct iovec) * 2); vecbuf[0].buffer = &reqbuf[0]; vecbuf[0].len = sizeof(reqbuf); vecbuf[1].buffer = buffer; vecbuf[1].len = length; /* Perform the ioctlv() request */ if (direction == ENDPOINT_TRANSFER_OUT) return IOS_Ioctlv(uhs_handle, 0xe, 0, 2, &vecbuf[0]); else if (direction == ENDPOINT_TRANSFER_IN) return IOS_Ioctlv(uhs_handle, 0xe, 1, 1, &vecbuf[0]); else return -1; }
int DIP::Open_Partition(unsigned int Offset, void* Ticket, void* Certificate, unsigned int Cert_Len, void* Out) { static ioctlv Vectors[5] __attribute__((aligned(0x20))); Command[0] = Ioctl::DI_OpenPartition << 24; Command[1] = Offset; Vectors[0].data = Command; Vectors[0].len = 0x20; Vectors[1].data = (Ticket == NULL) ? 0 : Ticket; Vectors[1].len = (Ticket == NULL) ? 0 : 0x2a4; Vectors[2].data = (Certificate == NULL) ? 0 : Certificate; Vectors[2].len = (Certificate == NULL) ? 0 : Cert_Len; Vectors[3].data = Out; Vectors[3].len = 0x49e4; Vectors[4].data = Output; Vectors[4].len = 0x20; Lock(); int Ret = IOS_Ioctlv(Device_Handle, Ioctl::DI_OpenPartition, 3, 2, Vectors); Unlock(); if (Ret == 2) throw "Ioctl error (DI_OpenPartition)"; return ((Ret == 1) ? 0 : -Ret); }
s32 WDVD_OpenPartition(u32 offset, u32 *IOS) { static u8 Tmd_Buffer[0x4A00] ATTRIBUTE_ALIGN(32); static ioctlv Vectors[5] ATTRIBUTE_ALIGN(32); s32 ret; memset(inbuf, 0, sizeof inbuf); memset(outbuf, 0, sizeof outbuf); inbuf[0] = IOCTL_DI_OPENPART << 24; inbuf[1] = offset; Vectors[0].data = inbuf; Vectors[0].len = 0x20; Vectors[1].data = 0; Vectors[1].len = 0; Vectors[2].data = 0; Vectors[2].len = 0; Vectors[3].data = Tmd_Buffer; Vectors[3].len = 0x49e4; Vectors[4].data = outbuf; Vectors[4].len = 0x20; ret = IOS_Ioctlv(di_fd, IOCTL_DI_OPENPART, 3, 2, (ioctlv *)Vectors); if(ret < 0) return ret; *IOS = (u32)(Tmd_Buffer[0x18b]); return (ret == 1) ? 0 : -ret; }
void tell_cIOS_to_return_to_channel(void) { if (TITLE_UPPER(old_title_id) > 1 && TITLE_LOWER(old_title_id) > 2) // Don't change anything for system menu or no title id { static u64 sm_title_id ATTRIBUTE_ALIGN(32); sm_title_id = old_title_id; // title id to be launched in place of the system menu int ret; static ioctlv vector[0x08] ATTRIBUTE_ALIGN(32); vector[0].data = &sm_title_id; vector[0].len = 8; int es_fd = IOS_Open("/dev/es", 0); if (es_fd < 0) { debug("Couldn't open ES module\n"); return; } ret = IOS_Ioctlv(es_fd, 0xA1, 1, 0, vector); debug ("tell_cIOS_to_return_to_channel = %d\n", ret); IOS_Close(es_fd); } }
static inline s32 __usb_interrupt_bulk_message(s32 fd,u8 ioctl,u8 bEndpoint,u16 wLength,void *rpData,usbcallback cb,void *usrdata) { s32 ret = IPC_ENOMEM; u8 *pEndP = NULL; u16 *pLength = NULL; ioctlv *vec = NULL; struct _usb_cb *msgcb = NULL; if(((s32)rpData%32)!=0) return IPC_EINVAL; if(wLength && !rpData) return IPC_EINVAL; if(!wLength && rpData) return IPC_EINVAL; vec = iosAlloc(hId,sizeof(ioctlv)*3); if(vec==NULL) return IPC_ENOMEM; pEndP = iosAlloc(hId,32); if(pEndP==NULL) goto done; *pEndP = bEndpoint; pLength = iosAlloc(hId,32); if(pLength==NULL) goto done; *pLength = wLength; vec[0].data = pEndP; vec[0].len = sizeof(u8); vec[1].data = pLength; vec[1].len = sizeof(u16); vec[2].data = rpData; vec[2].len = wLength; if(cb==NULL) ret = IOS_Ioctlv(fd,ioctl,2,1,vec); else { msgcb = iosAlloc(hId,sizeof(struct _usb_cb)); if(msgcb==NULL) goto done; msgcb->fd = -1; msgcb->cb = cb; msgcb->usrdata = usrdata; msgcb->vec = vec; return IOS_IoctlvAsync(fd,ioctl,2,1,vec,__usb_bulk_messageCB,msgcb); } done: if(pLength!=NULL) iosFree(hId,pLength); if(pEndP!=NULL) iosFree(hId,pEndP); if(vec!=NULL) iosFree(hId,vec); return ret; }
/* Submit a control request to endpoint 0 */ int UhsSubmitControlRequest(int uhs_handle, uint32_t if_handle, void *buffer, uint8_t bRequest, uint8_t bmRequestType, uint16_t wValue, uint16_t wIndex, uint16_t wLength, int timeout) { /* Symbol loading */ unsigned int coreinit_handle; OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); void* (*memset)(void *buffer, int value, unsigned length); int (*IOS_Ioctlv)(int fd, int request, int cnt_in, int cnt_out, struct iovec *vecbuf); OSDynLoad_FindExport(coreinit_handle, false, "memset", &memset); OSDynLoad_FindExport(coreinit_handle, false, "IOS_Ioctlv", &IOS_Ioctlv); /* Allocate and fill in the request buffer */ uint8_t reqbuf[0xa1]; memset(&reqbuf[0], 0, sizeof(reqbuf)); *((uint32_t*)&reqbuf[0x00]) = if_handle; reqbuf[0x04] = 0; /* Endpoint 0 */ *((uint32_t*)&reqbuf[0x05]) = timeout; *((uint32_t*)&reqbuf[0x09]) = 1; /* Transfer type */ reqbuf[0x0d] = bRequest; reqbuf[0x0e] = bmRequestType; *((uint16_t*)&reqbuf[0x0f]) = wValue; *((uint16_t*)&reqbuf[0x11]) = wIndex; *((uint16_t*)&reqbuf[0x13]) = wLength; /* Allocate and fill in the I/O vectors */ struct iovec vecbuf[2]; memset(&vecbuf[0], 0, sizeof(struct iovec) * 2); vecbuf[0].buffer = &reqbuf[0]; vecbuf[0].len = sizeof(reqbuf); vecbuf[0].unknown8[3] = 1; vecbuf[1].buffer = buffer; vecbuf[1].len = (int)wLength; vecbuf[1].unknown8[3] = 1; /* Perform the ioctlv() request */ if (bmRequestType & (1 << 7)) return IOS_Ioctlv(uhs_handle, 0xc, 1, 1, &vecbuf[0]); else return IOS_Ioctlv(uhs_handle, 0xc, 0, 2, &vecbuf[0]); }
s32 Nand_Unmount(nandDevice *dev) { s32 fd, ret; /* Open FAT module */ fd = IOS_Open("fat", 0); if (fd < 0) return fd; /* Unmount device */ ret = IOS_Ioctlv(fd, dev->umountCmd, 0, 0, NULL); /* Close FAT module */ IOS_Close(fd); return ret; }
s32 DVDClose( s32 fd ) { s32 DVDHandle = IOS_Open("/dev/di", 0 ); if( DVDHandle < 0 ) return DVDHandle; vector *v = (vector*)malloca( sizeof(vector), 32 ); v[0].data = fd; v[0].len = sizeof(u32); s32 r = IOS_Ioctlv( DVDHandle, DVD_CLOSE, 1, 0, v ); free( v ); IOS_Close( DVDHandle ); return r; }
s32 Nand_Mount(nandDevice *dev) { s32 fd, ret; /* Open FAT module */ fd = IOS_Open("fat", 0); if (fd < 0) return fd; // TODO Tell the cIOS which partition to use /* Mount device */ ret = IOS_Ioctlv(fd, dev->mountCmd, 0, 0, NULL); /* Close FAT module */ IOS_Close(fd); return ret; }
s32 BlockIOSReload(void) { /* Open ES Module */ s32 ESHandle = IOS_Open("/dev/es", 0); /* IOS Reload Block */ static ioctlv block_vector[2] ATTRIBUTE_ALIGN(32); static u32 mode ATTRIBUTE_ALIGN(32); static u32 ios ATTRIBUTE_ALIGN(32); mode = 2; block_vector[0].data = &mode; block_vector[0].len = sizeof(u32); ios = IOS_GetVersion(); block_vector[1].data = &ios; block_vector[1].len = sizeof(u32); s32 ret = IOS_Ioctlv(ESHandle, 0xA0, 2, 0, block_vector); /* Close ES Module */ IOS_Close(ESHandle); return ret; }
s32 DVDWrite( s32 fd, void *ptr, u32 len ) { s32 DVDHandle = IOS_Open("/dev/di", 0 ); if( DVDHandle < 0 ) return DVDHandle; vector *v = (vector*)malloca( sizeof(vector)*2, 32 ); v[0].data = fd; v[0].len = sizeof(u32); v[1].data = (u32)ptr; v[1].len = len; s32 r = IOS_Ioctlv( DVDHandle, DVD_WRITE, 2, 0, v ); free( v ); IOS_Close( DVDHandle ); return r; }
s32 WDVD_OpenPartition(u64 offset) { u8 *vector = NULL; //u32 *buffer = NULL; s32 ret; //gprintf( "%s %i\n", __FILE__, __LINE__ ); //buffer = (u32 *)memalign(32, 0x5000); // if (!buffer) // return -1; //gprintf( "%s %i\n", __FILE__, __LINE__ ); vector = (u8 *)wdvd_buffer; memset(wdvd_buffer, 0, 0x5000); wdvd_buffer[0] = (u32)(wdvd_buffer + 0x10); wdvd_buffer[1] = 0x20; wdvd_buffer[3] = 0x024A; wdvd_buffer[6] = (u32)(wdvd_buffer + 0x380); wdvd_buffer[7] = 0x49E4; wdvd_buffer[8] = (u32)(wdvd_buffer + 0x360); wdvd_buffer[9] = 0x20; wdvd_buffer[(0x40 >> 2)] = IOCTL_DI_OPENPART << 24; wdvd_buffer[(0x40 >> 2) + 1] = offset >> 2; //gprintf( "%s %i\n", __FILE__, __LINE__ ); ret = IOS_Ioctlv(di_fd, IOCTL_DI_OPENPART, 3, 2, (ioctlv *)vector); //free(buffer); //gprintf( "%s %i\n", __FILE__, __LINE__ ); if (ret < 0) return ret; return (ret == 1) ? 0 : -ret; }
s32 DVDCreateDir( char *FileName ) { s32 fd = IOS_Open("/dev/di", 0 ); if( fd < 0 ) return fd; vector *v = (vector*)malloca( sizeof(vector), 32 ); char *lFileName = (char*)malloca( strlen(FileName), 32 ); strcpy( lFileName, FileName ); v[0].data = (u32)lFileName; v[0].len = strlen(lFileName); s32 r = IOS_Ioctlv( fd, DVD_CREATEDIR, 1, 0, v ); free( lFileName ); free( v ); IOS_Close( fd ); return r; }
MCPError MCP_GetSysProdSettings(IOSHandle handle, MCPSysProdSettings *settings) { if (!settings) { return MCPError::InvalidArg; } auto message = internal::mcpAllocateMessage(sizeof(IOSVec)); if (!message) { return MCPError::AllocError; } auto outVec = reinterpret_cast<IOSVec *>(message); outVec->paddr = settings; outVec->len = sizeof(MCPSysProdSettings); auto iosError = IOS_Ioctlv(handle, MCPCommand::GetSysProdSettings, 0, 1, outVec); auto mcpError = internal::mcpDecodeIosErrorToMcpError(iosError); internal::mcpFreeMessage(message); return mcpError; }
static inline s32 __usb_control_message(s32 fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData,usbcallback cb,void *usrdata) { s32 ret = IPC_ENOMEM; u8 *pRqType = NULL; u8 *pRq = NULL; u8 *pNull = NULL; u16 *pValue = NULL; u16 *pIndex = NULL; u16 *pLength = NULL; ioctlv *vec = NULL; struct _usb_cb *msgcb = NULL; if(((s32)rpData%32)!=0) return IPC_EINVAL; if(wLength && !rpData) return IPC_EINVAL; if(!wLength && rpData) return IPC_EINVAL; vec = iosAlloc(hId,sizeof(ioctlv)*7); if(vec==NULL) return IPC_ENOMEM; pRqType = iosAlloc(hId,32); if(pRqType==NULL) goto done; *pRqType = bmRequestType; pRq = iosAlloc(hId,32); if(pRq==NULL) goto done; *pRq = bmRequest; pValue = iosAlloc(hId,32); if(pValue==NULL) goto done; *pValue = bswap16(wValue); pIndex = iosAlloc(hId,32); if(pIndex==NULL) goto done; *pIndex = bswap16(wIndex); pLength = iosAlloc(hId,32); if(pLength==NULL) goto done; *pLength = bswap16(wLength); pNull = iosAlloc(hId,32); if(pNull==NULL) goto done; *pNull = 0; vec[0].data = pRqType; vec[0].len = sizeof(u8); vec[1].data = pRq; vec[1].len = sizeof(u8); vec[2].data = pValue; vec[2].len = sizeof(u16); vec[3].data = pIndex; vec[3].len = sizeof(u16); vec[4].data = pLength; vec[4].len = sizeof(u16); vec[5].data = pNull; vec[5].len = sizeof(u8); vec[6].data = rpData; vec[6].len = wLength; if(cb==NULL) ret = IOS_Ioctlv(fd,USB_IOCTL_CTRLMSG,6,1,vec); else { msgcb = iosAlloc(hId,sizeof(struct _usb_cb)); if(msgcb==NULL) goto done; msgcb->fd = -1; msgcb->cb = cb; msgcb->usrdata = usrdata; msgcb->vec = vec; return IOS_IoctlvAsync(fd,USB_IOCTL_CTRLMSG,6,1,vec,__usb_control_messageCB,msgcb); } done: if(pNull!=NULL) iosFree(hId,pNull); if(pLength!=NULL) iosFree(hId,pLength); if(pIndex!=NULL) iosFree(hId,pIndex); if(pValue!=NULL) iosFree(hId,pValue); if(pRq!=NULL) iosFree(hId,pRq); if(pRqType!=NULL) iosFree(hId,pRqType); if(vec!=NULL) iosFree(hId,vec); return ret; }
UCError UCReadSysConfig(UCHandle handle, uint32_t count, phys_ptr<UCSysConfig> settings) { phys_ptr<void> vecBuffer = nullptr; phys_ptr<void> reqBuffer = nullptr; phys_ptr<UCReadSysConfigRequest> request = nullptr; phys_ptr<IoctlVec> vecs = nullptr; auto vecBufSize = static_cast<uint32_t>((1 + count) * sizeof(IoctlVec)); auto reqBufSize = static_cast<uint32_t>(count * sizeof(UCSysConfig) + sizeof(UCReadSysConfigRequest)); auto error = allocIpcData(vecBufSize, &vecBuffer); if (error < UCError::OK) { goto out; } error = allocIpcData(reqBufSize, &reqBuffer); if (error < UCError::OK) { goto out; } request = phys_cast<UCReadSysConfigRequest *>(reqBuffer); request->unk0x00 = 0u; request->count = count; std::memcpy(request->settings, settings.get(), sizeof(UCSysConfig) * count); vecs = phys_cast<IoctlVec *>(vecBuffer); vecs[0].len = reqBufSize; vecs[0].paddr = phys_cast<phys_addr>(reqBuffer); for (auto i = 0u; i < count; ++i) { auto size = settings[i].dataSize; vecs[1 + i].len = size; if (size) { phys_ptr<void> dataBuffer; error = allocIpcData(vecBufSize, &dataBuffer); if (error < UCError::OK) { goto out; } vecs[1 + i].paddr = phys_cast<phys_addr>(dataBuffer); } else { vecs[1 + i].paddr = phys_addr { 0u }; } } error = static_cast<UCError>(IOS_Ioctlv(handle, UCCommand::ReadSysConfig, 0, 1 + count, vecs)); for (auto i = 0u; i < count; ++i) { settings[i].error = request->settings[i].error; if (auto len = vecs[i + 1].len) { auto dst = phys_cast<void *>(phys_addr { virt_cast<virt_addr>(settings[i].data).getAddress() }); auto src = phys_cast<const void *>(vecs[i + 1].paddr); std::memcpy(dst.get(), src.get(), len); } } out: for (auto i = 0u; i < count; ++i) { if (vecs[i + 1].paddr) { freeIpcData(phys_cast<void *>(vecs[i + 1].paddr)); } } if (vecBuffer) { freeIpcData(vecBuffer); } if (reqBuffer) { freeIpcData(reqBuffer); } return error; }