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