Home | History | Annotate | Line # | Download | only in netboot
if_prom.c revision 1.8.2.1
      1  1.8.2.1  cgd /* $NetBSD: if_prom.c,v 1.8.2.1 1997/06/01 04:14:24 cgd Exp $ */
      2      1.1  cgd 
      3      1.1  cgd /*
      4      1.6  cgd  * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
      5      1.1  cgd  * Copyright (c) 1993 Adam Glass
      6      1.1  cgd  * All rights reserved.
      7      1.1  cgd  *
      8      1.1  cgd  * Redistribution and use in source and binary forms, with or without
      9      1.1  cgd  * modification, are permitted provided that the following conditions
     10      1.1  cgd  * are met:
     11      1.1  cgd  * 1. Redistributions of source code must retain the above copyright
     12      1.1  cgd  *    notice, this list of conditions and the following disclaimer.
     13      1.1  cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1  cgd  *    notice, this list of conditions and the following disclaimer in the
     15      1.1  cgd  *    documentation and/or other materials provided with the distribution.
     16      1.1  cgd  * 3. All advertising materials mentioning features or use of this software
     17      1.1  cgd  *    must display the following acknowledgement:
     18      1.1  cgd  *	This product includes software developed by Adam Glass.
     19      1.1  cgd  * 4. The name of the Author may not be used to endorse or promote products
     20      1.1  cgd  *    derived from this software without specific prior written permission.
     21      1.1  cgd  *
     22      1.1  cgd  * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
     23      1.1  cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24      1.1  cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25      1.1  cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26      1.1  cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27      1.1  cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28      1.1  cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29      1.1  cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30      1.1  cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31      1.1  cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32      1.1  cgd  * SUCH DAMAGE.
     33      1.1  cgd  */
     34      1.1  cgd 
     35      1.1  cgd #include <sys/param.h>
     36      1.1  cgd #include <sys/types.h>
     37      1.1  cgd 
     38      1.1  cgd #include <netinet/in.h>
     39      1.1  cgd #include <netinet/in_systm.h>
     40      1.1  cgd 
     41      1.5  cgd #include <lib/libsa/netif.h>
     42      1.1  cgd #include "include/prom.h"
     43      1.5  cgd #include <lib/libkern/libkern.h>
     44      1.1  cgd 
     45      1.8  cgd #include "stand/common/bbinfo.h"
     46      1.6  cgd 
     47      1.1  cgd int prom_probe();
     48      1.1  cgd int prom_match();
     49      1.1  cgd void prom_init();
     50      1.1  cgd int prom_get();
     51      1.1  cgd int prom_put();
     52      1.1  cgd void prom_end();
     53      1.1  cgd 
     54      1.1  cgd extern struct netif_stats	prom_stats[];
     55      1.1  cgd 
     56      1.1  cgd struct netif_dif prom_ifs[] = {
     57      1.1  cgd /*	dif_unit	dif_nsel	dif_stats	dif_private	*/
     58      1.1  cgd {	0,		1,		&prom_stats[0],	0,		},
     59      1.1  cgd };
     60      1.1  cgd 
     61      1.1  cgd struct netif_stats prom_stats[NENTS(prom_ifs)];
     62      1.1  cgd 
     63      1.6  cgd struct netbbinfo netbbinfo = {
     64      1.6  cgd 	0xfeedbabedeadbeef,			/* magic number */
     65      1.6  cgd 	0,					/* set */
     66      1.6  cgd 	0, 0, 0, 0, 0, 0,			/* ether address */
     67      1.6  cgd 	0,					/* force */
     68      1.6  cgd 	{ 0, },					/* pad2 */
     69      1.6  cgd 	0,					/* cksum */
     70      1.6  cgd 	0xfeedbeefdeadbabe,			/* magic number */
     71      1.6  cgd };
     72      1.6  cgd 
     73      1.1  cgd struct netif_driver prom_netif_driver = {
     74      1.1  cgd 	"prom",			/* netif_bname */
     75      1.1  cgd 	prom_match,		/* netif_match */
     76      1.1  cgd 	prom_probe,		/* netif_probe */
     77      1.1  cgd 	prom_init,		/* netif_init */
     78      1.1  cgd 	prom_get,		/* netif_get */
     79      1.1  cgd 	prom_put,		/* netif_put */
     80      1.1  cgd 	prom_end,		/* netif_end */
     81      1.1  cgd 	prom_ifs,		/* netif_ifs */
     82      1.1  cgd 	NENTS(prom_ifs)		/* netif_nifs */
     83      1.1  cgd };
     84      1.1  cgd 
     85      1.6  cgd int netfd, broken_firmware;
     86      1.1  cgd 
     87      1.1  cgd int
     88      1.1  cgd prom_match(nif, machdep_hint)
     89      1.1  cgd 	struct netif *nif;
     90      1.1  cgd 	void *machdep_hint;
     91      1.1  cgd {
     92      1.1  cgd 
     93      1.1  cgd 	return (1);
     94      1.1  cgd }
     95      1.1  cgd 
     96      1.1  cgd int
     97      1.1  cgd prom_probe(nif, machdep_hint)
     98      1.1  cgd 	struct netif *nif;
     99      1.1  cgd 	void *machdep_hint;
    100      1.1  cgd {
    101      1.1  cgd 
    102      1.1  cgd 	return 0;
    103      1.1  cgd }
    104      1.1  cgd 
    105      1.1  cgd int
    106      1.1  cgd prom_put(desc, pkt, len)
    107      1.1  cgd 	struct iodesc *desc;
    108      1.1  cgd 	void *pkt;
    109      1.1  cgd 	int len;
    110      1.1  cgd {
    111      1.1  cgd 
    112      1.1  cgd 	prom_write(netfd, len, pkt, 0);
    113      1.1  cgd 
    114      1.1  cgd 	return len;
    115      1.1  cgd }
    116      1.1  cgd 
    117      1.1  cgd 
    118      1.1  cgd int
    119      1.1  cgd prom_get(desc, pkt, len, timeout)
    120      1.1  cgd 	struct iodesc *desc;
    121      1.1  cgd 	void *pkt;
    122      1.1  cgd 	int len;
    123      1.1  cgd 	time_t timeout;
    124      1.1  cgd {
    125      1.4  cgd 	prom_return_t ret;
    126      1.4  cgd 	time_t t;
    127      1.4  cgd 	int cc;
    128      1.1  cgd 	char hate[2000];
    129      1.1  cgd 
    130      1.4  cgd 	t = getsecs();
    131      1.4  cgd 	cc = 0;
    132      1.4  cgd 	while (((getsecs() - t) < timeout) && !cc) {
    133      1.6  cgd 		if (broken_firmware)
    134      1.6  cgd 			ret.bits = prom_read(netfd, 0, hate, 0);
    135      1.6  cgd 		else
    136      1.6  cgd 			ret.bits = prom_read(netfd, sizeof hate, hate, 0);
    137      1.1  cgd 		if (ret.u.status == 0)
    138      1.6  cgd 			cc = ret.u.retval;
    139      1.4  cgd 	}
    140      1.6  cgd 	if (broken_firmware)
    141      1.6  cgd 		cc = min(cc, len);
    142      1.6  cgd 	else
    143      1.6  cgd 		cc = len;
    144      1.1  cgd 	bcopy(hate, pkt, cc);
    145      1.1  cgd 
    146      1.4  cgd 	return cc;
    147      1.1  cgd }
    148      1.1  cgd 
    149      1.2  cgd extern char *strchr();
    150      1.2  cgd 
    151      1.1  cgd void
    152      1.1  cgd prom_init(desc, machdep_hint)
    153      1.1  cgd 	struct iodesc *desc;
    154      1.1  cgd 	void *machdep_hint;
    155      1.1  cgd {
    156      1.4  cgd 	prom_return_t ret;
    157      1.4  cgd 	char devname[64];
    158      1.6  cgd 	int devlen, i, netbbinfovalid;
    159      1.2  cgd 	char *enet_addr;
    160      1.6  cgd 	u_int64_t *qp, csum;
    161      1.6  cgd 
    162      1.6  cgd 	broken_firmware = 0;
    163      1.6  cgd 
    164      1.6  cgd 	csum = 0;
    165      1.6  cgd 	for (i = 0, qp = (u_int64_t *)&netbbinfo;
    166      1.6  cgd 	    i < (sizeof netbbinfo / sizeof (u_int64_t)); i++, qp++)
    167      1.6  cgd 		csum += *qp;
    168      1.6  cgd 	netbbinfovalid = (csum == 0);
    169      1.6  cgd 	if (netbbinfovalid)
    170      1.6  cgd 		netbbinfovalid = netbbinfo.set;
    171      1.6  cgd 
    172      1.6  cgd #if 0
    173      1.6  cgd 	printf("netbbinfo ");
    174      1.6  cgd 	if (!netbbinfovalid)
    175      1.6  cgd 		printf("invalid\n");
    176      1.6  cgd 	else
    177      1.6  cgd 		printf("valid: force = %d, ea = %s\n", netbbinfo.force,
    178      1.6  cgd 		    ether_sprintf(netbbinfo.ether_addr));
    179      1.6  cgd #endif
    180      1.1  cgd 
    181      1.4  cgd 	ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof(devname));
    182      1.4  cgd 	devlen = ret.u.retval;
    183      1.2  cgd 
    184      1.2  cgd 	/* Ethernet address is the 9th component of the booted_dev string. */
    185      1.2  cgd 	enet_addr = devname;
    186      1.2  cgd 	for (i = 0; i < 8; i++) {
    187      1.2  cgd 		enet_addr = strchr(enet_addr, ' ');
    188      1.2  cgd 		if (enet_addr == NULL) {
    189      1.7  cgd 			printf("boot: boot device name does not contain ethernet address.\n");
    190      1.3  cgd 			goto punt;
    191      1.2  cgd 		}
    192      1.2  cgd 		enet_addr++;
    193      1.2  cgd 	}
    194      1.2  cgd 	if (enet_addr != NULL) {
    195      1.2  cgd 		int hv, lv;
    196      1.2  cgd 
    197      1.2  cgd #define	dval(c)	(((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
    198      1.2  cgd 		 (((c) >= 'A' && (c) <= 'F') ? (10 + (c) - 'A') : \
    199      1.2  cgd 		  (((c) >= 'a' && (c) <= 'f') ? (10 + (c) - 'a') : -1)))
    200      1.2  cgd 
    201      1.2  cgd 		for (i = 0; i < 6; i++) {
    202      1.2  cgd 			hv = dval(*enet_addr); enet_addr++;
    203      1.2  cgd 			lv = dval(*enet_addr); enet_addr++;
    204      1.2  cgd 			enet_addr++;
    205      1.2  cgd 
    206      1.2  cgd 			if (hv == -1 || lv == -1) {
    207      1.7  cgd 				printf("boot: boot device name contains bogus ethernet address.\n");
    208      1.3  cgd 				goto punt;
    209      1.2  cgd 			}
    210      1.2  cgd 
    211      1.2  cgd 			desc->myea[i] = (hv << 4) | lv;
    212      1.2  cgd 		}
    213      1.2  cgd #undef dval
    214      1.2  cgd 	}
    215      1.2  cgd 
    216      1.6  cgd 	if (netbbinfovalid && netbbinfo.force) {
    217      1.7  cgd 		printf("boot: using hard-coded ethernet address (forced).\n");
    218      1.6  cgd 		bcopy(netbbinfo.ether_addr, desc->myea, sizeof desc->myea);
    219      1.6  cgd 	}
    220      1.6  cgd 
    221      1.6  cgd gotit:
    222      1.3  cgd 	printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea));
    223      1.3  cgd 
    224      1.4  cgd 	ret.bits = prom_open(devname, devlen + 1);
    225      1.4  cgd 	if (ret.u.status) {
    226      1.4  cgd 		printf("prom_init: open failed: %d\n", ret.u.status);
    227      1.6  cgd 		goto reallypunt;
    228      1.4  cgd 	}
    229      1.4  cgd 	netfd = ret.u.retval;
    230      1.3  cgd 	return;
    231      1.1  cgd 
    232      1.3  cgd punt:
    233      1.6  cgd 	broken_firmware = 1;
    234      1.6  cgd         if (netbbinfovalid) {
    235      1.7  cgd                 printf("boot: using hard-coded ethernet address.\n");
    236      1.6  cgd                 bcopy(netbbinfo.ether_addr, desc->myea, sizeof desc->myea);
    237      1.6  cgd                 goto gotit;
    238      1.6  cgd         }
    239      1.6  cgd 
    240      1.6  cgd reallypunt:
    241      1.7  cgd 	printf("\n");
    242      1.3  cgd 	printf("Boot device name was: \"%s\"\n", devname);
    243      1.3  cgd 	printf("\n");
    244      1.6  cgd 	printf("Your firmware may be too old to network-boot NetBSD/Alpha,\n");
    245      1.6  cgd 	printf("or you might have to hard-code an ethernet address into\n");
    246      1.6  cgd 	printf("your network boot block with setnetbootinfo(8).\n");
    247      1.3  cgd 	halt();
    248      1.1  cgd }
    249      1.1  cgd 
    250      1.1  cgd void
    251      1.1  cgd prom_end(nif)
    252      1.1  cgd 	struct netif *nif;
    253      1.1  cgd {
    254      1.1  cgd 
    255      1.1  cgd 	prom_close(netfd);
    256      1.1  cgd }
    257