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