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