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