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