1 /* $NetBSD: eehandlers.c,v 1.9 2000/11/28 22:31:37 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 * 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 51 #include <machine/eeprom.h> 52 #ifdef __sparc__ 53 #include <machine/openpromio.h> 54 #endif /* __sparc__ */ 55 56 #include "defs.h" 57 58 extern char *path_eeprom; 59 extern int eval; 60 extern int update_checksums; 61 extern int ignore_checksum; 62 extern int fix_checksum; 63 extern int cksumfail; 64 extern u_short writecount; 65 66 struct timeb; 67 extern time_t get_date (char *, struct timeb *); 68 69 static char err_str[BUFSIZE]; 70 71 static void badval (struct keytabent *, char *); 72 static int doio (struct keytabent *, u_char *, ssize_t, int); 73 74 struct keytabent eekeytab[] = { 75 { "hwupdate", 0x10, ee_hwupdate }, 76 { "memsize", 0x14, ee_num8 }, 77 { "memtest", 0x15, ee_num8 }, 78 { "scrsize", 0x16, ee_screensize }, 79 { "watchdog_reboot", 0x17, ee_truefalse }, 80 { "default_boot", 0x18, ee_truefalse }, 81 { "bootdev", 0x19, ee_bootdev }, 82 { "kbdtype", 0x1e, ee_kbdtype }, 83 { "console", 0x1f, ee_constype }, 84 { "keyclick", 0x21, ee_truefalse }, 85 { "diagdev", 0x22, ee_bootdev }, 86 { "diagpath", 0x28, ee_diagpath }, 87 { "columns", 0x50, ee_num8 }, 88 { "rows", 0x51, ee_num8 }, 89 { "ttya_use_baud", 0x58, ee_truefalse }, 90 { "ttya_baud", 0x59, ee_num16 }, 91 { "ttya_no_rtsdtr", 0x5b, ee_truefalse }, 92 { "ttyb_use_baud", 0x60, ee_truefalse }, 93 { "ttyb_baud", 0x61, ee_num16 }, 94 { "ttyb_no_rtsdtr", 0x63, ee_truefalse }, 95 { "banner", 0x68, ee_banner }, 96 { "secure", 0, ee_notsupp }, 97 { "bad_login", 0, ee_notsupp }, 98 { "password", 0, ee_notsupp }, 99 { NULL, 0, ee_notsupp }, 100 }; 101 102 #define BARF(kt) { \ 103 badval((kt), arg); \ 104 ++eval; \ 105 return; \ 106 } 107 108 #define FAILEDREAD(kt) { \ 109 warnx("%s", err_str); \ 110 warnx("failed to read field `%s'", (kt)->kt_keyword); \ 111 ++eval; \ 112 return; \ 113 } 114 115 #define FAILEDWRITE(kt) { \ 116 warnx("%s", err_str); \ 117 warnx("failed to update field `%s'", (kt)->kt_keyword); \ 118 ++eval; \ 119 return; \ 120 } 121 122 void 123 ee_action(keyword, arg) 124 char *keyword, *arg; 125 { 126 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() 141 { 142 struct keytabent *ktent; 143 144 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) 145 (*ktent->kt_handler)(ktent, NULL); 146 } 147 148 void 149 ee_hwupdate(ktent, arg) 150 struct keytabent *ktent; 151 char *arg; 152 { 153 time_t t; 154 char *cp, *cp2; 155 156 if (arg) { 157 if ((strcmp(arg, "now") == 0) || 158 (strcmp(arg, "today") == 0)) { 159 if ((t = time(NULL)) == (time_t)(-1)) { 160 warnx("can't get current time"); 161 ++eval; 162 return; 163 } 164 } else 165 if ((t = get_date(arg, NULL)) == (time_t)(-1)) 166 BARF(ktent); 167 168 if (doio(ktent, (u_char *)&t, sizeof(t), IO_WRITE)) 169 FAILEDWRITE(ktent); 170 } else 171 if (doio(ktent, (u_char *)&t, sizeof(t), IO_READ)) 172 FAILEDREAD(ktent); 173 174 cp = ctime(&t); 175 if ((cp2 = strrchr(cp, '\n')) != NULL) 176 *cp2 = '\0'; 177 178 printf("%s=%ld (%s)\n", ktent->kt_keyword, (long)t, cp); 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 < (strlen(arg) - 1); ++i) 192 if (!isdigit(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 < (strlen(arg) - 1); ++i) 218 if (!isdigit(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 < (strlen(arg) - 1); ++i) 398 if (!isdigit(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