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