]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Support the EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE operation 1637/head
authorMichael Brown <mcb30@ipxe.org>
Wed, 25 Feb 2026 00:25:03 +0000 (00:25 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 25 Feb 2026 00:25:03 +0000 (00:25 +0000)
Support getting the size of a TFTP file via the EFI PXE API, as
required for booting OpenBSD.

Debugged-by: Eric Radman <ericshane@eradman.com>
Tested-by: Eric Radman <ericshane@eradman.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/interface/efi/efi_pxe.c

index 2d1a6fd73a6d15a54bee5abf0b56d19332eef750..702d4d4f8e8de428b517cc01e27402f55a800730 100644 (file)
@@ -96,6 +96,8 @@ struct efi_pxe {
 
        /** (M)TFTP download interface */
        struct interface tftp;
+       /** Opcode */
+       unsigned int opcode;
        /** Block size (for TFTP) */
        size_t blksize;
        /** Overall return status */
@@ -354,11 +356,17 @@ static int efi_pxe_tftp_deliver ( struct efi_pxe *pxe,
        /* 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;
 }
@@ -908,7 +916,8 @@ efi_pxe_mtftp ( EFI_PXE_BASE_CODE_PROTOCOL *base,
 
        /* 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;
@@ -925,7 +934,12 @@ efi_pxe_mtftp ( EFI_PXE_BASE_CODE_PROTOCOL *base,
        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,
@@ -933,14 +947,18 @@ efi_pxe_mtftp ( EFI_PXE_BASE_CODE_PROTOCOL *base,
                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 );