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