Home | History | Annotate | Line # | Download | only in efiboot
efinet.c revision 1.3.2.3
      1  1.3.2.3  pgoyette /*	$NetBSD: efinet.c,v 1.3.2.3 2018/11/26 01:52:52 pgoyette Exp $	*/
      2  1.3.2.2  pgoyette 
      3  1.3.2.2  pgoyette /*-
      4  1.3.2.2  pgoyette  * Copyright (c) 2001 Doug Rabson
      5  1.3.2.2  pgoyette  * Copyright (c) 2002, 2006 Marcel Moolenaar
      6  1.3.2.2  pgoyette  * All rights reserved.
      7  1.3.2.2  pgoyette  *
      8  1.3.2.2  pgoyette  * Redistribution and use in source and binary forms, with or without
      9  1.3.2.2  pgoyette  * modification, are permitted provided that the following conditions
     10  1.3.2.2  pgoyette  * are met:
     11  1.3.2.2  pgoyette  * 1. Redistributions of source code must retain the above copyright
     12  1.3.2.2  pgoyette  *    notice, this list of conditions and the following disclaimer.
     13  1.3.2.2  pgoyette  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.3.2.2  pgoyette  *    notice, this list of conditions and the following disclaimer in the
     15  1.3.2.2  pgoyette  *    documentation and/or other materials provided with the distribution.
     16  1.3.2.2  pgoyette  *
     17  1.3.2.2  pgoyette  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     18  1.3.2.2  pgoyette  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  1.3.2.2  pgoyette  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  1.3.2.2  pgoyette  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  1.3.2.2  pgoyette  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  1.3.2.2  pgoyette  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  1.3.2.2  pgoyette  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  1.3.2.2  pgoyette  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  1.3.2.2  pgoyette  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  1.3.2.2  pgoyette  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  1.3.2.2  pgoyette  * SUCH DAMAGE.
     28  1.3.2.2  pgoyette  */
     29  1.3.2.2  pgoyette 
     30  1.3.2.2  pgoyette #include <sys/cdefs.h>
     31  1.3.2.2  pgoyette #include <sys/param.h>
     32  1.3.2.2  pgoyette 
     33  1.3.2.2  pgoyette #include "efiboot.h"
     34  1.3.2.2  pgoyette 
     35  1.3.2.2  pgoyette #include <lib/libsa/net.h>
     36  1.3.2.2  pgoyette #include <lib/libsa/netif.h>
     37  1.3.2.2  pgoyette #include <lib/libsa/dev_net.h>
     38  1.3.2.2  pgoyette 
     39  1.3.2.2  pgoyette #include "devopen.h"
     40  1.3.2.2  pgoyette 
     41  1.3.2.2  pgoyette #ifndef ETHER_ALIGN
     42  1.3.2.2  pgoyette #define ETHER_ALIGN	2
     43  1.3.2.2  pgoyette #endif
     44  1.3.2.2  pgoyette 
     45  1.3.2.2  pgoyette #define ETHER_EXT_LEN	(ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_ALIGN)
     46  1.3.2.2  pgoyette 
     47  1.3.2.2  pgoyette #if defined(DEBUG) || defined(ARP_DEBUG) || defined(BOOTP_DEBUG) || \
     48  1.3.2.2  pgoyette     defined(NET_DEBUG) || defined(NETIF_DEBUG) || defined(NFS_DEBUG) || \
     49  1.3.2.2  pgoyette     defined(RARP_DEBUG) || defined(RPC_DEBUG)
     50  1.3.2.2  pgoyette int debug = 1;
     51  1.3.2.2  pgoyette #else
     52  1.3.2.2  pgoyette int debug = 0;
     53  1.3.2.2  pgoyette #endif
     54  1.3.2.2  pgoyette 
     55  1.3.2.2  pgoyette extern bool kernel_loaded;
     56  1.3.2.2  pgoyette 
     57  1.3.2.2  pgoyette struct efinetinfo {
     58  1.3.2.2  pgoyette 	EFI_SIMPLE_NETWORK *net;
     59  1.3.2.2  pgoyette 	bool bootdev;
     60  1.3.2.2  pgoyette 	size_t pktbufsz;
     61  1.3.2.2  pgoyette 	UINT8 *pktbuf;
     62  1.3.2.2  pgoyette 	struct {
     63  1.3.2.2  pgoyette 		int type;
     64  1.3.2.2  pgoyette 		u_int tag;
     65  1.3.2.2  pgoyette 	} bus;
     66  1.3.2.2  pgoyette };
     67  1.3.2.2  pgoyette #if notyet
     68  1.3.2.2  pgoyette static struct btinfo_netif bi_netif;
     69  1.3.2.2  pgoyette #endif
     70  1.3.2.2  pgoyette 
     71  1.3.2.2  pgoyette static int	efinet_match(struct netif *, void *);
     72  1.3.2.2  pgoyette static int	efinet_probe(struct netif *, void *);
     73  1.3.2.2  pgoyette static void	efinet_init(struct iodesc *, void *);
     74  1.3.2.2  pgoyette static int	efinet_get(struct iodesc *, void *, size_t, saseconds_t);
     75  1.3.2.2  pgoyette static int	efinet_put(struct iodesc *, void *, size_t);
     76  1.3.2.2  pgoyette static void	efinet_end(struct netif *);
     77  1.3.2.2  pgoyette 
     78  1.3.2.2  pgoyette struct netif_driver efinetif = {
     79  1.3.2.2  pgoyette 	.netif_bname = "net",
     80  1.3.2.2  pgoyette 	.netif_match = efinet_match,
     81  1.3.2.2  pgoyette 	.netif_probe = efinet_probe,
     82  1.3.2.2  pgoyette 	.netif_init = efinet_init,
     83  1.3.2.2  pgoyette 	.netif_get = efinet_get,
     84  1.3.2.2  pgoyette 	.netif_put = efinet_put,
     85  1.3.2.2  pgoyette 	.netif_end = efinet_end,
     86  1.3.2.2  pgoyette 	.netif_ifs = NULL,
     87  1.3.2.2  pgoyette 	.netif_nifs = 0
     88  1.3.2.2  pgoyette };
     89  1.3.2.2  pgoyette 
     90  1.3.2.2  pgoyette #ifdef EFINET_DEBUG
     91  1.3.2.2  pgoyette static void
     92  1.3.2.2  pgoyette dump_mode(EFI_SIMPLE_NETWORK_MODE *mode)
     93  1.3.2.2  pgoyette {
     94  1.3.2.2  pgoyette 	int i;
     95  1.3.2.2  pgoyette 
     96  1.3.2.2  pgoyette 	printf("State                 = %x\n", mode->State);
     97  1.3.2.2  pgoyette 	printf("HwAddressSize         = %u\n", mode->HwAddressSize);
     98  1.3.2.2  pgoyette 	printf("MediaHeaderSize       = %u\n", mode->MediaHeaderSize);
     99  1.3.2.2  pgoyette 	printf("MaxPacketSize         = %u\n", mode->MaxPacketSize);
    100  1.3.2.2  pgoyette 	printf("NvRamSize             = %u\n", mode->NvRamSize);
    101  1.3.2.2  pgoyette 	printf("NvRamAccessSize       = %u\n", mode->NvRamAccessSize);
    102  1.3.2.2  pgoyette 	printf("ReceiveFilterMask     = %x\n", mode->ReceiveFilterMask);
    103  1.3.2.2  pgoyette 	printf("ReceiveFilterSetting  = %u\n", mode->ReceiveFilterSetting);
    104  1.3.2.2  pgoyette 	printf("MaxMCastFilterCount   = %u\n", mode->MaxMCastFilterCount);
    105  1.3.2.2  pgoyette 	printf("MCastFilterCount      = %u\n", mode->MCastFilterCount);
    106  1.3.2.2  pgoyette 	printf("MCastFilter           = {");
    107  1.3.2.2  pgoyette 	for (i = 0; i < mode->MCastFilterCount; i++)
    108  1.3.2.2  pgoyette 		printf(" %s", ether_sprintf(mode->MCastFilter[i].Addr));
    109  1.3.2.2  pgoyette 	printf(" }\n");
    110  1.3.2.2  pgoyette 	printf("CurrentAddress        = %s\n",
    111  1.3.2.2  pgoyette 	    ether_sprintf(mode->CurrentAddress.Addr));
    112  1.3.2.2  pgoyette 	printf("BroadcastAddress      = %s\n",
    113  1.3.2.2  pgoyette 	    ether_sprintf(mode->BroadcastAddress.Addr));
    114  1.3.2.2  pgoyette 	printf("PermanentAddress      = %s\n",
    115  1.3.2.2  pgoyette 	    ether_sprintf(mode->PermanentAddress.Addr));
    116  1.3.2.2  pgoyette 	printf("IfType                = %u\n", mode->IfType);
    117  1.3.2.2  pgoyette 	printf("MacAddressChangeable  = %d\n", mode->MacAddressChangeable);
    118  1.3.2.2  pgoyette 	printf("MultipleTxSupported   = %d\n", mode->MultipleTxSupported);
    119  1.3.2.2  pgoyette 	printf("MediaPresentSupported = %d\n", mode->MediaPresentSupported);
    120  1.3.2.2  pgoyette 	printf("MediaPresent          = %d\n", mode->MediaPresent);
    121  1.3.2.2  pgoyette }
    122  1.3.2.2  pgoyette #endif
    123  1.3.2.2  pgoyette 
    124  1.3.2.2  pgoyette static int
    125  1.3.2.2  pgoyette efinet_match(struct netif *nif, void *machdep_hint)
    126  1.3.2.2  pgoyette {
    127  1.3.2.2  pgoyette 	struct devdesc *dev = machdep_hint;
    128  1.3.2.2  pgoyette 
    129  1.3.2.2  pgoyette 	if (dev->d_unit != nif->nif_unit)
    130  1.3.2.2  pgoyette 		return 0;
    131  1.3.2.2  pgoyette 
    132  1.3.2.2  pgoyette 	return 1;
    133  1.3.2.2  pgoyette }
    134  1.3.2.2  pgoyette 
    135  1.3.2.2  pgoyette static int
    136  1.3.2.2  pgoyette efinet_probe(struct netif *nif, void *machdep_hint)
    137  1.3.2.2  pgoyette {
    138  1.3.2.2  pgoyette 
    139  1.3.2.2  pgoyette 	return 0;
    140  1.3.2.2  pgoyette }
    141  1.3.2.2  pgoyette 
    142  1.3.2.2  pgoyette static int
    143  1.3.2.2  pgoyette efinet_put(struct iodesc *desc, void *pkt, size_t len)
    144  1.3.2.2  pgoyette {
    145  1.3.2.2  pgoyette 	struct netif *nif = desc->io_netif;
    146  1.3.2.2  pgoyette 	struct efinetinfo *eni = nif->nif_devdata;
    147  1.3.2.2  pgoyette 	EFI_SIMPLE_NETWORK *net;
    148  1.3.2.2  pgoyette 	EFI_STATUS status;
    149  1.3.2.2  pgoyette 	void *buf;
    150  1.3.2.2  pgoyette 
    151  1.3.2.2  pgoyette 	if (eni == NULL)
    152  1.3.2.2  pgoyette 		return -1;
    153  1.3.2.2  pgoyette 	net = eni->net;
    154  1.3.2.2  pgoyette 
    155  1.3.2.2  pgoyette 	status = uefi_call_wrapper(net->Transmit, 7, net, 0, (UINTN)len, pkt, NULL,
    156  1.3.2.2  pgoyette 	    NULL, NULL);
    157  1.3.2.2  pgoyette 	if (EFI_ERROR(status))
    158  1.3.2.2  pgoyette 		return -1;
    159  1.3.2.2  pgoyette 
    160  1.3.2.2  pgoyette 	/* Wait for the buffer to be transmitted */
    161  1.3.2.2  pgoyette 	do {
    162  1.3.2.2  pgoyette 		buf = NULL;	/* XXX Is this needed? */
    163  1.3.2.2  pgoyette 		status = uefi_call_wrapper(net->GetStatus, 3, net, NULL, &buf);
    164  1.3.2.2  pgoyette 		/*
    165  1.3.2.2  pgoyette 		 * XXX EFI1.1 and the E1000 card returns a different
    166  1.3.2.2  pgoyette 		 * address than we gave.  Sigh.
    167  1.3.2.2  pgoyette 		 */
    168  1.3.2.2  pgoyette 	} while (!EFI_ERROR(status) && buf == NULL);
    169  1.3.2.2  pgoyette 
    170  1.3.2.2  pgoyette 	/* XXX How do we deal with status != EFI_SUCCESS now? */
    171  1.3.2.2  pgoyette 	return EFI_ERROR(status) ? -1 : len;
    172  1.3.2.2  pgoyette }
    173  1.3.2.2  pgoyette 
    174  1.3.2.2  pgoyette static int
    175  1.3.2.2  pgoyette efinet_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout)
    176  1.3.2.2  pgoyette {
    177  1.3.2.2  pgoyette 	struct netif *nif = desc->io_netif;
    178  1.3.2.2  pgoyette 	struct efinetinfo *eni = nif->nif_devdata;
    179  1.3.2.2  pgoyette 	EFI_SIMPLE_NETWORK *net;
    180  1.3.2.2  pgoyette 	EFI_STATUS status;
    181  1.3.2.2  pgoyette 	UINTN bufsz, rsz;
    182  1.3.2.2  pgoyette 	time_t t;
    183  1.3.2.2  pgoyette 	char *buf, *ptr;
    184  1.3.2.2  pgoyette 	int ret = -1;
    185  1.3.2.2  pgoyette 
    186  1.3.2.2  pgoyette 	if (eni == NULL)
    187  1.3.2.2  pgoyette 		return -1;
    188  1.3.2.2  pgoyette 	net = eni->net;
    189  1.3.2.2  pgoyette 
    190  1.3.2.2  pgoyette 	if (eni->pktbufsz < net->Mode->MaxPacketSize + ETHER_EXT_LEN) {
    191  1.3.2.2  pgoyette 		bufsz = net->Mode->MaxPacketSize + ETHER_EXT_LEN;
    192  1.3.2.2  pgoyette 		buf = alloc(bufsz);
    193  1.3.2.2  pgoyette 		if (buf == NULL)
    194  1.3.2.2  pgoyette 			return -1;
    195  1.3.2.2  pgoyette 		dealloc(eni->pktbuf, eni->pktbufsz);
    196  1.3.2.2  pgoyette 		eni->pktbufsz = bufsz;
    197  1.3.2.2  pgoyette 		eni->pktbuf = buf;
    198  1.3.2.2  pgoyette 	}
    199  1.3.2.2  pgoyette 	ptr = eni->pktbuf + ETHER_ALIGN;
    200  1.3.2.2  pgoyette 
    201  1.3.2.2  pgoyette 	t = getsecs();
    202  1.3.2.2  pgoyette 	while ((getsecs() - t) < timeout) {
    203  1.3.2.2  pgoyette 		rsz = eni->pktbufsz;
    204  1.3.2.2  pgoyette 		status = uefi_call_wrapper(net->Receive, 7, net, NULL, &rsz, ptr,
    205  1.3.2.2  pgoyette 		    NULL, NULL, NULL);
    206  1.3.2.2  pgoyette 		if (!EFI_ERROR(status)) {
    207  1.3.2.2  pgoyette 			rsz = uimin(rsz, len);
    208  1.3.2.2  pgoyette 			memcpy(pkt, ptr, rsz);
    209  1.3.2.2  pgoyette 			ret = (int)rsz;
    210  1.3.2.2  pgoyette 			break;
    211  1.3.2.2  pgoyette 		}
    212  1.3.2.2  pgoyette 		if (status != EFI_NOT_READY)
    213  1.3.2.2  pgoyette 			break;
    214  1.3.2.2  pgoyette 	}
    215  1.3.2.2  pgoyette 
    216  1.3.2.2  pgoyette 	return ret;
    217  1.3.2.2  pgoyette }
    218  1.3.2.2  pgoyette 
    219  1.3.2.2  pgoyette static void
    220  1.3.2.2  pgoyette efinet_init(struct iodesc *desc, void *machdep_hint)
    221  1.3.2.2  pgoyette {
    222  1.3.2.2  pgoyette 	struct netif *nif = desc->io_netif;
    223  1.3.2.2  pgoyette 	struct efinetinfo *eni;
    224  1.3.2.2  pgoyette 	EFI_SIMPLE_NETWORK *net;
    225  1.3.2.2  pgoyette 	EFI_STATUS status;
    226  1.3.2.2  pgoyette 	UINT32 mask;
    227  1.3.2.2  pgoyette 
    228  1.3.2.2  pgoyette 	if (nif->nif_driver->netif_ifs[nif->nif_unit].dif_unit < 0) {
    229  1.3.2.2  pgoyette 		printf("Invalid network interface %d\n", nif->nif_unit);
    230  1.3.2.2  pgoyette 		return;
    231  1.3.2.2  pgoyette 	}
    232  1.3.2.2  pgoyette 
    233  1.3.2.2  pgoyette 	eni = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private;
    234  1.3.2.2  pgoyette 	nif->nif_devdata = eni;
    235  1.3.2.2  pgoyette 	net = eni->net;
    236  1.3.2.2  pgoyette 	if (net->Mode->State == EfiSimpleNetworkStopped) {
    237  1.3.2.2  pgoyette 		status = uefi_call_wrapper(net->Start, 1, net);
    238  1.3.2.2  pgoyette 		if (EFI_ERROR(status)) {
    239  1.3.2.2  pgoyette 			printf("net%d: cannot start interface (status=%"
    240  1.3.2.2  pgoyette 			    PRIxMAX ")\n", nif->nif_unit, (uintmax_t)status);
    241  1.3.2.2  pgoyette 			return;
    242  1.3.2.2  pgoyette 		}
    243  1.3.2.2  pgoyette 	}
    244  1.3.2.2  pgoyette 
    245  1.3.2.2  pgoyette 	if (net->Mode->State != EfiSimpleNetworkInitialized) {
    246  1.3.2.2  pgoyette 		status = uefi_call_wrapper(net->Initialize, 3, net, 0, 0);
    247  1.3.2.2  pgoyette 		if (EFI_ERROR(status)) {
    248  1.3.2.2  pgoyette 			printf("net%d: cannot init. interface (status=%"
    249  1.3.2.2  pgoyette 			    PRIxMAX ")\n", nif->nif_unit, (uintmax_t)status);
    250  1.3.2.2  pgoyette 			return;
    251  1.3.2.2  pgoyette 		}
    252  1.3.2.2  pgoyette 	}
    253  1.3.2.2  pgoyette 
    254  1.3.2.2  pgoyette 	mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
    255  1.3.2.2  pgoyette 	    EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
    256  1.3.2.2  pgoyette 
    257  1.3.2.2  pgoyette 	status = uefi_call_wrapper(net->ReceiveFilters, 6, net, mask, 0, FALSE,
    258  1.3.2.2  pgoyette 	    0, NULL);
    259  1.3.2.2  pgoyette 	if (EFI_ERROR(status) && status != EFI_INVALID_PARAMETER) {
    260  1.3.2.2  pgoyette 		printf("net%d: cannot set rx. filters (status=%" PRIxMAX ")\n",
    261  1.3.2.2  pgoyette 		    nif->nif_unit, (uintmax_t)status);
    262  1.3.2.2  pgoyette 		return;
    263  1.3.2.2  pgoyette 	}
    264  1.3.2.2  pgoyette 
    265  1.3.2.2  pgoyette #if notyet
    266  1.3.2.2  pgoyette 	if (!kernel_loaded) {
    267  1.3.2.2  pgoyette 		bi_netif.bus = eni->bus.type;
    268  1.3.2.2  pgoyette 		bi_netif.addr.tag = eni->bus.tag;
    269  1.3.2.2  pgoyette 		snprintf(bi_netif.ifname, sizeof(bi_netif.ifname), "net%d",
    270  1.3.2.2  pgoyette 		    nif->nif_unit);
    271  1.3.2.2  pgoyette 		BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
    272  1.3.2.2  pgoyette 	}
    273  1.3.2.2  pgoyette #endif
    274  1.3.2.2  pgoyette 
    275  1.3.2.2  pgoyette #ifdef EFINET_DEBUG
    276  1.3.2.2  pgoyette 	dump_mode(net->Mode);
    277  1.3.2.2  pgoyette #endif
    278  1.3.2.2  pgoyette 
    279  1.3.2.2  pgoyette 	memcpy(desc->myea, net->Mode->PermanentAddress.Addr, 6);
    280  1.3.2.2  pgoyette 	desc->xid = 1;
    281  1.3.2.2  pgoyette }
    282  1.3.2.2  pgoyette 
    283  1.3.2.2  pgoyette static void
    284  1.3.2.2  pgoyette efinet_end(struct netif *nif)
    285  1.3.2.2  pgoyette {
    286  1.3.2.2  pgoyette 	struct efinetinfo *eni = nif->nif_devdata;
    287  1.3.2.2  pgoyette 	EFI_SIMPLE_NETWORK *net;
    288  1.3.2.2  pgoyette 
    289  1.3.2.2  pgoyette 	if (eni == NULL)
    290  1.3.2.2  pgoyette 		return;
    291  1.3.2.2  pgoyette 	net = eni->net;
    292  1.3.2.2  pgoyette 
    293  1.3.2.2  pgoyette 	uefi_call_wrapper(net->Shutdown, 1, net);
    294  1.3.2.2  pgoyette }
    295  1.3.2.2  pgoyette 
    296  1.3.2.2  pgoyette static bool
    297  1.3.2.2  pgoyette efi_net_pci_probe(struct efinetinfo *eni, EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *pdp)
    298  1.3.2.2  pgoyette {
    299  1.3.2.2  pgoyette #if notyet
    300  1.3.2.2  pgoyette 	PCI_DEVICE_PATH *pci = (PCI_DEVICE_PATH *)dp;
    301  1.3.2.2  pgoyette #endif
    302  1.3.2.2  pgoyette 	int bus = -1;
    303  1.3.2.2  pgoyette 
    304  1.3.2.2  pgoyette 	if (pdp != NULL &&
    305  1.3.2.2  pgoyette 	    DevicePathType(pdp) == ACPI_DEVICE_PATH &&
    306  1.3.2.2  pgoyette 	    (DevicePathSubType(pdp) == ACPI_DP ||
    307  1.3.2.2  pgoyette 	     DevicePathSubType(pdp) == EXPANDED_ACPI_DP)) {
    308  1.3.2.2  pgoyette 		ACPI_HID_DEVICE_PATH *acpi = (ACPI_HID_DEVICE_PATH *)pdp;
    309  1.3.2.2  pgoyette 		/* PCI root bus */
    310  1.3.2.2  pgoyette 		if (acpi->HID == EISA_PNP_ID(0x0A08) ||
    311  1.3.2.2  pgoyette 		    acpi->HID == EISA_PNP_ID(0x0A03)) {
    312  1.3.2.2  pgoyette 			bus = acpi->UID;
    313  1.3.2.2  pgoyette 		}
    314  1.3.2.2  pgoyette 	}
    315  1.3.2.2  pgoyette 	if (bus < 0)
    316  1.3.2.2  pgoyette 		return false;
    317  1.3.2.2  pgoyette 
    318  1.3.2.2  pgoyette #if notyet
    319  1.3.2.2  pgoyette 	eni->bus.type = BI_BUS_PCI;
    320  1.3.2.2  pgoyette 	eni->bus.tag = (bus & 0xff) << 8;
    321  1.3.2.2  pgoyette 	eni->bus.tag |= (pci->Device & 0x1f) << 3;
    322  1.3.2.2  pgoyette 	eni->bus.tag |= pci->Function & 0x7;
    323  1.3.2.2  pgoyette #endif
    324  1.3.2.2  pgoyette 	return true;
    325  1.3.2.2  pgoyette }
    326  1.3.2.2  pgoyette 
    327  1.3.2.2  pgoyette void
    328  1.3.2.2  pgoyette efi_net_probe(void)
    329  1.3.2.2  pgoyette {
    330  1.3.2.2  pgoyette 	struct efinetinfo *enis;
    331  1.3.2.2  pgoyette 	struct netif_dif *dif;
    332  1.3.2.2  pgoyette 	struct netif_stats *stats;
    333  1.3.2.2  pgoyette 	EFI_DEVICE_PATH *dp0, *dp, *pdp;
    334  1.3.2.2  pgoyette 	EFI_SIMPLE_NETWORK *net;
    335  1.3.2.2  pgoyette 	EFI_HANDLE *handles;
    336  1.3.2.2  pgoyette 	EFI_STATUS status;
    337  1.3.2.2  pgoyette 	UINTN i, nhandles;
    338  1.3.2.2  pgoyette 	int nifs, depth = -1;
    339  1.3.2.2  pgoyette 	bool found;
    340  1.3.2.2  pgoyette 
    341  1.3.2.2  pgoyette 	status = LibLocateHandle(ByProtocol, &SimpleNetworkProtocol, NULL,
    342  1.3.2.2  pgoyette 	    &nhandles, &handles);
    343  1.3.2.2  pgoyette 	if (EFI_ERROR(status) || nhandles == 0)
    344  1.3.2.2  pgoyette 		return;
    345  1.3.2.2  pgoyette 
    346  1.3.2.2  pgoyette 	enis = alloc(nhandles * sizeof(*enis));
    347  1.3.2.2  pgoyette 	if (enis == NULL)
    348  1.3.2.2  pgoyette 		return;
    349  1.3.2.2  pgoyette 	memset(enis, 0, nhandles * sizeof(*enis));
    350  1.3.2.2  pgoyette 
    351  1.3.2.2  pgoyette 	if (efi_bootdp) {
    352  1.3.2.2  pgoyette 		depth = efi_device_path_depth(efi_bootdp, HARDWARE_DEVICE_PATH);
    353  1.3.2.2  pgoyette 		if (depth == 0)
    354  1.3.2.2  pgoyette 			depth = 1;
    355  1.3.2.2  pgoyette 	}
    356  1.3.2.2  pgoyette 
    357  1.3.2.2  pgoyette 	nifs = 0;
    358  1.3.2.2  pgoyette 	for (i = 0; i < nhandles; i++) {
    359  1.3.2.2  pgoyette 		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
    360  1.3.2.2  pgoyette 		    &DevicePathProtocol, (void **)&dp0);
    361  1.3.2.2  pgoyette 		if (EFI_ERROR(status))
    362  1.3.2.2  pgoyette 			continue;
    363  1.3.2.2  pgoyette 
    364  1.3.2.2  pgoyette 		found = false;
    365  1.3.2.2  pgoyette 		for (dp = dp0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) {
    366  1.3.2.2  pgoyette 			if (DevicePathType(dp) == MESSAGING_DEVICE_PATH &&
    367  1.3.2.2  pgoyette 			    DevicePathSubType(dp) == MSG_MAC_ADDR_DP) {
    368  1.3.2.2  pgoyette 				found = true;
    369  1.3.2.2  pgoyette 				break;
    370  1.3.2.2  pgoyette 			}
    371  1.3.2.2  pgoyette 		}
    372  1.3.2.2  pgoyette 		if (!found)
    373  1.3.2.2  pgoyette 			continue;
    374  1.3.2.2  pgoyette 
    375  1.3.2.2  pgoyette 		status = uefi_call_wrapper(BS->OpenProtocol, 6, handles[i],
    376  1.3.2.2  pgoyette 		    &SimpleNetworkProtocol, (void **)&net, IH, NULL,
    377  1.3.2.2  pgoyette 		    EFI_OPEN_PROTOCOL_EXCLUSIVE);
    378  1.3.2.2  pgoyette 		if (EFI_ERROR(status)) {
    379  1.3.2.2  pgoyette 			printf("Unable to open network interface %" PRIuMAX
    380  1.3.2.2  pgoyette 			    " for exclusive access: %" PRIxMAX "\n",
    381  1.3.2.2  pgoyette 			    (uintmax_t)i, (uintmax_t)status);
    382  1.3.2.2  pgoyette 		}
    383  1.3.2.2  pgoyette 
    384  1.3.2.2  pgoyette 		found = false;
    385  1.3.2.2  pgoyette 		for (pdp = NULL, dp = dp0;
    386  1.3.2.2  pgoyette 		    !IsDevicePathEnd(dp);
    387  1.3.2.2  pgoyette 		    pdp = dp, dp = NextDevicePathNode(dp)) {
    388  1.3.2.2  pgoyette 			if (DevicePathType(dp) == HARDWARE_DEVICE_PATH) {
    389  1.3.2.2  pgoyette 				if (DevicePathSubType(dp) == HW_PCI_DP)
    390  1.3.2.2  pgoyette 					found = efi_net_pci_probe(&enis[nifs],
    391  1.3.2.2  pgoyette 					    dp, pdp);
    392  1.3.2.2  pgoyette 				break;
    393  1.3.2.2  pgoyette 			}
    394  1.3.2.2  pgoyette 		}
    395  1.3.2.2  pgoyette 		if (found) {
    396  1.3.2.2  pgoyette 			enis[nifs].net = net;
    397  1.3.2.2  pgoyette 			enis[nifs].bootdev = efi_pxe_match_booted_interface(
    398  1.3.2.2  pgoyette 			    &net->Mode->PermanentAddress, net->Mode->HwAddressSize);
    399  1.3.2.2  pgoyette 			enis[nifs].pktbufsz = net->Mode->MaxPacketSize +
    400  1.3.2.2  pgoyette 			    ETHER_EXT_LEN;
    401  1.3.2.2  pgoyette 			enis[nifs].pktbuf = alloc(enis[nifs].pktbufsz);
    402  1.3.2.2  pgoyette 			if (enis[nifs].pktbuf == NULL) {
    403  1.3.2.2  pgoyette 				while (i-- > 0) {
    404  1.3.2.2  pgoyette 					dealloc(enis[i].pktbuf, enis[i].pktbufsz);
    405  1.3.2.2  pgoyette 					if (i == 0)
    406  1.3.2.2  pgoyette 						break;
    407  1.3.2.2  pgoyette 				}
    408  1.3.2.2  pgoyette 				dealloc(enis, nhandles * sizeof(*enis));
    409  1.3.2.2  pgoyette 				FreePool(handles);
    410  1.3.2.2  pgoyette 				return;
    411  1.3.2.2  pgoyette 			}
    412  1.3.2.2  pgoyette 
    413  1.3.2.2  pgoyette 			if (depth > 0 && efi_device_path_ncmp(efi_bootdp, dp0, depth) == 0) {
    414  1.3.2.2  pgoyette 				char devname[9];
    415  1.3.2.2  pgoyette 				snprintf(devname, sizeof(devname), "net%u", nifs);
    416  1.3.2.2  pgoyette 				set_default_device(devname);
    417  1.3.2.2  pgoyette 			}
    418  1.3.2.2  pgoyette 
    419  1.3.2.2  pgoyette 			nifs++;
    420  1.3.2.2  pgoyette 		}
    421  1.3.2.2  pgoyette 	}
    422  1.3.2.2  pgoyette 
    423  1.3.2.2  pgoyette 	FreePool(handles);
    424  1.3.2.2  pgoyette 
    425  1.3.2.2  pgoyette 	if (nifs == 0)
    426  1.3.2.2  pgoyette 		return;
    427  1.3.2.2  pgoyette 
    428  1.3.2.2  pgoyette 	efinetif.netif_ifs = alloc(nifs * sizeof(*dif));
    429  1.3.2.2  pgoyette 	stats = alloc(nifs * sizeof(*stats));
    430  1.3.2.2  pgoyette 	if (efinetif.netif_ifs == NULL || stats == NULL) {
    431  1.3.2.2  pgoyette 		if (efinetif.netif_ifs != NULL) {
    432  1.3.2.2  pgoyette 			dealloc(efinetif.netif_ifs, nifs * sizeof(*dif));
    433  1.3.2.2  pgoyette 			efinetif.netif_ifs = NULL;
    434  1.3.2.2  pgoyette 		}
    435  1.3.2.2  pgoyette 		if (stats != NULL)
    436  1.3.2.2  pgoyette 			dealloc(stats, nifs * sizeof(*stats));
    437  1.3.2.2  pgoyette 		for (i = 0; i < nifs; i++)
    438  1.3.2.2  pgoyette 			dealloc(enis[i].pktbuf, enis[i].pktbufsz);
    439  1.3.2.2  pgoyette 		dealloc(enis, nhandles * sizeof(*enis));
    440  1.3.2.2  pgoyette 		return;
    441  1.3.2.2  pgoyette 	}
    442  1.3.2.2  pgoyette 	memset(efinetif.netif_ifs, 0, nifs * sizeof(*dif));
    443  1.3.2.2  pgoyette 	memset(stats, 0, nifs * sizeof(*stats));
    444  1.3.2.2  pgoyette 	efinetif.netif_nifs = nifs;
    445  1.3.2.2  pgoyette 
    446  1.3.2.2  pgoyette 	for (i = 0; i < nifs; i++) {
    447  1.3.2.2  pgoyette 		dif = &efinetif.netif_ifs[i];
    448  1.3.2.2  pgoyette 		dif->dif_unit = i;
    449  1.3.2.2  pgoyette 		dif->dif_nsel = 1;
    450  1.3.2.2  pgoyette 		dif->dif_stats = &stats[i];
    451  1.3.2.2  pgoyette 		dif->dif_private = &enis[i];
    452  1.3.2.2  pgoyette 	}
    453  1.3.2.2  pgoyette }
    454  1.3.2.2  pgoyette 
    455  1.3.2.2  pgoyette void
    456  1.3.2.2  pgoyette efi_net_show(void)
    457  1.3.2.2  pgoyette {
    458  1.3.2.2  pgoyette 	const struct netif_dif *dif;
    459  1.3.2.2  pgoyette 	const struct efinetinfo *eni;
    460  1.3.2.2  pgoyette 	EFI_SIMPLE_NETWORK *net;
    461  1.3.2.2  pgoyette 	int i;
    462  1.3.2.2  pgoyette 
    463  1.3.2.2  pgoyette 	for (i = 0; i < efinetif.netif_nifs; i++) {
    464  1.3.2.2  pgoyette 		dif = &efinetif.netif_ifs[i];
    465  1.3.2.2  pgoyette 		eni = dif->dif_private;
    466  1.3.2.2  pgoyette 		net = eni->net;
    467  1.3.2.2  pgoyette 
    468  1.3.2.3  pgoyette 		printf("net%d", dif->dif_unit);
    469  1.3.2.2  pgoyette 		if (net->Mode != NULL) {
    470  1.3.2.2  pgoyette 			for (UINT32 x = 0; x < net->Mode->HwAddressSize; x++) {
    471  1.3.2.2  pgoyette 				printf("%c%02x", x == 0 ? ' ' : ':',
    472  1.3.2.2  pgoyette 				    net->Mode->PermanentAddress.Addr[x]);
    473  1.3.2.2  pgoyette 			}
    474  1.3.2.2  pgoyette 		}
    475  1.3.2.2  pgoyette #if notyet
    476  1.3.2.2  pgoyette 		if (eni->bus.type == BI_BUS_PCI) {
    477  1.3.2.2  pgoyette 			printf(" pci%d,%d,%d", (eni->bus.tag >> 8) & 0xff,
    478  1.3.2.2  pgoyette 			    (eni->bus.tag >> 3) & 0x1f, eni->bus.tag & 0x7);
    479  1.3.2.2  pgoyette 		}
    480  1.3.2.2  pgoyette #endif
    481  1.3.2.2  pgoyette 		if (eni->bootdev)
    482  1.3.2.2  pgoyette 			printf(" pxeboot");
    483  1.3.2.2  pgoyette 		printf("\n");
    484  1.3.2.2  pgoyette 	}
    485  1.3.2.2  pgoyette }
    486  1.3.2.2  pgoyette 
    487  1.3.2.2  pgoyette int
    488  1.3.2.2  pgoyette efi_net_get_booted_interface_unit(void)
    489  1.3.2.2  pgoyette {
    490  1.3.2.2  pgoyette 	const struct netif_dif *dif;
    491  1.3.2.2  pgoyette 	const struct efinetinfo *eni;
    492  1.3.2.2  pgoyette 	int i;
    493  1.3.2.2  pgoyette 
    494  1.3.2.2  pgoyette 	for (i = 0; i < efinetif.netif_nifs; i++) {
    495  1.3.2.2  pgoyette 		dif = &efinetif.netif_ifs[i];
    496  1.3.2.2  pgoyette 		eni = dif->dif_private;
    497  1.3.2.2  pgoyette 		if (eni->bootdev)
    498  1.3.2.2  pgoyette 			return dif->dif_unit;
    499  1.3.2.2  pgoyette 	}
    500  1.3.2.2  pgoyette 	return -1;
    501  1.3.2.2  pgoyette }
    502  1.3.2.2  pgoyette 
    503  1.3.2.2  pgoyette int
    504  1.3.2.3  pgoyette efi_net_get_booted_macaddr(uint8_t *mac)
    505  1.3.2.3  pgoyette {
    506  1.3.2.3  pgoyette 	const struct netif_dif *dif;
    507  1.3.2.3  pgoyette 	const struct efinetinfo *eni;
    508  1.3.2.3  pgoyette 	EFI_SIMPLE_NETWORK *net;
    509  1.3.2.3  pgoyette 	int i;
    510  1.3.2.3  pgoyette 
    511  1.3.2.3  pgoyette 	for (i = 0; i < efinetif.netif_nifs; i++) {
    512  1.3.2.3  pgoyette 		dif = &efinetif.netif_ifs[i];
    513  1.3.2.3  pgoyette 		eni = dif->dif_private;
    514  1.3.2.3  pgoyette 		net = eni->net;
    515  1.3.2.3  pgoyette 		if (eni->bootdev && net->Mode != NULL && net->Mode->HwAddressSize == 6) {
    516  1.3.2.3  pgoyette 			memcpy(mac, net->Mode->PermanentAddress.Addr, 6);
    517  1.3.2.3  pgoyette 			return 0;
    518  1.3.2.3  pgoyette 		}
    519  1.3.2.3  pgoyette 	}
    520  1.3.2.3  pgoyette 
    521  1.3.2.3  pgoyette 	return -1;
    522  1.3.2.3  pgoyette }
    523  1.3.2.3  pgoyette 
    524  1.3.2.3  pgoyette int
    525  1.3.2.2  pgoyette efi_net_open(struct open_file *f, ...)
    526  1.3.2.2  pgoyette {
    527  1.3.2.2  pgoyette 	char **file, pathbuf[PATH_MAX], *default_device, *path, *ep;
    528  1.3.2.2  pgoyette 	const char *fname, *full_path;
    529  1.3.2.2  pgoyette 	struct devdesc desc;
    530  1.3.2.2  pgoyette 	intmax_t dev;
    531  1.3.2.2  pgoyette 	va_list ap;
    532  1.3.2.3  pgoyette 	int n, error;
    533  1.3.2.2  pgoyette 
    534  1.3.2.2  pgoyette 	va_start(ap, f);
    535  1.3.2.2  pgoyette 	fname = va_arg(ap, const char *);
    536  1.3.2.2  pgoyette 	file = va_arg(ap, char **);
    537  1.3.2.2  pgoyette 	va_end(ap);
    538  1.3.2.2  pgoyette 
    539  1.3.2.2  pgoyette 	default_device = get_default_device();
    540  1.3.2.2  pgoyette 	if (strchr(fname, ':') == NULL) {
    541  1.3.2.2  pgoyette 		if (strlen(default_device) > 0) {
    542  1.3.2.2  pgoyette 			snprintf(pathbuf, sizeof(pathbuf), "%s:%s", default_device, fname);
    543  1.3.2.2  pgoyette 			full_path = pathbuf;
    544  1.3.2.2  pgoyette 			path = __UNCONST(fname);
    545  1.3.2.2  pgoyette 		} else {
    546  1.3.2.2  pgoyette 			return EINVAL;
    547  1.3.2.2  pgoyette 		}
    548  1.3.2.2  pgoyette 	} else {
    549  1.3.2.2  pgoyette 		full_path = fname;
    550  1.3.2.2  pgoyette 		path = strchr(fname, ':') + 1;
    551  1.3.2.2  pgoyette 	}
    552  1.3.2.2  pgoyette 
    553  1.3.2.2  pgoyette 	if (strncmp(full_path, "net", 3) != 0)
    554  1.3.2.2  pgoyette 		return EINVAL;
    555  1.3.2.2  pgoyette         dev = strtoimax(full_path + 3, &ep, 10);
    556  1.3.2.2  pgoyette         if (dev < 0 || dev >= efinetif.netif_nifs)
    557  1.3.2.2  pgoyette                 return ENXIO;
    558  1.3.2.2  pgoyette 
    559  1.3.2.2  pgoyette         for (n = 0; n < ndevs; n++)
    560  1.3.2.2  pgoyette                 if (strcmp(DEV_NAME(&devsw[n]), "net") == 0) {
    561  1.3.2.2  pgoyette                         f->f_dev = &devsw[n];
    562  1.3.2.2  pgoyette                         break;
    563  1.3.2.2  pgoyette                 }
    564  1.3.2.2  pgoyette         if (n == ndevs)
    565  1.3.2.2  pgoyette                 return ENXIO;
    566  1.3.2.2  pgoyette 
    567  1.3.2.2  pgoyette 	*file = path;
    568  1.3.2.2  pgoyette 
    569  1.3.2.2  pgoyette 	//try_bootp = 1;
    570  1.3.2.2  pgoyette 
    571  1.3.2.2  pgoyette 	memset(&desc, 0, sizeof(desc));
    572  1.3.2.2  pgoyette 	strlcpy(desc.d_name, "net", sizeof(desc.d_name));
    573  1.3.2.2  pgoyette 	desc.d_unit = dev;
    574  1.3.2.2  pgoyette 
    575  1.3.2.3  pgoyette 	error = DEV_OPEN(f->f_dev)(f, &desc);
    576  1.3.2.3  pgoyette 	if (error)
    577  1.3.2.3  pgoyette 		return error;
    578  1.3.2.3  pgoyette 
    579  1.3.2.3  pgoyette 	return 0;
    580  1.3.2.2  pgoyette }
    581