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