From b0d2533fb298651f5cccc828d496558c787fadd5 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Tue, 2 Feb 2016 10:39:18 +0000 Subject: [PATCH] Add suppor to loader.efi to load files off hte network. For this we need to open the device in exclusive mode as, without this, the firmware may also be reading packets off the interface leading to a race. Reviewed by: emaste Sponsored by: ABT Systems Ltd Differential Revision: https://reviews.freebsd.org/D4132 --- sys/boot/efi/libefi/efinet.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index f1e614331999..d9ecdcc45f1c 100644 --- a/sys/boot/efi/libefi/efinet.c +++ b/sys/boot/efi/libefi/efinet.c @@ -184,11 +184,16 @@ efinet_init(struct iodesc *desc, void *machdep_hint) EFI_HANDLE h; EFI_STATUS status; + if (nif->nif_driver->netif_ifs[nif->nif_unit].dif_unit < 0) { + printf("Invalid network interface %d\n", nif->nif_unit); + return; + } + h = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private; status = BS->HandleProtocol(h, &sn_guid, (VOID **)&nif->nif_devdata); if (status != EFI_SUCCESS) { - printf("net%d: cannot start interface (status=%ld)\n", - nif->nif_unit, (long)status); + printf("net%d: cannot start interface (status=%lu)\n", + nif->nif_unit, EFI_ERROR_CODE(status)); return; } @@ -288,11 +293,30 @@ efinet_dev_init() stats = calloc(nifs, sizeof(struct netif_stats)); for (i = 0; i < nifs; i++) { + EFI_SIMPLE_NETWORK *net; + EFI_HANDLE h; + dif = &efinetif.netif_ifs[i]; + dif->dif_unit = -1; + + h = efi_find_handle(&efinet_dev, i); + + /* + * Open the network device in exclusive mode. Without this + * we will be racing with the UEFI network stack. It will + * pull packets off the network leading to lost packets. + */ + status = BS->OpenProtocol(h, &sn_guid, (void **)&net, + IH, 0, EFI_OPEN_PROTOCOL_EXCLUSIVE); + if (status != EFI_SUCCESS) { + printf("Unable to open network interface %d\n", i); + continue; + } + dif->dif_unit = i; dif->dif_nsel = 1; dif->dif_stats = &stats[i]; - dif->dif_private = efi_find_handle(&efinet_dev, i); + dif->dif_private = h; } return (0);