diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2018-12-01 00:16:32 +0100 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2018-12-02 21:59:37 +0100 |
commit | 622fe621a2e7f431f7dc5dcdfd30d56af00de0ae (patch) | |
tree | 4e700daaf20366cd8358f4411b99bcf3dfb22e48 /lib/efi_loader | |
parent | 0fdb9e30b325f52422fe9cf5e4c9d060a6d33562 (diff) |
efi_loader: correctly aligned transmit buffer
Calling net_send_packet() requires that the buffer is aligned to a multiple
of PKTALIGN (= ARCH_DMA_MINALIGN). The UEFI spec does not require
efi_net_transmit() to be called with a buffer with any special alignment.
So we have to copy to an aligned buffer. The current coding copies to an
aligned buffer only if CONFIG_EFI_LOADER_BOUNCE_BUFFER=y. Many boards
like the Odroid C2 do not use a bounce buffer.
With the patch we copy to a correctly aligned buffer in all cases.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/efi_net.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index a64c603ed3e..68ed9e9520c 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -14,6 +14,8 @@ static const efi_guid_t efi_pxe_guid = EFI_PXE_GUID; static struct efi_pxe_packet *dhcp_ack; static bool new_rx_packet; static void *new_tx_packet; +static void *transmit_buffer; + /* * The notification function of this event is called in every timer cycle * to check if a new network packet has been received. @@ -198,13 +200,11 @@ static efi_status_t EFIAPI efi_net_transmit(struct efi_simple_network *this, return EFI_EXIT(EFI_INVALID_PARAMETER); } -#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER - /* Ethernet packets always fit, just bounce */ - memcpy(efi_bounce_buffer, buffer, buffer_size); - net_send_packet(efi_bounce_buffer, buffer_size); -#else - net_send_packet(buffer, buffer_size); -#endif + /* Ensure that the packet fits into the buffer */ + if (buffer_size > PKTSIZE_ALIGN) + return EFI_EXIT(EFI_INVALID_PARAMETER); + memcpy(transmit_buffer, buffer, buffer_size); + net_send_packet(transmit_buffer, buffer_size); new_tx_packet = buffer; @@ -325,10 +325,14 @@ efi_status_t efi_net_register(void) /* We only expose the "active" network device, so one is enough */ netobj = calloc(1, sizeof(*netobj)); - if (!netobj) { - printf("ERROR: Out of memory\n"); - return EFI_OUT_OF_RESOURCES; - } + if (!netobj) + goto out_of_resources; + + /* Allocate an aligned transmit buffer */ + transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN); + if (!transmit_buffer) + goto out_of_resources; + transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN); /* Hook net up to the device list */ efi_add_handle(&netobj->header); @@ -408,4 +412,9 @@ efi_status_t efi_net_register(void) failure_to_add_protocol: printf("ERROR: Failure to add protocol\n"); return r; +out_of_resources: + free(netobj); + /* free(transmit_buffer) not needed yet */ + printf("ERROR: Out of memory\n"); + return EFI_OUT_OF_RESOURCES; } |