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