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