/** (M)TFTP download interface */
struct interface tftp;
+ /** Opcode */
+ unsigned int opcode;
/** Block size (for TFTP) */
size_t blksize;
/** Overall return status */
/* Deliver to data transfer buffer */
if ( ( rc = xferbuf_deliver ( &pxe->buf, iob_disown ( iobuf ),
meta ) ) != 0 )
- goto err_deliver;
+ goto done;
+
+ /* Stop when filesize is known, if applicable */
+ if ( ( pxe->opcode == EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE ) &&
+ ( meta->flags & XFER_FL_ABS_OFFSET ) ) {
+ goto done;
+ }
return 0;
- err_deliver:
+ done:
efi_pxe_tftp_close ( pxe, rc );
return rc;
}
/* Fail unless operation is supported */
if ( ! ( ( opcode == EFI_PXE_BASE_CODE_TFTP_READ_FILE ) ||
- ( opcode == EFI_PXE_BASE_CODE_MTFTP_READ_FILE ) ) ) {
+ ( opcode == EFI_PXE_BASE_CODE_MTFTP_READ_FILE ) ||
+ ( opcode == EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE ) ) ) {
DBGC ( pxe, "PXE %s unsupported MTFTP opcode %d\n",
pxe->name, opcode );
rc = -ENOTSUP;
pxe->blksize = ( ( callback && blksize ) ? *blksize : -1UL );
/* Initialise data transfer buffer */
- xferbuf_fixed_init ( &pxe->buf, data, *len );
+ memset ( &pxe->buf, 0, sizeof ( pxe->buf ) );
+ if ( opcode == EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE ) {
+ xferbuf_void_init ( &pxe->buf );
+ } else {
+ xferbuf_fixed_init ( &pxe->buf, data, *len );
+ }
/* Open download */
if ( ( rc = efi_pxe_tftp_open ( pxe, ip,
goto err_open;
/* Wait for download to complete */
+ pxe->opcode = opcode;
pxe->rc = -EINPROGRESS;
while ( pxe->rc == -EINPROGRESS )
step();
+ *len = pxe->buf.max;
if ( ( rc = pxe->rc ) != 0 ) {
- DBGC ( pxe, "PXE %s download failed: %s\n",
- pxe->name, strerror ( rc ) );
+ DBGC ( pxe, "PXE %s MTFTP %d failed: %s\n",
+ pxe->name, opcode, strerror ( rc ) );
goto err_download;
}
+ DBGC ( pxe, "PXE %s MTFTP %d %p+%llx complete\n",
+ pxe->name, opcode, data, *len );
err_download:
efi_pxe_tftp_close ( pxe, rc );