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