summaryrefslogtreecommitdiffstats
path: root/src/interface/efi
diff options
context:
space:
mode:
authorMichael Brown2017-09-07 00:56:22 +0200
committerMichael Brown2017-09-07 00:56:22 +0200
commite8f30571a375777fc83c14602f9ed32ac26eedb4 (patch)
treecca0a26dedd34c2414f4d43bfaa7e5bc417bf7bf /src/interface/efi
parent[efi] Check buffer length for packets retrieved via our SNP protocol (diff)
downloadipxe-e8f30571a375777fc83c14602f9ed32ac26eedb4.tar.gz
ipxe-e8f30571a375777fc83c14602f9ed32ac26eedb4.tar.xz
ipxe-e8f30571a375777fc83c14602f9ed32ac26eedb4.zip
[efi] Match behaviour of SnpDxe for truncated received packets
The UEFI specification does not state whether or not a return value of EFI_BUFFER_TOO_SMALL from the SNP Receive() method should follow the usual EFI API behaviour of allowing the caller to retry the request with an increased buffer size. Examination of the SnpDxe driver in EDK2 suggests that Receive() will just return the truncated packet (complete with any requested link-layer header fields), so match this behaviour. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi')
-rw-r--r--src/interface/efi/efi_snp.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
index 5c3592e5..263a25ac 100644
--- a/src/interface/efi/efi_snp.c
+++ b/src/interface/efi/efi_snp.c
@@ -710,7 +710,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
const void *iob_ll_src;
uint16_t iob_net_proto;
unsigned int iob_flags;
- size_t max_len;
+ size_t copy_len;
int rc;
DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
@@ -732,19 +732,15 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
}
DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
- /* Check buffer length */
- max_len = *len;
- *len = iob_len ( iobuf );
- if ( *len > max_len ) {
- rc = -ERANGE;
- goto out_too_long;
- }
-
/* Dequeue packet */
list_del ( &iobuf->list );
- /* Return packet to caller */
- memcpy ( data, iobuf->data, iob_len ( iobuf ) );
+ /* Return packet to caller, truncating to buffer length */
+ copy_len = iob_len ( iobuf );
+ if ( copy_len > *len )
+ copy_len = *len;
+ memcpy ( data, iobuf->data, copy_len );
+ *len = iob_len ( iobuf );
/* Attempt to decode link-layer header */
if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
@@ -765,11 +761,11 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
if ( net_proto )
*net_proto = ntohs ( iob_net_proto );
- rc = 0;
+ /* Check buffer length */
+ rc = ( ( copy_len == *len ) ? 0 : -ERANGE );
out_bad_ll_header:
free_iob ( iobuf );
- out_too_long:
out_no_packet:
return EFIRC ( rc );
}