summaryrefslogtreecommitdiff
path: root/lib/efi_loader
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2018-12-01 00:16:32 +0100
committerAlexander Graf <agraf@suse.de>2018-12-02 21:59:37 +0100
commit622fe621a2e7f431f7dc5dcdfd30d56af00de0ae (patch)
tree4e700daaf20366cd8358f4411b99bcf3dfb22e48 /lib/efi_loader
parent0fdb9e30b325f52422fe9cf5e4c9d060a6d33562 (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.c31
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;
}