Home | History | Annotate | Line # | Download | only in memswitch
      1 /*	$NetBSD: methods.c,v 1.8 2018/01/23 21:06:25 sevan Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Minoura Makoto.
      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 <stdio.h>
     33 #include <string.h>
     34 #include <err.h>
     35 #include <sys/types.h>
     36 
     37 #include "memswitch.h"
     38 #include "methods.h"
     39 
     40 int
     41 atoi_(const char **p)
     42 {
     43 	const char *p1 = *p;
     44 	int v = 0;
     45 	int first = 1;
     46 
     47 	while (*p1 == ' ' || *p1 == '\t')
     48 		p1++;
     49 
     50 	if (*p1 == 0) {
     51 		*p = 0;
     52 		return 0;
     53 	}
     54 	if (strlen(p1) >= 2 && strncasecmp("0x", p1, 2) == 0) {
     55 		p1 += 2;
     56 		while (1) {
     57 			if (*p1 >= '0' && *p1 <= '9') {
     58 				v *= 16;
     59 				v += *p1 - '0';
     60 				first = 0;
     61 			} else if (*p1 >= 'A' && *p1 <= 'F') {
     62 				v *= 16;
     63 				v += *p1 - 'A' + 10;
     64 				first = 0;
     65 			} else if (*p1 >= 'a' && *p1 <= 'f') {
     66 				v *= 16;
     67 				v += *p1 - 'a' + 10;
     68 				first = 0;
     69 			} else {
     70 				break;
     71 			}
     72 			p1++;
     73 		}
     74 	} else {
     75 		while (1) {
     76 			if (*p1 >= '0' && *p1 <= '9') {
     77 				v *= 10;
     78 				v += *p1 - '0';
     79 				first = 0;
     80 			} else {
     81 				break;
     82 			}
     83 			p1++;
     84 		}
     85 	}
     86 
     87 	if (first) {
     88 		*p = 0;
     89 		return 0;
     90 	}
     91 
     92 	while (*p1 == ' ' || *p1 == '\t') p1++;
     93 	*p = p1;
     94 	return v;
     95 }
     96 
     97 int
     98 fill_uchar(struct property *prop)
     99 {
    100 	if (current_values == 0)
    101 		alloc_current_values();
    102 
    103 	prop->current_value.byte[0] = current_values[prop->offset];
    104 	prop->current_value.byte[1] = 0;
    105 	prop->current_value.byte[2] = 0;
    106 	prop->current_value.byte[3] = 0;
    107 	prop->value_valid = 1;
    108 
    109 	return 0;
    110 }
    111 
    112 int
    113 fill_ushort(struct property *prop)
    114 {
    115 	if (current_values == 0)
    116 		alloc_current_values();
    117 
    118 	prop->current_value.byte[0] = current_values[prop->offset];
    119 	prop->current_value.byte[1] = current_values[prop->offset+1];
    120 	prop->current_value.byte[2] = 0;
    121 	prop->current_value.byte[3] = 0;
    122 	prop->value_valid = 1;
    123 
    124 	return 0;
    125 }
    126 
    127 int
    128 fill_ulong(struct property *prop)
    129 {
    130 	if (current_values == 0)
    131 		alloc_current_values();
    132 
    133 	prop->current_value.byte[0] = current_values[prop->offset];
    134 	prop->current_value.byte[1] = current_values[prop->offset+1];
    135 	prop->current_value.byte[2] = current_values[prop->offset+2];
    136 	prop->current_value.byte[3] = current_values[prop->offset+3];
    137 	prop->value_valid = 1;
    138 
    139 	return 0;
    140 }
    141 
    142 int
    143 flush_uchar(struct property *prop)
    144 {
    145 	if (!prop->modified)
    146 		return 0;
    147 
    148 	if (modified_values == 0)
    149 		alloc_modified_values();
    150 
    151 	modified_values[prop->offset] = prop->modified_value.byte[0];
    152 
    153 	return 0;
    154 }
    155 
    156 int
    157 flush_ushort(struct property *prop)
    158 {
    159 	if (!prop->modified)
    160 		return 0;
    161 
    162 	if (modified_values == 0)
    163 		alloc_modified_values();
    164 
    165 	modified_values[prop->offset] = prop->modified_value.byte[0];
    166 	modified_values[prop->offset+1] = prop->modified_value.byte[1];
    167 
    168 	return 0;
    169 }
    170 
    171 int
    172 flush_ulong(struct property *prop)
    173 {
    174 	if (!prop->modified)
    175 		return 0;
    176 
    177 	if (modified_values == 0)
    178 		alloc_modified_values();
    179 
    180 	modified_values[prop->offset] = prop->modified_value.byte[0];
    181 	modified_values[prop->offset+1] = prop->modified_value.byte[1];
    182 	modified_values[prop->offset+2] = prop->modified_value.byte[2];
    183 	modified_values[prop->offset+3] = prop->modified_value.byte[3];
    184 
    185 	return 0;
    186 }
    187 
    188 int
    189 flush_dummy(struct property *prop)
    190 {
    191 	return 0;
    192 }
    193 
    194 int
    195 parse_dummy(struct property *prop, const char *value)
    196 {
    197 	warnx("Cannot modify %s.%s", prop->class, prop->node);
    198 
    199 	return -1;
    200 }
    201 
    202 int
    203 parse_byte(struct property *prop, const char *value)
    204 {
    205 	const char *p = value;
    206 	int v;
    207 
    208 	v = atoi_(&p);
    209 	if (p == 0) {
    210 		warnx("%s: Invalid value", value);
    211 		return -1;
    212 	}
    213 
    214 	if (strcasecmp("MB", p) == 0)
    215 		v *= 1024 * 1024;
    216 	else if (strcasecmp("KB", p) == 0)
    217 		v *= 1024;
    218 	else if (*p != 0 &&
    219 		 strcasecmp("B", p) != 0) {
    220 		warnx("%s: Invalid value", value);
    221 		return -1;
    222 	}
    223 
    224 	if (v < prop->min) {
    225 		warnx("%s: Too small", value);
    226 		return -1;
    227 	} else if (v > prop->max) {
    228 		warnx("%s: Too large", value);
    229 		return -1;
    230 	}
    231 
    232 	prop->modified = 1;
    233 	prop->modified_value.longword = v;
    234 
    235 	return 0;
    236 }
    237 
    238 int
    239 parse_uchar(struct property *prop, const char *value)
    240 {
    241 	const char *p = value;
    242 	int v;
    243 
    244 	v = atoi_(&p);
    245 	if (p == 0) {
    246 		warnx("%s: Invalid value", value);
    247 		return -1;
    248 	}
    249 
    250 	if (v < prop->min) {
    251 		warnx("%s: Too small", value);
    252 		return -1;
    253 	} else if (v > prop->max) {
    254 		warnx("%s: Too large", value);
    255 		return -1;
    256 	}
    257 
    258 	prop->modified = 1;
    259 	prop->modified_value.byte[0] = v;
    260 
    261 	return 0;
    262 }
    263 
    264 int
    265 parse_ulong(struct property *prop, const char *value)
    266 {
    267 	const char *p = value;
    268 	int v;
    269 
    270 	v = atoi_(&p);
    271 	if (p == 0) {
    272 		warnx("%s: Invalid value", value);
    273 		return -1;
    274 	}
    275 
    276 	if (v < prop->min) {
    277 		warnx("%s: Too small", value);
    278 		return -1;
    279 	} else if (v > prop->max) {
    280 		warnx("%s: Too large", value);
    281 		return -1;
    282 	}
    283 
    284 	prop->modified = 1;
    285 	prop->modified_value.longword = v;
    286 
    287 	return 0;
    288 }
    289 
    290 int
    291 parse_ushort(struct property *prop, const char *value)
    292 {
    293 	const char *p = value;
    294 	int v;
    295 
    296 	v = atoi_(&p);
    297 	if (p == 0) {
    298 		warnx("%s: Invalid value", value);
    299 		return -1;
    300 	}
    301 
    302 	if (v < prop->min) {
    303 		warnx("%s: Too small", value);
    304 		return -1;
    305 	} else if (v > prop->max) {
    306 		warnx("%s: Too large", value);
    307 		return -1;
    308 	}
    309 
    310 	prop->modified = 1;
    311 	prop->modified_value.word[0] = v;
    312 
    313 	return 0;
    314 }
    315 
    316 int
    317 parse_time(struct property *prop, const char *value)
    318 {
    319 	const char *p = value;
    320 	int v;
    321 
    322 	while (*p == ' ' || *p == '\t') p++;
    323 	if (*p == '-') {
    324 		p++;
    325 		v = -atoi_(&p);
    326 	} else
    327 		v = atoi_(&p);
    328 	if (p == 0) {
    329 		warnx("%s: Invalid value", value);
    330 		return -1;
    331 	}
    332 
    333 	if (strcasecmp("hours", p) == 0 || strcasecmp("hour", p) == 0)
    334 		v *= 60 * 60;
    335 	else if (strcasecmp("minutes", p) == 0 ||
    336 		 strcasecmp("minute", p) == 0)
    337 		v *= 60;
    338 	else if (*p != 0 &&
    339 		 strcasecmp("second", p) != 0 &&
    340 		 strcasecmp("seconds", p) != 0) {
    341 		warnx("%s: Invalid value", value);
    342 		return -1;
    343 	}
    344 
    345 	if (v < prop->min) {
    346 		warnx("%s: Too small", value);
    347 		return -1;
    348 	} else if (v > prop->max) {
    349 		warnx("%s: Too large", value);
    350 		return -1;
    351 	}
    352 
    353 	prop->modified = 1;
    354 	prop->modified_value.longword = v;
    355 
    356 	return 0;
    357 }
    358 
    359 int
    360 parse_bootdev(struct property *prop, const char *value)
    361 {
    362 	const char *p = value;
    363 	int v;
    364 	char expr_scsi[32];
    365 
    366 	while (*p == ' ' || *p == '\t') p++;
    367 
    368 	if (strcasecmp("STD", p) == 0)
    369 		v = 0;
    370 	else if (strcasecmp("ROM", p) == 0)
    371 		v = 0xa000;
    372 	else if (strcasecmp("RAM", p) == 0)
    373 		v = 0xb000;
    374 	else if (strncasecmp("HD", p, 2) == 0) {
    375 		p += 2;
    376 		v = atoi_(&p);
    377 		if (p == 0 || v < 0 || v > 15) {
    378 			warnx("%s: Invalid value", value);
    379 			return -1;
    380 		}
    381 		v *= 0x0100;
    382 		v += 0x8000;
    383 	} else if (strncasecmp("FD", p, 2) == 0) {
    384 		p += 2;
    385 		v = atoi_(&p);
    386 		if (p == 0 || v < 0 || v > 3) {
    387 			warnx("%s: Invalid value", value);
    388 			return -1;
    389 		}
    390 		v *= 0x0100;
    391 		v += 0x9070;
    392 	} else if (strncasecmp("INSCSI", p, 6) == 0 ||
    393 		   strncasecmp("EXSCSI", p, 6) == 0) {
    394 		int isin = strncasecmp("EXSCSI", p, 6);
    395 
    396 		p += 6;
    397 		v = atoi_(&p);
    398 		if (p == 0 || v < 0 || v > 7) {
    399 			warnx("%s: Invalid value", value);
    400 			return -1;
    401 		}
    402 
    403 		/* change boot.romaddr */
    404 		sprintf(expr_scsi, "boot.romaddr=0x%06x",
    405 			(isin ? 0xfc0000 : 0xea0020) + v * 4);
    406 		modify_single(expr_scsi);
    407 
    408 		/* boot.device again */
    409 		v = 0xa000;
    410 	} else {
    411 		warnx("%s: Invalid value", value);
    412 		return -1;
    413 	}
    414 
    415 	prop->modified = 1;
    416 	prop->modified_value.word[0] = v;
    417 
    418 	return 0;
    419 }
    420 
    421 int
    422 parse_serial(struct property *prop, const char *value)
    423 #define NEXTSPEC	while (*p == ' ' || *p == '\t') p++;		\
    424 			if (*p++ != ',') {				\
    425 				warnx("%s: Invalid value", value);	\
    426 				return -1;				\
    427 			}						\
    428 			while (*p == ' ' || *p == '\t') p++;
    429 {
    430 	const char *p = value;
    431 	const char *q;
    432 	int baud, bit, parity, stop, flow;
    433 	static const int bauds[] = {75, 150, 300, 600, 1200, 2400, 4800, 9600,
    434 	    17361, 0};
    435 	static const char parities[] = "noe";
    436 	int i;
    437 
    438 	while (*p == ' ' || *p == '\t') p++;
    439 
    440 	/* speed */
    441 	baud = atoi_(&p);
    442 	if (p == 0) {
    443 		warnx("%s: Invalid value", value);
    444 		return -1;
    445 	}
    446 	for (i = 0; bauds[i]; i++)
    447 		if (baud == bauds[i])
    448 			break;
    449 	if (bauds[i] == 0) {
    450 		warnx("%d: Invalid speed", baud);
    451 		return -1;
    452 	}
    453 	baud = i;
    454 
    455 	NEXTSPEC;
    456 
    457 	/* bit size */
    458 	if (*p < '5' || *p > '8') {
    459 		warnx("%c: Invalid bit size", *p);
    460 		return -1;
    461 	}
    462 	bit = *p++ - '5';
    463 
    464 	NEXTSPEC;
    465 
    466 	/* parity */
    467 	q = strchr(parities, *p++);
    468 	if (q == 0) {
    469 		warnx("%c: Invalid parity spec", *p);
    470 		return -1;
    471 	}
    472 	parity = q - parities;
    473 
    474 	NEXTSPEC;
    475 
    476 	/* stop bit */
    477 	if (strncmp(p, "1.5", 3) == 0) {
    478 		stop = 2;
    479 		p += 3;
    480 	} else if (strncmp(p, "2", 1) == 0) {
    481 		stop = 0;
    482 		p++;
    483 	} else if (strncmp(p, "1", 1) == 0) {
    484 		stop = 1;
    485 		p++;
    486 	} else {
    487 		warnx("%s: Invalid value", value);
    488 		return -1;
    489 	}
    490 
    491 	NEXTSPEC;
    492 
    493 	/* flow */
    494 	if (*p == '-')
    495 		flow = 0;
    496 	else if (*p == 's')
    497 		flow = 1;
    498 	else {
    499 		warnx("%s: Invalid value", value);
    500 		return -1;
    501 	}
    502 
    503 	p++;
    504 	while (*p == ' ' || *p == '\t') p++;
    505 	if (*p != 0) {
    506 		warnx("%s: Invalid value", value);
    507 		return -1;
    508 	}
    509 
    510 	prop->modified = 1;
    511 	prop->modified_value.word[0] = ((stop << 14) +
    512 					(parity << 12) +
    513 					(bit << 10) +
    514 					(flow << 9) +
    515 					baud);
    516 
    517 	return 0;
    518 }
    519 #undef NEXTSPEC
    520 
    521 int
    522 parse_srammode(struct property *prop, const char *value)
    523 {
    524 	static const char *const sramstrs[] = {"unused", "SRAMDISK", "program"};
    525 	int i;
    526 
    527 	for (i = 0; i <= 2; i++) {
    528 		if (strcasecmp(value, sramstrs[i]) == 0)
    529 			break;
    530 	}
    531 	if (i > 2) {
    532 		warnx("%s: Invalid value", value);
    533 		return -1;
    534 	}
    535 
    536 	prop->modified = 1;
    537 	prop->modified_value.byte[0] = i;
    538 
    539 	return 0;
    540 }
    541 
    542 int
    543 print_uchar(struct property *prop, char *str)
    544 {
    545 	if (prop->modified)
    546 		snprintf(str, MAXVALUELEN,
    547 			 "%d", prop->modified_value.byte[0]);
    548 	else {
    549 		if (!prop->value_valid)
    550 			prop->fill(prop);
    551 		snprintf(str, MAXVALUELEN, "%d",
    552 			 prop->current_value.byte[0]);
    553 	}
    554 
    555 	return 0;
    556 }
    557 
    558 int
    559 print_ucharh(struct property *prop, char *str)
    560 {
    561 	if (prop->modified)
    562 		snprintf(str, MAXVALUELEN,
    563 			 "0x%4.4x", prop->modified_value.byte[0]);
    564 	else {
    565 		if (!prop->value_valid)
    566 			prop->fill(prop);
    567 		snprintf(str, MAXVALUELEN,
    568 			 "0x%4.4x", prop->current_value.byte[0]);
    569 	}
    570 
    571 	return 0;
    572 }
    573 
    574 int
    575 print_ushorth(struct property *prop, char *str)
    576 {
    577 	if (prop->modified)
    578 		snprintf(str, MAXVALUELEN,
    579 			  "0x%4.4x", prop->modified_value.word[0]);
    580 	else {
    581 		if (!prop->value_valid)
    582 			prop->fill(prop);
    583 		snprintf(str, MAXVALUELEN,
    584 			 "0x%4.4x", prop->current_value.word[0]);
    585 	}
    586 
    587 	return 0;
    588 }
    589 
    590 int
    591 print_ulong(struct property *prop, char *str)
    592 {
    593 	if (prop->modified)
    594 		snprintf(str, MAXVALUELEN,
    595 			 "%ld", prop->modified_value.longword);
    596 	else {
    597 		if (!prop->value_valid)
    598 			prop->fill(prop);
    599 		snprintf(str, MAXVALUELEN,
    600 			 "%ld", prop->current_value.longword);
    601 	}
    602 
    603 	return 0;
    604 }
    605 
    606 int
    607 print_ulongh(struct property *prop, char *str)
    608 {
    609 	if (prop->modified)
    610 		snprintf(str, MAXVALUELEN,
    611 			 "0x%8.8lx", prop->modified_value.longword);
    612 	else {
    613 		if (!prop->value_valid)
    614 			prop->fill(prop);
    615 		snprintf(str, MAXVALUELEN,
    616 			 "0x%8.8lx", prop->current_value.longword);
    617 	}
    618 
    619 	return 0;
    620 }
    621 
    622 int
    623 print_magic(struct property *prop, char *str)
    624 {
    625 	if (!prop->value_valid)
    626 		prop->fill(prop);
    627 	snprintf(str, MAXVALUELEN, "%c%c%c%c",
    628 		 prop->current_value.byte[0],
    629 		 prop->current_value.byte[1],
    630 		 prop->current_value.byte[2],
    631 		 prop->current_value.byte[3]);
    632 
    633 	return 0;
    634 }
    635 
    636 int
    637 print_timesec(struct property *prop, char *str)
    638 {
    639 	if (prop->modified)
    640 		snprintf(str, MAXVALUELEN,
    641 			 "%ld second", prop->modified_value.longword);
    642 	else {
    643 		if (!prop->value_valid)
    644 			prop->fill(prop);
    645 		snprintf(str, MAXVALUELEN,
    646 			 "%ld second", prop->current_value.longword);
    647 	}
    648 
    649 	return 0;
    650 }
    651 
    652 int
    653 print_bootdev(struct property *prop, char *str)
    654 {
    655 	unsigned int v;
    656 
    657 	if (prop->modified)
    658 		v = prop->modified_value.word[0];
    659 	else {
    660 		if (!prop->value_valid)
    661 			prop->fill(prop);
    662 		v = prop->current_value.word[0];
    663 	}
    664 
    665 	if (v == 0)
    666 		strcpy(str, "STD");
    667 	else if (v == 0xa000)
    668 		strcpy(str, "ROM");
    669 	else if (v == 0xb000)
    670 		strcpy(str, "RAM");
    671 	else if (v >= 0x8000 && v < 0x9000)
    672 		snprintf(str, MAXVALUELEN, "HD%d", (v & 0x0f00) >> 8);
    673 	else if (v >= 0x9000 && v < 0xa000)
    674 		snprintf(str, MAXVALUELEN, "FD%d", (v & 0x0f00) >> 8);
    675 	else
    676 		snprintf(str, MAXVALUELEN, "%8.8x", v);
    677 
    678 	return 0;
    679 }
    680 
    681 int
    682 print_serial(struct property *prop, char *str)
    683 {
    684 	unsigned int v;
    685 	const char *baud, *stop;
    686 	char bit, parity, flow;
    687 	static const char *const bauds[] = {"75", "150", "300", "600", "1200",
    688 			       "2400", "4800", "9600", "17361"};
    689 	static const char bits[] = "5678";
    690 	static const char parities[] = "noen";
    691 	static const char *const stops[] = {"2", "1", "1.5", "2"};
    692 	static const char flows[] = "-s";
    693 
    694 	if (prop->modified)
    695 		v = prop->modified_value.word[0];
    696 	else {
    697 		if (!prop->value_valid)
    698 			prop->fill(prop);
    699 		v = prop->current_value.word[0];
    700 	}
    701 
    702 	baud = bauds[v & 0x000f];
    703 	bit = bits[(v & 0x0c00) >> 10];
    704 	parity = parities[(v & 0x3000) >> 12];
    705 	stop = stops[(v & 0xe000) >> 14];
    706 	flow = flows[(v & 0x0200) >> 9];
    707 	sprintf(str, "%s,%c,%c,%s,%c", baud, bit, parity, stop, flow);
    708 
    709 	return 0;
    710 }
    711 
    712 int
    713 print_srammode(struct property *prop, char *str)
    714 {
    715 	int v;
    716 	static const char *const sramstrs[] = {"unused", "SRAMDISK", "program"};
    717 
    718 	if (prop->modified)
    719 		v = prop->modified_value.byte[0];
    720 	else {
    721 		if (!prop->value_valid)
    722 			prop->fill(prop);
    723 		v = prop->current_value.byte[0];
    724 	}
    725 
    726 	if (v < 0 || v > 2)
    727 		strcpy(str, "INVALID");
    728 	else
    729 		strcpy(str, sramstrs[v]);
    730 
    731 	return 0;
    732 }
    733