1 1.19 mrg /* $NetBSD: eehandlers.c,v 1.19 2019/10/05 23:30:22 mrg Exp $ */ 2 1.1 thorpej 3 1.2 thorpej /*- 4 1.2 thorpej * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 1.1 thorpej * All rights reserved. 6 1.1 thorpej * 7 1.2 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.2 thorpej * by Jason R. Thorpe. 9 1.2 thorpej * 10 1.1 thorpej * Redistribution and use in source and binary forms, with or without 11 1.1 thorpej * modification, are permitted provided that the following conditions 12 1.1 thorpej * are met: 13 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.1 thorpej * notice, this list of conditions and the following disclaimer. 15 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.1 thorpej * documentation and/or other materials provided with the distribution. 18 1.1 thorpej * 19 1.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.5 jtc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.5 jtc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.1 thorpej */ 31 1.1 thorpej 32 1.1 thorpej #include <sys/types.h> 33 1.1 thorpej #include <ctype.h> 34 1.1 thorpej #include <err.h> 35 1.1 thorpej #include <errno.h> 36 1.1 thorpej #include <fcntl.h> 37 1.1 thorpej #include <stdio.h> 38 1.1 thorpej #include <stdlib.h> 39 1.1 thorpej #include <string.h> 40 1.1 thorpej #include <time.h> 41 1.1 thorpej #include <unistd.h> 42 1.11 christos #include <util.h> 43 1.16 christos #include <sys/inttypes.h> 44 1.1 thorpej 45 1.1 thorpej #include <machine/eeprom.h> 46 1.1 thorpej 47 1.1 thorpej #include "defs.h" 48 1.1 thorpej 49 1.1 thorpej extern char *path_eeprom; 50 1.1 thorpej extern int eval; 51 1.1 thorpej extern int update_checksums; 52 1.1 thorpej extern int ignore_checksum; 53 1.1 thorpej extern int fix_checksum; 54 1.1 thorpej extern int cksumfail; 55 1.1 thorpej extern u_short writecount; 56 1.1 thorpej 57 1.1 thorpej static char err_str[BUFSIZE]; 58 1.1 thorpej 59 1.18 joerg static void badval(const struct keytabent *, char *); 60 1.18 joerg static int doio(const struct keytabent *, u_char *, ssize_t, int); 61 1.1 thorpej 62 1.18 joerg static u_char ee_checksum(u_char *, size_t); 63 1.18 joerg static void ee_hwupdate(const struct keytabent *, char *); 64 1.18 joerg static void ee_num8(const struct keytabent *, char *); 65 1.18 joerg static void ee_num16(const struct keytabent *, char *); 66 1.18 joerg static void ee_screensize(const struct keytabent *, char *); 67 1.18 joerg static void ee_truefalse(const struct keytabent *, char *); 68 1.18 joerg static void ee_bootdev(const struct keytabent *, char *); 69 1.18 joerg static void ee_kbdtype(const struct keytabent *, char *); 70 1.18 joerg static void ee_constype(const struct keytabent *, char *); 71 1.18 joerg static void ee_diagpath(const struct keytabent *, char *); 72 1.18 joerg static void ee_banner(const struct keytabent *, char *); 73 1.18 joerg static void ee_notsupp(const struct keytabent *, char *); 74 1.18 joerg 75 1.18 joerg static const struct keytabent eekeytab[] = { 76 1.9 mrg { "hwupdate", 0x10, ee_hwupdate }, 77 1.9 mrg { "memsize", 0x14, ee_num8 }, 78 1.9 mrg { "memtest", 0x15, ee_num8 }, 79 1.9 mrg { "scrsize", 0x16, ee_screensize }, 80 1.9 mrg { "watchdog_reboot", 0x17, ee_truefalse }, 81 1.9 mrg { "default_boot", 0x18, ee_truefalse }, 82 1.9 mrg { "bootdev", 0x19, ee_bootdev }, 83 1.9 mrg { "kbdtype", 0x1e, ee_kbdtype }, 84 1.9 mrg { "console", 0x1f, ee_constype }, 85 1.9 mrg { "keyclick", 0x21, ee_truefalse }, 86 1.9 mrg { "diagdev", 0x22, ee_bootdev }, 87 1.9 mrg { "diagpath", 0x28, ee_diagpath }, 88 1.9 mrg { "columns", 0x50, ee_num8 }, 89 1.9 mrg { "rows", 0x51, ee_num8 }, 90 1.9 mrg { "ttya_use_baud", 0x58, ee_truefalse }, 91 1.9 mrg { "ttya_baud", 0x59, ee_num16 }, 92 1.9 mrg { "ttya_no_rtsdtr", 0x5b, ee_truefalse }, 93 1.9 mrg { "ttyb_use_baud", 0x60, ee_truefalse }, 94 1.9 mrg { "ttyb_baud", 0x61, ee_num16 }, 95 1.9 mrg { "ttyb_no_rtsdtr", 0x63, ee_truefalse }, 96 1.9 mrg { "banner", 0x68, ee_banner }, 97 1.9 mrg { "secure", 0, ee_notsupp }, 98 1.9 mrg { "bad_login", 0, ee_notsupp }, 99 1.9 mrg { "password", 0, ee_notsupp }, 100 1.9 mrg { NULL, 0, ee_notsupp }, 101 1.9 mrg }; 102 1.9 mrg 103 1.1 thorpej #define BARF(kt) { \ 104 1.1 thorpej badval((kt), arg); \ 105 1.1 thorpej ++eval; \ 106 1.1 thorpej return; \ 107 1.1 thorpej } 108 1.1 thorpej 109 1.1 thorpej #define FAILEDREAD(kt) { \ 110 1.7 itojun warnx("%s", err_str); \ 111 1.1 thorpej warnx("failed to read field `%s'", (kt)->kt_keyword); \ 112 1.1 thorpej ++eval; \ 113 1.1 thorpej return; \ 114 1.1 thorpej } 115 1.1 thorpej 116 1.1 thorpej #define FAILEDWRITE(kt) { \ 117 1.7 itojun warnx("%s", err_str); \ 118 1.1 thorpej warnx("failed to update field `%s'", (kt)->kt_keyword); \ 119 1.1 thorpej ++eval; \ 120 1.1 thorpej return; \ 121 1.9 mrg } 122 1.9 mrg 123 1.9 mrg void 124 1.18 joerg ee_action(char *keyword, char *arg) 125 1.9 mrg { 126 1.18 joerg const struct keytabent *ktent; 127 1.9 mrg 128 1.9 mrg for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) { 129 1.9 mrg if (strcmp(ktent->kt_keyword, keyword) == 0) { 130 1.9 mrg (*ktent->kt_handler)(ktent, arg); 131 1.9 mrg return; 132 1.9 mrg } 133 1.9 mrg } 134 1.9 mrg 135 1.9 mrg warnx("unknown keyword %s", keyword); 136 1.9 mrg ++eval; 137 1.9 mrg } 138 1.9 mrg 139 1.9 mrg void 140 1.18 joerg ee_dump(void) 141 1.9 mrg { 142 1.18 joerg const struct keytabent *ktent; 143 1.9 mrg 144 1.9 mrg for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) 145 1.9 mrg (*ktent->kt_handler)(ktent, NULL); 146 1.1 thorpej } 147 1.1 thorpej 148 1.18 joerg static void 149 1.18 joerg ee_hwupdate(const struct keytabent *ktent, char *arg) 150 1.1 thorpej { 151 1.16 christos uint32_t hwtime; 152 1.1 thorpej time_t t; 153 1.1 thorpej char *cp, *cp2; 154 1.1 thorpej 155 1.1 thorpej if (arg) { 156 1.1 thorpej if ((strcmp(arg, "now") == 0) || 157 1.1 thorpej (strcmp(arg, "today") == 0)) { 158 1.1 thorpej if ((t = time(NULL)) == (time_t)(-1)) { 159 1.1 thorpej warnx("can't get current time"); 160 1.1 thorpej ++eval; 161 1.1 thorpej return; 162 1.1 thorpej } 163 1.1 thorpej } else 164 1.12 christos if ((t = parsedate(arg, NULL, NULL)) == (time_t)(-1)) 165 1.1 thorpej BARF(ktent); 166 1.16 christos hwtime = (uint32_t)t; /* XXX 32 bit time_t on hardware */ 167 1.16 christos if (hwtime != t) 168 1.16 christos warnx("time overflow"); 169 1.1 thorpej 170 1.16 christos if (doio(ktent, (u_char *)&hwtime, sizeof(hwtime), IO_WRITE)) 171 1.1 thorpej FAILEDWRITE(ktent); 172 1.16 christos } else { 173 1.16 christos if (doio(ktent, (u_char *)&hwtime, sizeof(hwtime), IO_READ)) 174 1.1 thorpej FAILEDREAD(ktent); 175 1.16 christos t = (time_t)hwtime; /* XXX 32 bit time_t on hardware */ 176 1.16 christos } 177 1.1 thorpej 178 1.1 thorpej cp = ctime(&t); 179 1.16 christos if (cp != NULL && (cp2 = strrchr(cp, '\n')) != NULL) 180 1.1 thorpej *cp2 = '\0'; 181 1.1 thorpej 182 1.16 christos printf("%s=%" PRId64, ktent->kt_keyword, (int64_t)t); 183 1.16 christos if (cp != NULL) 184 1.16 christos printf(" (%s)", cp); 185 1.16 christos printf("\n"); 186 1.1 thorpej } 187 1.1 thorpej 188 1.18 joerg static void 189 1.18 joerg ee_num8(const struct keytabent *ktent, char *arg) 190 1.1 thorpej { 191 1.1 thorpej u_char num8 = 0; 192 1.1 thorpej u_int num32; 193 1.1 thorpej int i; 194 1.1 thorpej 195 1.1 thorpej if (arg) { 196 1.15 nakayama for (i = 0; i < (int)strlen(arg) - 1; ++i) 197 1.10 dsl if (!isdigit((unsigned char)arg[i])) 198 1.1 thorpej BARF(ktent); 199 1.1 thorpej num32 = atoi(arg); 200 1.1 thorpej if (num32 > 0xff) 201 1.1 thorpej BARF(ktent); 202 1.1 thorpej num8 += num32; 203 1.1 thorpej if (doio(ktent, &num8, sizeof(num8), IO_WRITE)) 204 1.1 thorpej FAILEDWRITE(ktent); 205 1.1 thorpej } else 206 1.1 thorpej if (doio(ktent, &num8, sizeof(num8), IO_READ)) 207 1.1 thorpej FAILEDREAD(ktent); 208 1.1 thorpej 209 1.1 thorpej printf("%s=%d\n", ktent->kt_keyword, num8); 210 1.1 thorpej } 211 1.1 thorpej 212 1.18 joerg static void 213 1.18 joerg ee_num16(const struct keytabent *ktent, char *arg) 214 1.1 thorpej { 215 1.1 thorpej u_int16_t num16 = 0; 216 1.1 thorpej u_int num32; 217 1.1 thorpej int i; 218 1.1 thorpej 219 1.1 thorpej if (arg) { 220 1.15 nakayama for (i = 0; i < (int)strlen(arg) - 1; ++i) 221 1.10 dsl if (!isdigit((unsigned char)arg[i])) 222 1.1 thorpej BARF(ktent); 223 1.1 thorpej num32 = atoi(arg); 224 1.1 thorpej if (num32 > 0xffff) 225 1.1 thorpej BARF(ktent); 226 1.1 thorpej num16 += num32; 227 1.1 thorpej if (doio(ktent, (u_char *)&num16, sizeof(num16), IO_WRITE)) 228 1.1 thorpej FAILEDWRITE(ktent); 229 1.1 thorpej } else 230 1.1 thorpej if (doio(ktent, (u_char *)&num16, sizeof(num16), IO_READ)) 231 1.1 thorpej FAILEDREAD(ktent); 232 1.1 thorpej 233 1.1 thorpej printf("%s=%d\n", ktent->kt_keyword, num16); 234 1.1 thorpej } 235 1.1 thorpej 236 1.18 joerg static const struct strvaltabent scrsizetab[] = { 237 1.1 thorpej { "1152x900", EE_SCR_1152X900 }, 238 1.1 thorpej { "1024x1024", EE_SCR_1024X1024 }, 239 1.1 thorpej { "1600x1280", EE_SCR_1600X1280 }, 240 1.1 thorpej { "1440x1440", EE_SCR_1440X1440 }, 241 1.1 thorpej { NULL, 0 }, 242 1.1 thorpej }; 243 1.1 thorpej 244 1.18 joerg static void 245 1.18 joerg ee_screensize(const struct keytabent *ktent, char *arg) 246 1.1 thorpej { 247 1.18 joerg const struct strvaltabent *svp; 248 1.1 thorpej u_char scsize; 249 1.1 thorpej 250 1.1 thorpej if (arg) { 251 1.1 thorpej for (svp = scrsizetab; svp->sv_str != NULL; ++svp) 252 1.1 thorpej if (strcmp(svp->sv_str, arg) == 0) 253 1.1 thorpej break; 254 1.1 thorpej if (svp->sv_str == NULL) 255 1.1 thorpej BARF(ktent); 256 1.1 thorpej 257 1.1 thorpej scsize = svp->sv_val; 258 1.1 thorpej if (doio(ktent, &scsize, sizeof(scsize), IO_WRITE)) 259 1.1 thorpej FAILEDWRITE(ktent); 260 1.1 thorpej } else { 261 1.1 thorpej if (doio(ktent, &scsize, sizeof(scsize), IO_READ)) 262 1.1 thorpej FAILEDREAD(ktent); 263 1.1 thorpej 264 1.1 thorpej for (svp = scrsizetab; svp->sv_str != NULL; ++svp) 265 1.1 thorpej if (svp->sv_val == scsize) 266 1.1 thorpej break; 267 1.1 thorpej if (svp->sv_str == NULL) { 268 1.1 thorpej warnx("unknown %s value %d", ktent->kt_keyword, 269 1.1 thorpej scsize); 270 1.1 thorpej return; 271 1.1 thorpej } 272 1.1 thorpej } 273 1.1 thorpej printf("%s=%s\n", ktent->kt_keyword, svp->sv_str); 274 1.1 thorpej } 275 1.1 thorpej 276 1.18 joerg static const struct strvaltabent truthtab[] = { 277 1.1 thorpej { "true", EE_TRUE }, 278 1.1 thorpej { "false", EE_FALSE }, 279 1.1 thorpej { NULL, 0 }, 280 1.1 thorpej }; 281 1.1 thorpej 282 1.18 joerg static void 283 1.18 joerg ee_truefalse(const struct keytabent *ktent, char *arg) 284 1.1 thorpej { 285 1.18 joerg const struct strvaltabent *svp; 286 1.1 thorpej u_char truth; 287 1.1 thorpej 288 1.1 thorpej if (arg) { 289 1.1 thorpej for (svp = truthtab; svp->sv_str != NULL; ++svp) 290 1.1 thorpej if (strcmp(svp->sv_str, arg) == 0) 291 1.1 thorpej break; 292 1.1 thorpej if (svp->sv_str == NULL) 293 1.1 thorpej BARF(ktent); 294 1.1 thorpej 295 1.1 thorpej truth = svp->sv_val; 296 1.1 thorpej if (doio(ktent, &truth, sizeof(truth), IO_WRITE)) 297 1.1 thorpej FAILEDWRITE(ktent); 298 1.1 thorpej } else { 299 1.1 thorpej if (doio(ktent, &truth, sizeof(truth), IO_READ)) 300 1.1 thorpej FAILEDREAD(ktent); 301 1.1 thorpej 302 1.1 thorpej for (svp = truthtab; svp->sv_str != NULL; ++svp) 303 1.1 thorpej if (svp->sv_val == truth) 304 1.1 thorpej break; 305 1.1 thorpej if (svp->sv_str == NULL) { 306 1.1 thorpej warnx("unknown truth value 0x%x for %s", truth, 307 1.1 thorpej ktent->kt_keyword); 308 1.1 thorpej return; 309 1.1 thorpej } 310 1.1 thorpej } 311 1.1 thorpej printf("%s=%s\n", ktent->kt_keyword, svp->sv_str); 312 1.1 thorpej } 313 1.1 thorpej 314 1.18 joerg static void 315 1.18 joerg ee_bootdev(const struct keytabent *ktent, char *arg) 316 1.1 thorpej { 317 1.1 thorpej u_char dev[5]; 318 1.1 thorpej int i; 319 1.1 thorpej size_t arglen; 320 1.1 thorpej char *cp; 321 1.1 thorpej 322 1.1 thorpej if (arg) { 323 1.1 thorpej /* 324 1.1 thorpej * The format of the string we accept is the following: 325 1.1 thorpej * cc(n,n,n) 326 1.1 thorpej * where: 327 1.1 thorpej * c -- an alphabetical character [a-z] 328 1.1 thorpej * n -- a number in hexadecimal, between 0 and ff, 329 1.1 thorpej * with no leading `0x'. 330 1.1 thorpej */ 331 1.1 thorpej arglen = strlen(arg); 332 1.1 thorpej if (arglen < 9 || arglen > 12 || arg[2] != '(' || 333 1.1 thorpej arg[arglen - 1] != ')') 334 1.1 thorpej BARF(ktent); 335 1.1 thorpej 336 1.1 thorpej /* Handle the first 2 letters. */ 337 1.1 thorpej for (i = 0; i < 2; ++i) { 338 1.1 thorpej if (arg[i] < 'a' || arg[i] > 'z') 339 1.1 thorpej BARF(ktent); 340 1.1 thorpej dev[i] = (u_char)arg[i]; 341 1.1 thorpej } 342 1.1 thorpej 343 1.1 thorpej /* Handle the 3 `0x'-less hex values. */ 344 1.1 thorpej cp = &arg[3]; 345 1.1 thorpej for (i = 2; i < 5; ++i) { 346 1.1 thorpej if (*cp == '\0') 347 1.1 thorpej BARF(ktent); 348 1.1 thorpej 349 1.1 thorpej if (*cp >= '0' && *cp <= '9') 350 1.1 thorpej dev[i] = *cp++ - '0'; 351 1.1 thorpej else if (*cp >= 'a' && *cp <= 'f') 352 1.1 thorpej dev[i] = 10 + (*cp++ - 'a'); 353 1.1 thorpej else 354 1.1 thorpej BARF(ktent); 355 1.1 thorpej 356 1.1 thorpej /* Deal with a second digit. */ 357 1.1 thorpej if (*cp >= '0' && *cp <= '9') { 358 1.1 thorpej dev[i] <<= 4; 359 1.1 thorpej dev[i] &= 0xf0; 360 1.1 thorpej dev[i] += *cp++ - '0'; 361 1.1 thorpej } else if (*cp >= 'a' && *cp <= 'f') { 362 1.1 thorpej dev[i] <<= 4; 363 1.1 thorpej dev[i] &= 0xf0; 364 1.1 thorpej dev[i] += 10 + (*cp++ - 'a'); 365 1.1 thorpej } 366 1.1 thorpej 367 1.1 thorpej /* Ensure we have the correct delimiter. */ 368 1.1 thorpej if ((*cp == ',' && i < 4) || (*cp == ')' && i == 4)) { 369 1.1 thorpej ++cp; 370 1.1 thorpej continue; 371 1.1 thorpej } else 372 1.1 thorpej BARF(ktent); 373 1.1 thorpej } 374 1.1 thorpej if (doio(ktent, (u_char *)&dev[0], sizeof(dev), IO_WRITE)) 375 1.1 thorpej FAILEDWRITE(ktent); 376 1.1 thorpej } else 377 1.1 thorpej if (doio(ktent, (u_char *)&dev[0], sizeof(dev), IO_READ)) 378 1.1 thorpej FAILEDREAD(ktent); 379 1.1 thorpej 380 1.1 thorpej printf("%s=%c%c(%x,%x,%x)\n", ktent->kt_keyword, dev[0], 381 1.1 thorpej dev[1], dev[2], dev[3], dev[4]); 382 1.1 thorpej } 383 1.1 thorpej 384 1.18 joerg static void 385 1.18 joerg ee_kbdtype(const struct keytabent *ktent, char *arg) 386 1.1 thorpej { 387 1.1 thorpej u_char kbd = 0; 388 1.1 thorpej u_int kbd2; 389 1.1 thorpej int i; 390 1.1 thorpej 391 1.1 thorpej if (arg) { 392 1.15 nakayama for (i = 0; i < (int)strlen(arg) - 1; ++i) 393 1.10 dsl if (!isdigit((unsigned char)arg[i])) 394 1.1 thorpej BARF(ktent); 395 1.1 thorpej kbd2 = atoi(arg); 396 1.1 thorpej if (kbd2 > 0xff) 397 1.1 thorpej BARF(ktent); 398 1.1 thorpej kbd += kbd2; 399 1.1 thorpej if (doio(ktent, &kbd, sizeof(kbd), IO_WRITE)) 400 1.1 thorpej FAILEDWRITE(ktent); 401 1.1 thorpej } else 402 1.1 thorpej if (doio(ktent, &kbd, sizeof(kbd), IO_READ)) 403 1.1 thorpej FAILEDREAD(ktent); 404 1.1 thorpej 405 1.1 thorpej printf("%s=%d (%s)\n", ktent->kt_keyword, kbd, kbd ? "other" : "Sun"); 406 1.1 thorpej } 407 1.1 thorpej 408 1.18 joerg static const struct strvaltabent constab[] = { 409 1.1 thorpej { "b&w", EE_CONS_BW }, 410 1.1 thorpej { "ttya", EE_CONS_TTYA }, 411 1.1 thorpej { "ttyb", EE_CONS_TTYB }, 412 1.1 thorpej { "color", EE_CONS_COLOR }, 413 1.1 thorpej { "p4opt", EE_CONS_P4OPT }, 414 1.1 thorpej { NULL, 0 }, 415 1.1 thorpej }; 416 1.1 thorpej 417 1.18 joerg static void 418 1.18 joerg ee_constype(const struct keytabent *ktent, char *arg) 419 1.1 thorpej { 420 1.18 joerg const struct strvaltabent *svp; 421 1.1 thorpej u_char cons; 422 1.1 thorpej 423 1.1 thorpej if (arg) { 424 1.1 thorpej for (svp = constab; svp->sv_str != NULL; ++svp) 425 1.1 thorpej if (strcmp(svp->sv_str, arg) == 0) 426 1.1 thorpej break; 427 1.1 thorpej if (svp->sv_str == NULL) 428 1.1 thorpej BARF(ktent); 429 1.1 thorpej 430 1.1 thorpej cons = svp->sv_val; 431 1.1 thorpej if (doio(ktent, &cons, sizeof(cons), IO_WRITE)) 432 1.1 thorpej FAILEDWRITE(ktent); 433 1.1 thorpej } else { 434 1.1 thorpej if (doio(ktent, &cons, sizeof(cons), IO_READ)) 435 1.1 thorpej FAILEDREAD(ktent); 436 1.1 thorpej 437 1.1 thorpej for (svp = constab; svp->sv_str != NULL; ++svp) 438 1.1 thorpej if (svp->sv_val == cons) 439 1.1 thorpej break; 440 1.1 thorpej if (svp->sv_str == NULL) { 441 1.1 thorpej warnx("unknown type 0x%x for %s", cons, 442 1.1 thorpej ktent->kt_keyword); 443 1.1 thorpej return; 444 1.1 thorpej } 445 1.1 thorpej } 446 1.1 thorpej printf("%s=%s\n", ktent->kt_keyword, svp->sv_str); 447 1.1 thorpej 448 1.1 thorpej } 449 1.1 thorpej 450 1.18 joerg static void 451 1.18 joerg ee_diagpath(const struct keytabent *ktent, char *arg) 452 1.1 thorpej { 453 1.1 thorpej char path[40]; 454 1.1 thorpej 455 1.6 lukem memset(path, 0, sizeof(path)); 456 1.1 thorpej if (arg) { 457 1.1 thorpej if (strlen(arg) > sizeof(path)) 458 1.1 thorpej BARF(ktent); 459 1.3 mrg memcpy(path, arg, sizeof path); 460 1.1 thorpej if (doio(ktent, (u_char *)&path[0], sizeof(path), IO_WRITE)) 461 1.1 thorpej FAILEDWRITE(ktent); 462 1.1 thorpej } else 463 1.1 thorpej if (doio(ktent, (u_char *)&path[0], sizeof(path), IO_READ)) 464 1.1 thorpej FAILEDREAD(ktent); 465 1.1 thorpej 466 1.1 thorpej printf("%s=%s\n", ktent->kt_keyword, path); 467 1.1 thorpej } 468 1.1 thorpej 469 1.18 joerg static void 470 1.18 joerg ee_banner(const struct keytabent *ktent, char *arg) 471 1.1 thorpej { 472 1.1 thorpej char string[80]; 473 1.1 thorpej u_char enable; 474 1.1 thorpej struct keytabent kt; 475 1.1 thorpej 476 1.1 thorpej kt.kt_keyword = "enable_banner"; 477 1.1 thorpej kt.kt_offset = EE_BANNER_ENABLE_LOC; 478 1.1 thorpej kt.kt_handler = ee_notsupp; 479 1.1 thorpej 480 1.3 mrg memset(string, '\0', sizeof(string)); 481 1.1 thorpej if (arg) { 482 1.1 thorpej if (strlen(arg) > sizeof(string)) 483 1.1 thorpej BARF(ktent); 484 1.1 thorpej if (*arg != '\0') { 485 1.1 thorpej enable = EE_TRUE; 486 1.3 mrg memcpy(string, arg, sizeof string); 487 1.1 thorpej if (doio(ktent, (u_char *)string, 488 1.1 thorpej sizeof(string), IO_WRITE)) 489 1.1 thorpej FAILEDWRITE(ktent); 490 1.1 thorpej } else { 491 1.1 thorpej enable = EE_FALSE; 492 1.1 thorpej if (doio(ktent, (u_char *)string, 493 1.1 thorpej sizeof(string), IO_READ)) 494 1.1 thorpej FAILEDREAD(ktent); 495 1.1 thorpej } 496 1.1 thorpej 497 1.1 thorpej if (doio(&kt, &enable, sizeof(enable), IO_WRITE)) 498 1.1 thorpej FAILEDWRITE(&kt); 499 1.1 thorpej } else { 500 1.1 thorpej if (doio(ktent, (u_char *)string, sizeof(string), IO_READ)) 501 1.1 thorpej FAILEDREAD(ktent); 502 1.1 thorpej if (doio(&kt, &enable, sizeof(enable), IO_READ)) 503 1.1 thorpej FAILEDREAD(&kt); 504 1.1 thorpej } 505 1.1 thorpej printf("%s=%s (%s)\n", ktent->kt_keyword, string, 506 1.1 thorpej enable == EE_TRUE ? "enabled" : "disabled"); 507 1.1 thorpej } 508 1.1 thorpej 509 1.1 thorpej /* ARGSUSED */ 510 1.18 joerg static void 511 1.18 joerg ee_notsupp(const struct keytabent *ktent, char *arg) 512 1.1 thorpej { 513 1.1 thorpej 514 1.1 thorpej warnx("field `%s' not yet supported", ktent->kt_keyword); 515 1.1 thorpej } 516 1.1 thorpej 517 1.1 thorpej static void 518 1.18 joerg badval(const struct keytabent *ktent, char *arg) 519 1.1 thorpej { 520 1.1 thorpej 521 1.1 thorpej warnx("inappropriate value `%s' for field `%s'", arg, 522 1.1 thorpej ktent->kt_keyword); 523 1.1 thorpej } 524 1.1 thorpej 525 1.1 thorpej static int 526 1.18 joerg doio(const struct keytabent *ktent, u_char *buf, ssize_t len, int wr) 527 1.1 thorpej { 528 1.1 thorpej int fd, rval = 0; 529 1.1 thorpej u_char *buf2; 530 1.1 thorpej 531 1.1 thorpej buf2 = (u_char *)calloc(1, len); 532 1.1 thorpej if (buf2 == NULL) { 533 1.19 mrg strncpy(err_str, "memory allocation failed", sizeof err_str); 534 1.1 thorpej return (1); 535 1.1 thorpej } 536 1.1 thorpej 537 1.1 thorpej fd = open(path_eeprom, wr == IO_WRITE ? O_RDWR : O_RDONLY, 0640); 538 1.1 thorpej if (fd < 0) { 539 1.3 mrg (void)snprintf(err_str, sizeof err_str, "open: %s: %s", path_eeprom, 540 1.1 thorpej strerror(errno)); 541 1.1 thorpej free(buf2); 542 1.1 thorpej return (1); 543 1.1 thorpej } 544 1.1 thorpej 545 1.1 thorpej if (lseek(fd, (off_t)ktent->kt_offset, SEEK_SET) < (off_t)0) { 546 1.4 thorpej (void)snprintf(err_str, sizeof err_str, "lseek: %s: %s", 547 1.3 mrg path_eeprom, strerror(errno)); 548 1.1 thorpej rval = 1; 549 1.1 thorpej goto done; 550 1.1 thorpej } 551 1.1 thorpej 552 1.1 thorpej if (read(fd, buf2, len) != len) { 553 1.3 mrg (void)snprintf(err_str, sizeof err_str, "read: %s: %s", 554 1.3 mrg path_eeprom, strerror(errno)); 555 1.1 thorpej return (1); 556 1.1 thorpej } 557 1.1 thorpej 558 1.1 thorpej if (wr == IO_WRITE) { 559 1.6 lukem if (memcmp(buf, buf2, len) == 0) 560 1.1 thorpej goto done; 561 1.1 thorpej 562 1.1 thorpej if (lseek(fd, (off_t)ktent->kt_offset, SEEK_SET) < (off_t)0) { 563 1.3 mrg (void)snprintf(err_str, sizeof err_str, "lseek: %s: %s", 564 1.3 mrg path_eeprom, strerror(errno)); 565 1.1 thorpej rval = 1; 566 1.1 thorpej goto done; 567 1.1 thorpej } 568 1.1 thorpej 569 1.1 thorpej ++update_checksums; 570 1.1 thorpej if (write(fd, buf, len) < 0) { 571 1.3 mrg (void)snprintf(err_str, sizeof err_str, "write: %s: %s", 572 1.3 mrg path_eeprom, strerror(errno)); 573 1.1 thorpej rval = 1; 574 1.1 thorpej goto done; 575 1.1 thorpej } 576 1.1 thorpej } else 577 1.6 lukem memmove(buf, buf2, len); 578 1.1 thorpej 579 1.1 thorpej done: 580 1.1 thorpej free(buf2); 581 1.1 thorpej (void)close(fd); 582 1.1 thorpej return (rval); 583 1.1 thorpej } 584 1.1 thorpej 585 1.1 thorpej /* 586 1.1 thorpej * Read from eeLastHwUpdate to just before eeReserved. Calculate 587 1.1 thorpej * a checksum, and deposit 3 copies of it sequentially starting at 588 1.1 thorpej * eeChecksum[0]. Increment the write count, and deposit 3 copies 589 1.1 thorpej * of it sequentially starting at eeWriteCount[0]. 590 1.1 thorpej */ 591 1.1 thorpej void 592 1.18 joerg ee_updatechecksums(void) 593 1.1 thorpej { 594 1.1 thorpej struct keytabent kt; 595 1.1 thorpej u_char checkme[EE_SIZE - EE_HWUPDATE_LOC]; 596 1.1 thorpej u_char checksum; 597 1.1 thorpej int i; 598 1.1 thorpej 599 1.1 thorpej kt.kt_keyword = "eeprom contents"; 600 1.1 thorpej kt.kt_offset = EE_HWUPDATE_LOC; 601 1.1 thorpej kt.kt_handler = ee_notsupp; 602 1.1 thorpej 603 1.1 thorpej if (doio(&kt, checkme, sizeof(checkme), IO_READ)) { 604 1.1 thorpej cksumfail = 1; 605 1.1 thorpej FAILEDREAD(&kt); 606 1.1 thorpej } 607 1.1 thorpej 608 1.1 thorpej checksum = ee_checksum(checkme, sizeof(checkme)); 609 1.1 thorpej 610 1.1 thorpej kt.kt_keyword = "eeprom checksum"; 611 1.1 thorpej for (i = 0; i < 4; ++i) { 612 1.1 thorpej kt.kt_offset = EE_CKSUM_LOC + (i * sizeof(checksum)); 613 1.1 thorpej if (doio(&kt, &checksum, sizeof(checksum), IO_WRITE)) { 614 1.1 thorpej cksumfail = 1; 615 1.1 thorpej FAILEDWRITE(&kt); 616 1.1 thorpej } 617 1.1 thorpej } 618 1.1 thorpej 619 1.1 thorpej kt.kt_keyword = "eeprom writecount"; 620 1.1 thorpej for (i = 0; i < 4; ++i) { 621 1.1 thorpej kt.kt_offset = EE_WC_LOC + (i * sizeof(writecount)); 622 1.1 thorpej if (doio(&kt, (u_char *)&writecount, sizeof(writecount), 623 1.1 thorpej IO_WRITE)) { 624 1.1 thorpej cksumfail = 1; 625 1.1 thorpej FAILEDWRITE(&kt); 626 1.1 thorpej } 627 1.1 thorpej } 628 1.1 thorpej } 629 1.1 thorpej 630 1.1 thorpej void 631 1.18 joerg ee_verifychecksums(void) 632 1.1 thorpej { 633 1.1 thorpej struct keytabent kt; 634 1.1 thorpej u_char checkme[EE_SIZE - EE_HWUPDATE_LOC]; 635 1.1 thorpej u_char checksum, ochecksum[3]; 636 1.1 thorpej u_short owritecount[3]; 637 1.1 thorpej 638 1.1 thorpej /* 639 1.1 thorpej * Verify that the EEPROM's write counts match, and update the 640 1.1 thorpej * global copy for use later. 641 1.1 thorpej */ 642 1.1 thorpej kt.kt_keyword = "eeprom writecount"; 643 1.1 thorpej kt.kt_offset = EE_WC_LOC; 644 1.1 thorpej kt.kt_handler = ee_notsupp; 645 1.1 thorpej 646 1.1 thorpej if (doio(&kt, (u_char *)&owritecount, sizeof(owritecount), IO_READ)) { 647 1.1 thorpej cksumfail = 1; 648 1.1 thorpej FAILEDREAD(&kt); 649 1.1 thorpej } 650 1.1 thorpej 651 1.1 thorpej if (owritecount[0] != owritecount[1] || 652 1.1 thorpej owritecount[0] != owritecount[2]) { 653 1.1 thorpej warnx("eeprom writecount mismatch %s", 654 1.1 thorpej ignore_checksum ? "(ignoring)" : 655 1.1 thorpej (fix_checksum ? "(fixing)" : "")); 656 1.1 thorpej 657 1.1 thorpej if (!ignore_checksum && !fix_checksum) { 658 1.1 thorpej cksumfail = 1; 659 1.1 thorpej return; 660 1.1 thorpej } 661 1.1 thorpej 662 1.1 thorpej writecount = MAXIMUM(owritecount[0], owritecount[1]); 663 1.1 thorpej writecount = MAXIMUM(writecount, owritecount[2]); 664 1.1 thorpej } else 665 1.1 thorpej writecount = owritecount[0]; 666 1.1 thorpej 667 1.1 thorpej /* 668 1.1 thorpej * Verify that the EEPROM's checksums match and are correct. 669 1.1 thorpej */ 670 1.1 thorpej kt.kt_keyword = "eeprom checksum"; 671 1.1 thorpej kt.kt_offset = EE_CKSUM_LOC; 672 1.1 thorpej 673 1.1 thorpej if (doio(&kt, ochecksum, sizeof(ochecksum), IO_READ)) { 674 1.1 thorpej cksumfail = 1; 675 1.1 thorpej FAILEDREAD(&kt); 676 1.1 thorpej } 677 1.1 thorpej 678 1.1 thorpej if (ochecksum[0] != ochecksum[1] || 679 1.1 thorpej ochecksum[0] != ochecksum[2]) { 680 1.1 thorpej warnx("eeprom checksum mismatch %s", 681 1.1 thorpej ignore_checksum ? "(ignoring)" : 682 1.1 thorpej (fix_checksum ? "(fixing)" : "")); 683 1.1 thorpej 684 1.1 thorpej if (!ignore_checksum && !fix_checksum) { 685 1.1 thorpej cksumfail = 1; 686 1.1 thorpej return; 687 1.1 thorpej } 688 1.1 thorpej } 689 1.1 thorpej 690 1.1 thorpej kt.kt_keyword = "eeprom contents"; 691 1.1 thorpej kt.kt_offset = EE_HWUPDATE_LOC; 692 1.1 thorpej 693 1.1 thorpej if (doio(&kt, checkme, sizeof(checkme), IO_READ)) { 694 1.1 thorpej cksumfail = 1; 695 1.1 thorpej FAILEDREAD(&kt); 696 1.1 thorpej } 697 1.1 thorpej 698 1.1 thorpej checksum = ee_checksum(checkme, sizeof(checkme)); 699 1.1 thorpej 700 1.1 thorpej if (ochecksum[0] != checksum) { 701 1.1 thorpej warnx("eeprom checksum incorrect %s", 702 1.1 thorpej ignore_checksum ? "(ignoring)" : 703 1.1 thorpej (fix_checksum ? "(fixing)" : "")); 704 1.1 thorpej 705 1.1 thorpej if (!ignore_checksum && !fix_checksum) { 706 1.1 thorpej cksumfail = 1; 707 1.1 thorpej return; 708 1.1 thorpej } 709 1.1 thorpej } 710 1.1 thorpej 711 1.1 thorpej if (fix_checksum) 712 1.1 thorpej ee_updatechecksums(); 713 1.1 thorpej } 714 1.1 thorpej 715 1.18 joerg static u_char 716 1.18 joerg ee_checksum(u_char *area, size_t len) 717 1.1 thorpej { 718 1.1 thorpej u_char sum = 0; 719 1.1 thorpej 720 1.1 thorpej while (len--) 721 1.1 thorpej sum += *area++; 722 1.1 thorpej 723 1.1 thorpej return (0x100 - sum); 724 1.1 thorpej } 725