xref: /freebsd/stand/uboot/net.c (revision 9dc70af83e5992e543542adbf5a6edeb38f187f6)
1*9dc70af8SWarner Losh /*-
2*9dc70af8SWarner Losh  * Copyright (c) 2000-2001 Benno Rice
3*9dc70af8SWarner Losh  * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.com>
4*9dc70af8SWarner Losh  * All rights reserved.
5*9dc70af8SWarner Losh  *
6*9dc70af8SWarner Losh  * Redistribution and use in source and binary forms, with or without
7*9dc70af8SWarner Losh  * modification, are permitted provided that the following conditions
8*9dc70af8SWarner Losh  * are met:
9*9dc70af8SWarner Losh  * 1. Redistributions of source code must retain the above copyright
10*9dc70af8SWarner Losh  *    notice, this list of conditions and the following disclaimer.
11*9dc70af8SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
12*9dc70af8SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
13*9dc70af8SWarner Losh  *    documentation and/or other materials provided with the distribution.
14*9dc70af8SWarner Losh  *
15*9dc70af8SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*9dc70af8SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*9dc70af8SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*9dc70af8SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*9dc70af8SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*9dc70af8SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*9dc70af8SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*9dc70af8SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*9dc70af8SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*9dc70af8SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*9dc70af8SWarner Losh  * SUCH DAMAGE.
26*9dc70af8SWarner Losh  */
27*9dc70af8SWarner Losh 
28*9dc70af8SWarner Losh #include <sys/cdefs.h>
29*9dc70af8SWarner Losh __FBSDID("$FreeBSD$");
30*9dc70af8SWarner Losh 
31*9dc70af8SWarner Losh #include <sys/param.h>
32*9dc70af8SWarner Losh #include <sys/types.h>
33*9dc70af8SWarner Losh #include <sys/socket.h>
34*9dc70af8SWarner Losh 
35*9dc70af8SWarner Losh #include <net/if.h>
36*9dc70af8SWarner Losh #include <netinet/in.h>
37*9dc70af8SWarner Losh #include <netinet/in_systm.h>
38*9dc70af8SWarner Losh #include <netinet/if_ether.h>
39*9dc70af8SWarner Losh #include <netinet/ip.h>
40*9dc70af8SWarner Losh 
41*9dc70af8SWarner Losh #include <stand.h>
42*9dc70af8SWarner Losh #include <net.h>
43*9dc70af8SWarner Losh #include <netif.h>
44*9dc70af8SWarner Losh 
45*9dc70af8SWarner Losh #include "api_public.h"
46*9dc70af8SWarner Losh #include "glue.h"
47*9dc70af8SWarner Losh #include "libuboot.h"
48*9dc70af8SWarner Losh #include "dev_net.h"
49*9dc70af8SWarner Losh 
50*9dc70af8SWarner Losh static int	net_probe(struct netif *, void *);
51*9dc70af8SWarner Losh static int	net_match(struct netif *, void *);
52*9dc70af8SWarner Losh static void	net_init(struct iodesc *, void *);
53*9dc70af8SWarner Losh static ssize_t	net_get(struct iodesc *, void **, time_t);
54*9dc70af8SWarner Losh static ssize_t	net_put(struct iodesc *, void *, size_t);
55*9dc70af8SWarner Losh static void	net_end(struct netif *);
56*9dc70af8SWarner Losh 
57*9dc70af8SWarner Losh extern struct netif_stats net_stats[];
58*9dc70af8SWarner Losh 
59*9dc70af8SWarner Losh struct netif_dif net_ifs[] = {
60*9dc70af8SWarner Losh 	/*	dif_unit	dif_nsel	dif_stats	dif_private */
61*9dc70af8SWarner Losh 	{	0,		1,		&net_stats[0],	0,	},
62*9dc70af8SWarner Losh };
63*9dc70af8SWarner Losh 
64*9dc70af8SWarner Losh struct netif_stats net_stats[nitems(net_ifs)];
65*9dc70af8SWarner Losh 
66*9dc70af8SWarner Losh struct netif_driver uboot_net = {
67*9dc70af8SWarner Losh 	"uboot_eth",		/* netif_bname */
68*9dc70af8SWarner Losh 	net_match,		/* netif_match */
69*9dc70af8SWarner Losh 	net_probe,		/* netif_probe */
70*9dc70af8SWarner Losh 	net_init,		/* netif_init */
71*9dc70af8SWarner Losh 	net_get,		/* netif_get */
72*9dc70af8SWarner Losh 	net_put,		/* netif_put */
73*9dc70af8SWarner Losh 	net_end,		/* netif_end */
74*9dc70af8SWarner Losh 	net_ifs,		/* netif_ifs */
75*9dc70af8SWarner Losh 	nitems(net_ifs)		/* netif_nifs */
76*9dc70af8SWarner Losh };
77*9dc70af8SWarner Losh 
78*9dc70af8SWarner Losh struct uboot_softc {
79*9dc70af8SWarner Losh 	uint32_t	sc_pad;
80*9dc70af8SWarner Losh 	uint8_t		sc_rxbuf[ETHER_MAX_LEN];
81*9dc70af8SWarner Losh 	uint8_t		sc_txbuf[ETHER_MAX_LEN + PKTALIGN];
82*9dc70af8SWarner Losh 	uint8_t		*sc_txbufp;
83*9dc70af8SWarner Losh 	int		sc_handle;	/* device handle for ub_dev_xxx */
84*9dc70af8SWarner Losh };
85*9dc70af8SWarner Losh 
86*9dc70af8SWarner Losh static struct uboot_softc uboot_softc;
87*9dc70af8SWarner Losh 
88*9dc70af8SWarner Losh /*
89*9dc70af8SWarner Losh  * get_env_net_params()
90*9dc70af8SWarner Losh  *
91*9dc70af8SWarner Losh  * Attempt to obtain all the parms we need for netbooting from the U-Boot
92*9dc70af8SWarner Losh  * environment.  If we fail to obtain the values it may still be possible to
93*9dc70af8SWarner Losh  * netboot; the net_dev code will attempt to get the values from bootp, rarp,
94*9dc70af8SWarner Losh  * and other such sources.
95*9dc70af8SWarner Losh  *
96*9dc70af8SWarner Losh  * If rootip.s_addr is non-zero net_dev assumes the required global variables
97*9dc70af8SWarner Losh  * are set and skips the bootp inquiry.  For that reason, we don't set rootip
98*9dc70af8SWarner Losh  * until we've verified that we have at least the minimum required info.
99*9dc70af8SWarner Losh  *
100*9dc70af8SWarner Losh  * This is called from netif_init() which can result in it getting called
101*9dc70af8SWarner Losh  * multiple times, by design.  The network code at higher layers zeroes out
102*9dc70af8SWarner Losh  * rootip when it closes a network interface, so if it gets opened again we have
103*9dc70af8SWarner Losh  * to obtain all this info again.
104*9dc70af8SWarner Losh  */
105*9dc70af8SWarner Losh static void
106*9dc70af8SWarner Losh get_env_net_params()
107*9dc70af8SWarner Losh {
108*9dc70af8SWarner Losh 	char *envstr;
109*9dc70af8SWarner Losh 	in_addr_t rootaddr, serveraddr;
110*9dc70af8SWarner Losh 
111*9dc70af8SWarner Losh 	/*
112*9dc70af8SWarner Losh 	 * Silently get out right away if we don't have rootpath, because none
113*9dc70af8SWarner Losh 	 * of the other info we obtain below is sufficient to boot without it.
114*9dc70af8SWarner Losh 	 *
115*9dc70af8SWarner Losh 	 * If we do have rootpath, copy it into the global var and also set
116*9dc70af8SWarner Losh 	 * dhcp.root-path in the env.  If we don't get all the other info from
117*9dc70af8SWarner Losh 	 * the u-boot env below, we will still try dhcp/bootp, but the server-
118*9dc70af8SWarner Losh 	 * provided path will not replace the user-provided value we set here.
119*9dc70af8SWarner Losh 	 */
120*9dc70af8SWarner Losh 	if ((envstr = ub_env_get("rootpath")) == NULL)
121*9dc70af8SWarner Losh 		return;
122*9dc70af8SWarner Losh 	strlcpy(rootpath, envstr, sizeof(rootpath));
123*9dc70af8SWarner Losh 	setenv("dhcp.root-path", rootpath, 0);
124*9dc70af8SWarner Losh 
125*9dc70af8SWarner Losh 	/*
126*9dc70af8SWarner Losh 	 * Our own IP address must be valid.  Silently get out if it's not set,
127*9dc70af8SWarner Losh 	 * but whine if it's there and we can't parse it.
128*9dc70af8SWarner Losh 	 */
129*9dc70af8SWarner Losh 	if ((envstr = ub_env_get("ipaddr")) == NULL)
130*9dc70af8SWarner Losh 		return;
131*9dc70af8SWarner Losh 	if ((myip.s_addr = inet_addr(envstr)) == INADDR_NONE) {
132*9dc70af8SWarner Losh 		printf("Could not parse ipaddr '%s'\n", envstr);
133*9dc70af8SWarner Losh 		return;
134*9dc70af8SWarner Losh 	}
135*9dc70af8SWarner Losh 
136*9dc70af8SWarner Losh 	/*
137*9dc70af8SWarner Losh 	 * Netmask is optional, default to the "natural" netmask for our IP, but
138*9dc70af8SWarner Losh 	 * whine if it was provided and we couldn't parse it.
139*9dc70af8SWarner Losh 	 */
140*9dc70af8SWarner Losh 	if ((envstr = ub_env_get("netmask")) != NULL &&
141*9dc70af8SWarner Losh 	    (netmask = inet_addr(envstr)) == INADDR_NONE) {
142*9dc70af8SWarner Losh 		printf("Could not parse netmask '%s'\n", envstr);
143*9dc70af8SWarner Losh 	}
144*9dc70af8SWarner Losh 	if (netmask == INADDR_NONE) {
145*9dc70af8SWarner Losh 		if (IN_CLASSA(myip.s_addr))
146*9dc70af8SWarner Losh 			netmask = IN_CLASSA_NET;
147*9dc70af8SWarner Losh 		else if (IN_CLASSB(myip.s_addr))
148*9dc70af8SWarner Losh 			netmask = IN_CLASSB_NET;
149*9dc70af8SWarner Losh 		else
150*9dc70af8SWarner Losh 			netmask = IN_CLASSC_NET;
151*9dc70af8SWarner Losh 	}
152*9dc70af8SWarner Losh 
153*9dc70af8SWarner Losh 	/*
154*9dc70af8SWarner Losh 	 * Get optional serverip before rootpath; the latter can override it.
155*9dc70af8SWarner Losh 	 * Whine only if it's present but can't be parsed.
156*9dc70af8SWarner Losh 	 */
157*9dc70af8SWarner Losh 	serveraddr = INADDR_NONE;
158*9dc70af8SWarner Losh 	if ((envstr = ub_env_get("serverip")) != NULL) {
159*9dc70af8SWarner Losh 		if ((serveraddr = inet_addr(envstr)) == INADDR_NONE)
160*9dc70af8SWarner Losh 			printf("Could not parse serverip '%s'\n", envstr);
161*9dc70af8SWarner Losh 	}
162*9dc70af8SWarner Losh 
163*9dc70af8SWarner Losh 	/*
164*9dc70af8SWarner Losh 	 * There must be a rootpath.  It may be ip:/path or it may be just the
165*9dc70af8SWarner Losh 	 * path in which case the ip needs to be in serverip.
166*9dc70af8SWarner Losh 	 */
167*9dc70af8SWarner Losh 	rootaddr = net_parse_rootpath();
168*9dc70af8SWarner Losh 	if (rootaddr == INADDR_NONE)
169*9dc70af8SWarner Losh 		rootaddr = serveraddr;
170*9dc70af8SWarner Losh 	if (rootaddr == INADDR_NONE) {
171*9dc70af8SWarner Losh 		printf("No server address for rootpath '%s'\n", envstr);
172*9dc70af8SWarner Losh 		return;
173*9dc70af8SWarner Losh 	}
174*9dc70af8SWarner Losh 	rootip.s_addr = rootaddr;
175*9dc70af8SWarner Losh 
176*9dc70af8SWarner Losh 	/*
177*9dc70af8SWarner Losh 	 * Gateway IP is optional unless rootip is on a different net in which
178*9dc70af8SWarner Losh 	 * case whine if it's missing or we can't parse it, and set rootip addr
179*9dc70af8SWarner Losh 	 * to zero, which signals to other network code that network params
180*9dc70af8SWarner Losh 	 * aren't set (so it will try dhcp, bootp, etc).
181*9dc70af8SWarner Losh 	 */
182*9dc70af8SWarner Losh 	envstr = ub_env_get("gatewayip");
183*9dc70af8SWarner Losh 	if (!SAMENET(myip, rootip, netmask)) {
184*9dc70af8SWarner Losh 		if (envstr == NULL)  {
185*9dc70af8SWarner Losh 			printf("Need gatewayip for a root server on a "
186*9dc70af8SWarner Losh 			    "different network.\n");
187*9dc70af8SWarner Losh 			rootip.s_addr = 0;
188*9dc70af8SWarner Losh 			return;
189*9dc70af8SWarner Losh 		}
190*9dc70af8SWarner Losh 		if ((gateip.s_addr = inet_addr(envstr)) == INADDR_NONE) {
191*9dc70af8SWarner Losh 			printf("Could not parse gatewayip '%s'\n", envstr);
192*9dc70af8SWarner Losh 			rootip.s_addr = 0;
193*9dc70af8SWarner Losh 			return;
194*9dc70af8SWarner Losh 		}
195*9dc70af8SWarner Losh 	}
196*9dc70af8SWarner Losh }
197*9dc70af8SWarner Losh 
198*9dc70af8SWarner Losh static int
199*9dc70af8SWarner Losh net_match(struct netif *nif, void *machdep_hint)
200*9dc70af8SWarner Losh {
201*9dc70af8SWarner Losh 	char **a = (char **)machdep_hint;
202*9dc70af8SWarner Losh 
203*9dc70af8SWarner Losh 	if (memcmp("net", *a, 3) == 0)
204*9dc70af8SWarner Losh 		return (1);
205*9dc70af8SWarner Losh 
206*9dc70af8SWarner Losh 	printf("net_match: could not match network device\n");
207*9dc70af8SWarner Losh 	return (0);
208*9dc70af8SWarner Losh }
209*9dc70af8SWarner Losh 
210*9dc70af8SWarner Losh static int
211*9dc70af8SWarner Losh net_probe(struct netif *nif, void *machdep_hint)
212*9dc70af8SWarner Losh {
213*9dc70af8SWarner Losh 	struct device_info *di;
214*9dc70af8SWarner Losh 	int i;
215*9dc70af8SWarner Losh 
216*9dc70af8SWarner Losh 	for (i = 0; i < devs_no; i++)
217*9dc70af8SWarner Losh 		if ((di = ub_dev_get(i)) != NULL)
218*9dc70af8SWarner Losh 			if (di->type == DEV_TYP_NET)
219*9dc70af8SWarner Losh 				break;
220*9dc70af8SWarner Losh 
221*9dc70af8SWarner Losh 	if (i == devs_no) {
222*9dc70af8SWarner Losh 		printf("net_probe: no network devices found, maybe not"
223*9dc70af8SWarner Losh 		    " enumerated yet..?\n");
224*9dc70af8SWarner Losh 		return (-1);
225*9dc70af8SWarner Losh 	}
226*9dc70af8SWarner Losh 
227*9dc70af8SWarner Losh #if defined(NETIF_DEBUG)
228*9dc70af8SWarner Losh 	printf("net_probe: network device found: %d\n", i);
229*9dc70af8SWarner Losh #endif
230*9dc70af8SWarner Losh 	uboot_softc.sc_handle = i;
231*9dc70af8SWarner Losh 
232*9dc70af8SWarner Losh 	return (0);
233*9dc70af8SWarner Losh }
234*9dc70af8SWarner Losh 
235*9dc70af8SWarner Losh static ssize_t
236*9dc70af8SWarner Losh net_put(struct iodesc *desc, void *pkt, size_t len)
237*9dc70af8SWarner Losh {
238*9dc70af8SWarner Losh 	struct netif *nif = desc->io_netif;
239*9dc70af8SWarner Losh 	struct uboot_softc *sc = nif->nif_devdata;
240*9dc70af8SWarner Losh 	size_t sendlen;
241*9dc70af8SWarner Losh 	ssize_t rv;
242*9dc70af8SWarner Losh 
243*9dc70af8SWarner Losh #if defined(NETIF_DEBUG)
244*9dc70af8SWarner Losh 	struct ether_header *eh;
245*9dc70af8SWarner Losh 
246*9dc70af8SWarner Losh 	printf("net_put: desc %p, pkt %p, len %d\n", desc, pkt, len);
247*9dc70af8SWarner Losh 	eh = pkt;
248*9dc70af8SWarner Losh 	printf("dst: %s ", ether_sprintf(eh->ether_dhost));
249*9dc70af8SWarner Losh 	printf("src: %s ", ether_sprintf(eh->ether_shost));
250*9dc70af8SWarner Losh 	printf("type: 0x%x\n", eh->ether_type & 0xffff);
251*9dc70af8SWarner Losh #endif
252*9dc70af8SWarner Losh 
253*9dc70af8SWarner Losh 	if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
254*9dc70af8SWarner Losh 		sendlen = ETHER_MIN_LEN - ETHER_CRC_LEN;
255*9dc70af8SWarner Losh 		bzero(sc->sc_txbufp, sendlen);
256*9dc70af8SWarner Losh 	} else
257*9dc70af8SWarner Losh 		sendlen = len;
258*9dc70af8SWarner Losh 
259*9dc70af8SWarner Losh 	memcpy(sc->sc_txbufp, pkt, len);
260*9dc70af8SWarner Losh 
261*9dc70af8SWarner Losh 	rv = ub_dev_send(sc->sc_handle, sc->sc_txbufp, sendlen);
262*9dc70af8SWarner Losh 
263*9dc70af8SWarner Losh #if defined(NETIF_DEBUG)
264*9dc70af8SWarner Losh 	printf("net_put: ub_send returned %d\n", rv);
265*9dc70af8SWarner Losh #endif
266*9dc70af8SWarner Losh 	if (rv == 0)
267*9dc70af8SWarner Losh 		rv = len;
268*9dc70af8SWarner Losh 	else
269*9dc70af8SWarner Losh 		rv = -1;
270*9dc70af8SWarner Losh 
271*9dc70af8SWarner Losh 	return (rv);
272*9dc70af8SWarner Losh }
273*9dc70af8SWarner Losh 
274*9dc70af8SWarner Losh static ssize_t
275*9dc70af8SWarner Losh net_get(struct iodesc *desc, void **pkt, time_t timeout)
276*9dc70af8SWarner Losh {
277*9dc70af8SWarner Losh 	struct netif *nif = desc->io_netif;
278*9dc70af8SWarner Losh 	struct uboot_softc *sc = nif->nif_devdata;
279*9dc70af8SWarner Losh 	time_t t;
280*9dc70af8SWarner Losh 	int err, rlen;
281*9dc70af8SWarner Losh 	size_t len;
282*9dc70af8SWarner Losh 	char *buf;
283*9dc70af8SWarner Losh 
284*9dc70af8SWarner Losh #if defined(NETIF_DEBUG)
285*9dc70af8SWarner Losh 	printf("net_get: pkt %p, timeout %d\n", pkt, timeout);
286*9dc70af8SWarner Losh #endif
287*9dc70af8SWarner Losh 	t = getsecs();
288*9dc70af8SWarner Losh 	len = sizeof(sc->sc_rxbuf);
289*9dc70af8SWarner Losh 	do {
290*9dc70af8SWarner Losh 		err = ub_dev_recv(sc->sc_handle, sc->sc_rxbuf, len, &rlen);
291*9dc70af8SWarner Losh 
292*9dc70af8SWarner Losh 		if (err != 0) {
293*9dc70af8SWarner Losh 			printf("net_get: ub_dev_recv() failed, error=%d\n",
294*9dc70af8SWarner Losh 			    err);
295*9dc70af8SWarner Losh 			rlen = 0;
296*9dc70af8SWarner Losh 			break;
297*9dc70af8SWarner Losh 		}
298*9dc70af8SWarner Losh 	} while ((rlen == -1 || rlen == 0) && (getsecs() - t < timeout));
299*9dc70af8SWarner Losh 
300*9dc70af8SWarner Losh #if defined(NETIF_DEBUG)
301*9dc70af8SWarner Losh 	printf("net_get: received len %d (%x)\n", rlen, rlen);
302*9dc70af8SWarner Losh #endif
303*9dc70af8SWarner Losh 
304*9dc70af8SWarner Losh 	if (rlen > 0) {
305*9dc70af8SWarner Losh 		buf = malloc(rlen + ETHER_ALIGN);
306*9dc70af8SWarner Losh 		if (buf == NULL)
307*9dc70af8SWarner Losh 			return (-1);
308*9dc70af8SWarner Losh 		memcpy(buf + ETHER_ALIGN, sc->sc_rxbuf, rlen);
309*9dc70af8SWarner Losh 		*pkt = buf;
310*9dc70af8SWarner Losh 		return ((ssize_t)rlen);
311*9dc70af8SWarner Losh 	}
312*9dc70af8SWarner Losh 
313*9dc70af8SWarner Losh 	return (-1);
314*9dc70af8SWarner Losh }
315*9dc70af8SWarner Losh 
316*9dc70af8SWarner Losh static void
317*9dc70af8SWarner Losh net_init(struct iodesc *desc, void *machdep_hint)
318*9dc70af8SWarner Losh {
319*9dc70af8SWarner Losh 	struct netif *nif = desc->io_netif;
320*9dc70af8SWarner Losh 	struct uboot_softc *sc;
321*9dc70af8SWarner Losh 	struct device_info *di;
322*9dc70af8SWarner Losh 	int err;
323*9dc70af8SWarner Losh 
324*9dc70af8SWarner Losh 	sc = nif->nif_devdata = &uboot_softc;
325*9dc70af8SWarner Losh 
326*9dc70af8SWarner Losh 	if ((err = ub_dev_open(sc->sc_handle)) != 0)
327*9dc70af8SWarner Losh 		panic("%s%d: initialisation failed with error %d",
328*9dc70af8SWarner Losh 		    nif->nif_driver->netif_bname, nif->nif_unit, err);
329*9dc70af8SWarner Losh 
330*9dc70af8SWarner Losh 	/* Get MAC address */
331*9dc70af8SWarner Losh 	di = ub_dev_get(sc->sc_handle);
332*9dc70af8SWarner Losh 	memcpy(desc->myea, di->di_net.hwaddr, 6);
333*9dc70af8SWarner Losh 	if (memcmp (desc->myea, "\0\0\0\0\0\0", 6) == 0) {
334*9dc70af8SWarner Losh 		panic("%s%d: empty ethernet address!",
335*9dc70af8SWarner Losh 		    nif->nif_driver->netif_bname, nif->nif_unit);
336*9dc70af8SWarner Losh 	}
337*9dc70af8SWarner Losh 
338*9dc70af8SWarner Losh 	/* Attempt to get netboot params from the u-boot env. */
339*9dc70af8SWarner Losh 	get_env_net_params();
340*9dc70af8SWarner Losh 	if (myip.s_addr != 0)
341*9dc70af8SWarner Losh 		desc->myip = myip;
342*9dc70af8SWarner Losh 
343*9dc70af8SWarner Losh #if defined(NETIF_DEBUG)
344*9dc70af8SWarner Losh 	printf("network: %s%d attached to %s\n", nif->nif_driver->netif_bname,
345*9dc70af8SWarner Losh 	    nif->nif_unit, ether_sprintf(desc->myea));
346*9dc70af8SWarner Losh #endif
347*9dc70af8SWarner Losh 
348*9dc70af8SWarner Losh 	/* Set correct alignment for TX packets */
349*9dc70af8SWarner Losh 	sc->sc_txbufp = sc->sc_txbuf;
350*9dc70af8SWarner Losh 	if ((unsigned long)sc->sc_txbufp % PKTALIGN)
351*9dc70af8SWarner Losh 		sc->sc_txbufp += PKTALIGN -
352*9dc70af8SWarner Losh 		    (unsigned long)sc->sc_txbufp % PKTALIGN;
353*9dc70af8SWarner Losh }
354*9dc70af8SWarner Losh 
355*9dc70af8SWarner Losh static void
356*9dc70af8SWarner Losh net_end(struct netif *nif)
357*9dc70af8SWarner Losh {
358*9dc70af8SWarner Losh 	struct uboot_softc *sc = nif->nif_devdata;
359*9dc70af8SWarner Losh 	int err;
360*9dc70af8SWarner Losh 
361*9dc70af8SWarner Losh 	if ((err = ub_dev_close(sc->sc_handle)) != 0)
362*9dc70af8SWarner Losh 		panic("%s%d: net_end failed with error %d",
363*9dc70af8SWarner Losh 		    nif->nif_driver->netif_bname, nif->nif_unit, err);
364*9dc70af8SWarner Losh }
365