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