xref: /netbsd-src/usr.sbin/memswitch/methods.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: methods.c,v 1.6 2008/04/28 20:24:17 martin 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