xref: /netbsd/usr.sbin/memswitch/methods.c (revision d6aaec91)
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
atoi_(const char ** p)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
fill_uchar(struct property * prop)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
fill_ushort(struct property * prop)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
fill_ulong(struct property * prop)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
flush_uchar(struct property * prop)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
flush_ushort(struct property * prop)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
flush_ulong(struct property * prop)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
flush_dummy(struct property * prop)189 flush_dummy(struct property *prop)
190 {
191 	return 0;
192 }
193 
194 int
parse_dummy(struct property * prop,const char * value)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
parse_byte(struct property * prop,const char * value)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
parse_uchar(struct property * prop,const char * value)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
parse_ulong(struct property * prop,const char * value)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
parse_ushort(struct property * prop,const char * value)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
parse_time(struct property * prop,const char * value)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
parse_bootdev(struct property * prop,const char * value)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
parse_serial(struct property * prop,const char * value)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
parse_srammode(struct property * prop,const char * value)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
print_uchar(struct property * prop,char * str)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
print_ucharh(struct property * prop,char * str)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
print_ushorth(struct property * prop,char * str)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
print_ulong(struct property * prop,char * str)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
print_ulongh(struct property * prop,char * str)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
print_magic(struct property * prop,char * str)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
print_timesec(struct property * prop,char * str)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
print_bootdev(struct property * prop,char * str)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
print_serial(struct property * prop,char * str)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
print_srammode(struct property * prop,char * str)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