Bug Summary

File:kern/subr_userconf.c
Warning:line 1003, column 3
Value stored to 'i' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name subr_userconf.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/kern/subr_userconf.c
1/* $OpenBSD: subr_userconf.c,v 1.47 2021/10/24 00:02:25 jsg Exp $ */
2
3/*
4 * Copyright (c) 1996-2001 Mats O Jansson <moj@stacken.kth.se>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/device.h>
32#include <sys/malloc.h>
33#include <sys/time.h>
34
35#include <dev/cons.h>
36
37extern char *locnames[];
38extern short locnamp[];
39extern short cfroots[];
40extern int cfroots_size;
41extern int pv_size;
42extern short pv[];
43extern char *pdevnames[];
44extern int pdevnames_size;
45extern struct pdevinit pdevinit[];
46
47int userconf_base = 16; /* Base for "large" numbers */
48int userconf_maxdev = -1; /* # of used device slots */
49int userconf_totdev = -1; /* # of device slots */
50int userconf_maxlocnames = -1; /* # of locnames */
51int userconf_cnt = -1; /* Line counter for ... */
52int userconf_lines = 12; /* ... # of lines per page */
53int userconf_histlen = 0;
54int userconf_histcur = 0;
55char userconf_history[1024];
56int userconf_histsz = sizeof(userconf_history);
57char userconf_argbuf[40]; /* Additional input */
58char userconf_cmdbuf[40]; /* Command line */
59char userconf_histbuf[40];
60
61void userconf_init(void);
62int userconf_more(void);
63void userconf_modify(char *, long *, long);
64void userconf_hist_cmd(char);
65void userconf_hist_int(long);
66void userconf_hist_eoc(void);
67void userconf_pnum(long);
68void userconf_pdevnam(short);
69void userconf_pdev(short);
70int userconf_number(char *, long *, long);
71int userconf_device(char *, long *, short *, short *);
72int userconf_attr(char *, long *);
73void userconf_change(int);
74void userconf_disable(int);
75void userconf_enable(int);
76void userconf_help(void);
77void userconf_list(void);
78void userconf_show(void);
79void userconf_common_attr_val(short, long *, char);
80void userconf_show_attr(char *);
81void userconf_common_dev(char *, int, short, short, char);
82void userconf_common_attr(char *, int, char);
83void userconf_add_read(char *, char, char *, int, long *);
84void userconf_add(char *, int, short, short);
85int userconf_parse(char *);
86
87#define UC_CHANGE'c' 'c'
88#define UC_DISABLE'd' 'd'
89#define UC_ENABLE'e' 'e'
90#define UC_FIND'f' 'f'
91#define UC_SHOW's' 's'
92
93char *userconf_cmds[] = {
94 "add", "a",
95 "base", "b",
96 "change", "c",
97#if defined(DDB1)
98 "ddb", "D",
99#endif
100 "disable", "d",
101 "enable", "e",
102 "exit", "q",
103 "find", "f",
104 "help", "h",
105 "list", "l",
106 "lines", "L",
107 "quit", "q",
108 "show", "s",
109 "verbose", "v",
110 "?", "h",
111 "", "",
112};
113
114void
115userconf_init(void)
116{
117 int i = 0;
118 struct cfdata *cd;
119 int ln;
120
121 while (cfdata[i].cf_attach != NULL((void *)0)) {
122 userconf_maxdev = i;
123 userconf_totdev = i;
124
125 cd = &cfdata[i];
126 ln = cd->cf_locnames;
127 while (locnamp[ln] != -1) {
128 if (locnamp[ln] > userconf_maxlocnames)
129 userconf_maxlocnames = locnamp[ln];
130 ln++;
131 }
132 i++;
133 }
134
135 while (cfdata[i].cf_attach == NULL((void *)0)) {
136 userconf_totdev = i;
137 i++;
138 }
139 userconf_totdev = userconf_totdev - 1;
140}
141
142int
143userconf_more(void)
144{
145 int quit = 0;
146 char c = '\0';
147
148 if (userconf_cnt != -1) {
149 if (userconf_cnt == userconf_lines) {
150 printf("--- more ---");
151 c = cngetc();
152 userconf_cnt = 0;
153 printf("\r \r");
154 }
155 userconf_cnt++;
156 if (c == 'q' || c == 'Q')
157 quit = 1;
158 }
159 return (quit);
160}
161
162void
163userconf_hist_cmd(char cmd)
164{
165 userconf_histcur = userconf_histlen;
166 if (userconf_histcur < userconf_histsz) {
167 userconf_history[userconf_histcur] = cmd;
168 userconf_histcur++;
169 }
170}
171
172void
173userconf_hist_int(long val)
174{
175 snprintf(userconf_histbuf, sizeof userconf_histbuf, " %ld", val);
176 if (userconf_histcur + strlen(userconf_histbuf) < userconf_histsz) {
177 bcopy(userconf_histbuf,
178 &userconf_history[userconf_histcur],
179 strlen(userconf_histbuf));
180 userconf_histcur = userconf_histcur + strlen(userconf_histbuf);
181 }
182}
183
184void
185userconf_hist_eoc(void)
186{
187 if (userconf_histcur < userconf_histsz) {
188 userconf_history[userconf_histcur] = '\n';
189 userconf_histcur++;
190 userconf_histlen = userconf_histcur;
191 }
192}
193
194void
195userconf_pnum(long val)
196{
197 if (val > -2 && val < 16) {
198 printf("%ld",val);
199 return;
200 }
201
202 switch (userconf_base) {
203 case 8:
204 printf("0%lo",val);
205 break;
206 case 10:
207 printf("%ld",val);
208 break;
209 case 16:
210 default:
211 printf("0x%lx",val);
212 break;
213 }
214}
215
216void
217userconf_pdevnam(short dev)
218{
219 struct cfdata *cd;
220
221 cd = &cfdata[dev];
222 printf("%s", cd->cf_driver->cd_name);
223 switch (cd->cf_fstate) {
224 case FSTATE_NOTFOUND0:
225 case FSTATE_DNOTFOUND3:
226 printf("%d", cd->cf_unit);
227 break;
228 case FSTATE_FOUND1:
229 printf("*FOUND*");
230 break;
231 case FSTATE_STAR2:
232 case FSTATE_DSTAR4:
233 printf("*");
234 break;
235 default:
236 printf("*UNKNOWN*");
237 break;
238 }
239}
240
241void
242userconf_pdev(short devno)
243{
244 struct cfdata *cd;
245 short *p;
246 long *l;
247 int ln;
248 char c;
249
250 if (devno > userconf_maxdev && devno <= userconf_totdev) {
251 printf("%3d free slot (for add)\n", devno);
252 return;
253 }
254
255 if (devno > userconf_totdev &&
256 devno <= userconf_totdev+pdevnames_size) {
257 printf("%3d %s count %d", devno,
258 pdevnames[devno-userconf_totdev-1],
259 abs(pdevinit[devno-userconf_totdev-1].pdev_count));
260 if (pdevinit[devno-userconf_totdev-1].pdev_count < 1)
261 printf(" disable");
262 printf(" (pseudo device)\n");
263 return;
264 }
265
266 if (devno > userconf_maxdev) {
267 printf("Unknown devno (max is %d)\n", userconf_maxdev);
268 return;
269 }
270
271 cd = &cfdata[devno];
272
273 printf("%3d ", devno);
274 userconf_pdevnam(devno);
275 printf(" at");
276 c = ' ';
277 p = cd->cf_parents;
278 if (*p == -1)
279 printf(" root");
280 while (*p != -1) {
281 printf("%c", c);
282 userconf_pdevnam(*p++);
283 c = '|';
284 }
285 switch (cd->cf_fstate) {
286 case FSTATE_NOTFOUND0:
287 case FSTATE_FOUND1:
288 case FSTATE_STAR2:
289 break;
290 case FSTATE_DNOTFOUND3:
291 case FSTATE_DSTAR4:
292 printf(" disable");
293 break;
294 default:
295 printf(" ???");
296 break;
297 }
298 l = cd->cf_loc;
299 ln = cd->cf_locnames;
300 while (locnamp[ln] != -1) {
301 printf(" %s ", locnames[locnamp[ln]]);
302 ln++;
303 userconf_pnum(*l++);
304 }
305 printf(" flags 0x%x\n", cd->cf_flags);
306}
307
308int
309userconf_number(char *c, long *val, long limit)
310{
311 u_long num = 0;
312 int neg = 0;
313 int base = 10;
314
315 if (*c == '-') {
316 neg = 1;
317 c++;
318 }
319 if (*c == '0') {
320 base = 8;
321 c++;
322 if (*c == 'x' || *c == 'X') {
323 base = 16;
324 c++;
325 }
326 }
327 while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') {
328 u_char cc = *c;
329
330 if (cc >= '0' && cc <= '9')
331 cc = cc - '0';
332 else if (cc >= 'a' && cc <= 'f')
333 cc = cc - 'a' + 10;
334 else if (cc >= 'A' && cc <= 'F')
335 cc = cc - 'A' + 10;
336 else
337 return (-1);
338
339 if (cc > base)
340 return (-1);
341 num = num * base + cc;
342 c++;
343 }
344
345 if (neg && num > limit) /* overflow */
346 return (1);
347 *val = neg ? - num : num;
348 return (0);
349}
350
351int
352userconf_device(char *cmd, long *len, short *unit, short *state)
353{
354 short u = 0, s = FSTATE_FOUND1;
355 int l = 0;
356 char *c;
357
358 c = cmd;
359 while (*c >= 'a' && *c <= 'z') {
360 l++;
361 c++;
362 }
363 if (*c == '*') {
364 s = FSTATE_STAR2;
365 c++;
366 } else {
367 while (*c >= '0' && *c <= '9') {
368 s = FSTATE_NOTFOUND0;
369 u = u*10 + *c - '0';
370 c++;
371 }
372 }
373 while (*c == ' ' || *c == '\t' || *c == '\n')
374 c++;
375
376 if (*c == '\0') {
377 *len = l;
378 *unit = u;
379 *state = s;
380 return(0);
381 }
382
383 return(-1);
384}
385
386int
387userconf_attr(char *cmd, long *val)
388{
389 char *c;
390 short attr = -1, i = 0, l = 0;
391
392 c = cmd;
393 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
394 c++;
395 l++;
396 }
397
398 while (i <= userconf_maxlocnames) {
399 if (strlen(locnames[i]) == l) {
400 if (strncasecmp(cmd, locnames[i], l) == 0)
401 attr = i;
402 }
403 i++;
404 }
405
406 if (attr == -1) {
407 return (-1);
408 }
409
410 *val = attr;
411
412 return(0);
413}
414
415void
416userconf_modify(char *item, long *val, long limit)
417{
418 int ok = 0;
419 long a;
420 char *c;
421 int i;
422
423 while (!ok) {
424 printf("%s [", item);
425 userconf_pnum(*val);
426 printf("] ? ");
427
428 i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
429
430 c = userconf_argbuf;
431 while (*c == ' ' || *c == '\t' || *c == '\n') c++;
432
433 if (*c != '\0') {
434 if (userconf_number(c, &a, limit) == 0) {
435 *val = a;
436 ok = 1;
437 } else {
438 printf("Unknown argument\n");
439 }
440 } else {
441 ok = 1;
442 }
443 }
444}
445
446void
447userconf_change(int devno)
448{
449 struct cfdata *cd;
450 char c = '\0';
451 long *l, tmp;
452 int ln;
453
454 if (devno <= userconf_maxdev) {
455 userconf_pdev(devno);
456
457 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
458 printf("change (y/n) ?");
459 c = cngetc();
460 printf("\n");
461 }
462
463 if (c == 'y' || c == 'Y') {
464 int share = 0, i, lklen;
465 long *lk;
466
467 /* XXX add cmd 'c' <devno> */
468 userconf_hist_cmd('c');
469 userconf_hist_int(devno);
470
471 cd = &cfdata[devno];
472 l = cd->cf_loc;
473 ln = cd->cf_locnames;
474
475 /*
476 * Search for some other driver sharing this
477 * locator table. if one does, we may need to
478 * replace the locators with a malloc'd copy.
479 */
480 for (i = 0; cfdata[i].cf_driver; i++)
481 if (i != devno && cfdata[i].cf_loc == l)
482 share = 1;
483 if (share) {
484 for (i = 0; locnamp[ln+i] != -1 ; i++)
485 ;
486 lk = l = mallocarray(i, sizeof(long),
487 M_TEMP127, M_NOWAIT0x0002);
488 if (lk == NULL((void *)0)) {
489 printf("out of memory.\n");
490 return;
491 }
492 lklen = i * sizeof(long);
493 bcopy(cd->cf_loc, l, lklen);
494 }
495
496 while (locnamp[ln] != -1) {
497 userconf_modify(locnames[locnamp[ln]], l,
498 LONG_MAX0x7fffffffffffffffL);
499
500 /* XXX add *l */
501 userconf_hist_int(*l);
502
503 ln++;
504 l++;
505 }
506 tmp = cd->cf_flags;
507 userconf_modify("flags", &tmp, INT_MAX0x7fffffff);
508 userconf_hist_int(tmp);
509 cd->cf_flags = tmp;
510
511 if (share) {
512 if (memcmp(cd->cf_loc, lk, lklen)__builtin_memcmp((cd->cf_loc), (lk), (lklen)))
513 cd->cf_loc = lk;
514 else
515 free(lk, M_TEMP127, lklen);
516 }
517
518 printf("%3d ", devno);
519 userconf_pdevnam(devno);
520 printf(" changed\n");
521 userconf_pdev(devno);
522 }
523 return;
524 }
525
526 if (devno > userconf_maxdev && devno <= userconf_totdev) {
527 printf("%3d can't change free slot\n", devno);
528 return;
529 }
530
531 if (devno > userconf_totdev &&
532 devno <= userconf_totdev+pdevnames_size) {
533 userconf_pdev(devno);
534 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
535 printf("change (y/n) ?");
536 c = cngetc();
537 printf("\n");
538 }
539
540 if (c == 'y' || c == 'Y') {
541 /* XXX add cmd 'c' <devno> */
542 userconf_hist_cmd('c');
543 userconf_hist_int(devno);
544
545 tmp = pdevinit[devno-userconf_totdev-1].pdev_count;
546 userconf_modify("count", &tmp, INT_MAX0x7fffffff);
547 userconf_hist_int(tmp);
548 pdevinit[devno-userconf_totdev-1].pdev_count = tmp;
549
550 printf("%3d %s changed\n", devno,
551 pdevnames[devno-userconf_totdev-1]);
552 userconf_pdev(devno);
553
554 /* XXX add eoc */
555 userconf_hist_eoc();
556 }
557 return;
558 }
559
560 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
561}
562
563void
564userconf_disable(int devno)
565{
566 int done = 0;
567
568 if (devno <= userconf_maxdev) {
569 switch (cfdata[devno].cf_fstate) {
570 case FSTATE_NOTFOUND0:
571 cfdata[devno].cf_fstate = FSTATE_DNOTFOUND3;
572 break;
573 case FSTATE_STAR2:
574 cfdata[devno].cf_fstate = FSTATE_DSTAR4;
575 break;
576 case FSTATE_DNOTFOUND3:
577 case FSTATE_DSTAR4:
578 done = 1;
579 break;
580 default:
581 printf("Error unknown state\n");
582 break;
583 }
584
585 printf("%3d ", devno);
586 userconf_pdevnam(devno);
587 if (done) {
588 printf(" already");
589 } else {
590 /* XXX add cmd 'd' <devno> eoc */
591 userconf_hist_cmd('d');
592 userconf_hist_int(devno);
593 userconf_hist_eoc();
594 }
595 printf(" disabled\n");
596
597 return;
598 }
599
600 if (devno > userconf_maxdev && devno <= userconf_totdev) {
601 printf("%3d can't disable free slot\n", devno);
602 return;
603 }
604
605 if (devno > userconf_totdev &&
606 devno <= userconf_totdev+pdevnames_size) {
607 printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]);
608 if (pdevinit[devno-userconf_totdev-1].pdev_count < 1) {
609 printf(" already ");
610 } else {
611 pdevinit[devno-userconf_totdev-1].pdev_count *= -1;
612 /* XXX add cmd 'd' <devno> eoc */
613 userconf_hist_cmd('d');
614 userconf_hist_int(devno);
615 userconf_hist_eoc();
616 }
617 printf(" disabled\n");
618 return;
619 }
620
621 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
622}
623
624void
625userconf_enable(int devno)
626{
627 int done = 0;
628
629 if (devno <= userconf_maxdev) {
630 switch (cfdata[devno].cf_fstate) {
631 case FSTATE_DNOTFOUND3:
632 cfdata[devno].cf_fstate = FSTATE_NOTFOUND0;
633 break;
634 case FSTATE_DSTAR4:
635 cfdata[devno].cf_fstate = FSTATE_STAR2;
636 break;
637 case FSTATE_NOTFOUND0:
638 case FSTATE_STAR2:
639 done = 1;
640 break;
641 default:
642 printf("Error unknown state\n");
643 break;
644 }
645
646 printf("%3d ", devno);
647 userconf_pdevnam(devno);
648 if (done) {
649 printf(" already");
650 } else {
651 /* XXX add cmd 'e' <devno> eoc */
652 userconf_hist_cmd('e');
653 userconf_hist_int(devno);
654 userconf_hist_eoc();
655 }
656 printf(" enabled\n");
657 return;
658 }
659
660 if (devno > userconf_maxdev && devno <= userconf_totdev) {
661 printf("%3d can't enable free slot\n", devno);
662 return;
663 }
664
665 if (devno > userconf_totdev &&
666 devno <= userconf_totdev+pdevnames_size) {
667 printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]);
668 if (pdevinit[devno-userconf_totdev-1].pdev_count > 0) {
669 printf(" already");
670 } else {
671 pdevinit[devno-userconf_totdev-1].pdev_count *= -1;
672 /* XXX add cmd 'e' <devno> eoc */
673 userconf_hist_cmd('e');
674 userconf_hist_int(devno);
675 userconf_hist_eoc();
676 }
677 printf(" enabled\n");
678 return;
679 }
680
681 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
682}
683
684void
685userconf_help(void)
686{
687 int j = 0, k;
688
689 printf("command args description\n");
690 while (*userconf_cmds[j] != '\0') {
691 printf("%s", userconf_cmds[j]);
692 k = strlen(userconf_cmds[j]);
693 while (k < 10) {
694 printf(" ");
695 k++;
696 }
697 switch (*userconf_cmds[j+1]) {
698 case 'L':
699 printf("[count] number of lines before more");
700 break;
701 case 'a':
702 printf("dev add a device");
703 break;
704 case 'b':
705 printf("8|10|16 base on large numbers");
706 break;
707 case 'c':
708 printf("devno|dev change devices");
709 break;
710#if defined(DDB1)
711 case 'D':
712 printf(" enter ddb");
713 break;
714#endif
715 case 'd':
716 printf("attr val|devno|dev disable devices");
717 break;
718 case 'e':
719 printf("attr val|devno|dev enable devices");
720 break;
721 case 'f':
722 printf("devno|dev find devices");
723 break;
724 case 'h':
725 printf(" this message");
726 break;
727 case 'l':
728 printf(" list configuration");
729 break;
730 case 'q':
731 printf(" leave UKC");
732 break;
733 case 's':
734 printf("[attr [val]] "
735 "show attributes (or devices with an attribute)");
736 break;
737 case 'v':
738 printf(" toggle verbose booting");
739 break;
740 default:
741 printf(" don't know");
742 break;
743 }
744 printf("\n");
745 j += 2;
746 }
747}
748
749void
750userconf_list(void)
751{
752 int i = 0;
753
754 userconf_cnt = 0;
755
756 while (i <= (userconf_totdev+pdevnames_size)) {
757 if (userconf_more())
758 break;
759 userconf_pdev(i++);
760 }
761
762 userconf_cnt = -1;
763}
764
765void
766userconf_show(void)
767{
768 int i = 0;
769
770 userconf_cnt = 0;
771
772 while (i <= userconf_maxlocnames) {
773 if (userconf_more())
774 break;
775 printf("%s\n", locnames[i++]);
776 }
777
778 userconf_cnt = -1;
779}
780
781void
782userconf_common_attr_val(short attr, long *val, char routine)
783{
784 struct cfdata *cd;
785 long *l;
786 int ln;
787 int i = 0, quit = 0;
788
789 userconf_cnt = 0;
790
791 while (i <= userconf_maxdev) {
792 cd = &cfdata[i];
793 l = cd->cf_loc;
794 ln = cd->cf_locnames;
795 while (locnamp[ln] != -1) {
796 if (locnamp[ln] == attr) {
797 if (val == NULL((void *)0)) {
798 quit = userconf_more();
799 userconf_pdev(i);
800 } else {
801 if (*val == *l) {
802 quit = userconf_more();
803 switch (routine) {
804 case UC_ENABLE'e':
805 userconf_enable(i);
806 break;
807 case UC_DISABLE'd':
808 userconf_disable(i);
809 break;
810 case UC_SHOW's':
811 userconf_pdev(i);
812 break;
813 default:
814 printf("Unknown routine /%c/\n",
815 routine);
816 break;
817 }
818 }
819 }
820 }
821 if (quit)
822 break;
823 ln++;
824 l++;
825 }
826 if (quit)
827 break;
828 i++;
829 }
830
831 userconf_cnt = -1;
832}
833
834void
835userconf_show_attr(char *cmd)
836{
837 char *c;
838 short attr = -1, i = 0, l = 0;
839 long a;
840
841 c = cmd;
842 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
843 c++;
844 l++;
845 }
846 while (*c == ' ' || *c == '\t' || *c == '\n') {
847 c++;
848 }
849 while (i <= userconf_maxlocnames) {
850 if (strlen(locnames[i]) == l) {
851 if (strncasecmp(cmd, locnames[i], l) == 0) {
852 attr = i;
853 }
854 }
855 i++;
856 }
857
858 if (attr == -1) {
859 printf("Unknown attribute\n");
860 return;
861 }
862
863 if (*c == '\0') {
864 userconf_common_attr_val(attr, NULL((void *)0), UC_SHOW's');
865 } else {
866 if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0) {
867 userconf_common_attr_val(attr, &a, UC_SHOW's');
868 } else {
869 printf("Unknown argument\n");
870 }
871 }
872}
873
874void
875userconf_common_dev(char *dev, int len, short unit, short state, char routine)
876{
877 int i = 0;
878
879 switch (routine) {
880 case UC_CHANGE'c':
881 break;
882 default:
883 userconf_cnt = 0;
884 break;
885 }
886
887 while (cfdata[i].cf_attach != NULL((void *)0)) {
888 if (strlen(cfdata[i].cf_driver->cd_name) == len) {
889
890 /*
891 * Ok, if device name is correct
892 * If state == FSTATE_FOUND, look for "dev"
893 * If state == FSTATE_STAR, look for "dev*"
894 * If state == FSTATE_NOTFOUND, look for "dev0"
895 */
896 if (strncasecmp(dev, cfdata[i].cf_driver->cd_name,
897 len) == 0 &&
898 (state == FSTATE_FOUND1 ||
899 (state == FSTATE_STAR2 &&
900 (cfdata[i].cf_fstate == FSTATE_STAR2 ||
901 cfdata[i].cf_fstate == FSTATE_DSTAR4)) ||
902 (state == FSTATE_NOTFOUND0 &&
903 cfdata[i].cf_unit == unit &&
904 (cfdata[i].cf_fstate == FSTATE_NOTFOUND0 ||
905 cfdata[i].cf_fstate == FSTATE_DNOTFOUND3)))) {
906 if (userconf_more())
907 break;
908 switch (routine) {
909 case UC_CHANGE'c':
910 userconf_change(i);
911 break;
912 case UC_ENABLE'e':
913 userconf_enable(i);
914 break;
915 case UC_DISABLE'd':
916 userconf_disable(i);
917 break;
918 case UC_FIND'f':
919 userconf_pdev(i);
920 break;
921 default:
922 printf("Unknown routine /%c/\n",
923 routine);
924 break;
925 }
926 }
927 }
928 i++;
929 }
930
931 for (i = 0; i < pdevnames_size; i++) {
932 if (strncasecmp(dev, pdevnames[i], len) == 0 &&
933 state == FSTATE_FOUND1) {
934 switch(routine) {
935 case UC_CHANGE'c':
936 userconf_change(userconf_totdev+1+i);
937 break;
938 case UC_ENABLE'e':
939 userconf_enable(userconf_totdev+1+i);
940 break;
941 case UC_DISABLE'd':
942 userconf_disable(userconf_totdev+1+i);
943 break;
944 case UC_FIND'f':
945 userconf_pdev(userconf_totdev+1+i);
946 break;
947 default:
948 printf("Unknown pseudo routine /%c/\n",routine);
949 break;
950 }
951 }
952 }
953
954 switch (routine) {
955 case UC_CHANGE'c':
956 break;
957 default:
958 userconf_cnt = -1;
959 break;
960 }
961}
962
963void
964userconf_common_attr(char *cmd, int attr, char routine)
965{
966 char *c;
967 short l = 0;
968 long a;
969
970 c = cmd;
971 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
972 c++;
973 l++;
974 }
975 while (*c == ' ' || *c == '\t' || *c == '\n')
976 c++;
977
978 if (*c == '\0') {
979 printf("Value missing for attribute\n");
980 return;
981 }
982
983 if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0) {
984 userconf_common_attr_val(attr, &a, routine);
985 } else {
986 printf("Unknown argument\n");
987 }
988}
989
990void
991userconf_add_read(char *prompt, char field, char *dev, int len, long *val)
992{
993 int ok = 0;
994 long a;
995 char *c;
996 int i;
997
998 *val = -1;
999
1000 while (!ok) {
1001 printf("%s ? ", prompt);
1002
1003 i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
Value stored to 'i' is never read
1004
1005 c = userconf_argbuf;
1006 while (*c == ' ' || *c == '\t' || *c == '\n')
1007 c++;
1008
1009 if (*c != '\0') {
1010 if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0) {
1011 if (a > userconf_maxdev) {
1012 printf("Unknown devno (max is %d)\n",
1013 userconf_maxdev);
1014 } else if (strncasecmp(dev,
1015 cfdata[a].cf_driver->cd_name, len) != 0 &&
1016 field == 'a') {
1017 printf("Not same device type\n");
1018 } else {
1019 *val = a;
1020 ok = 1;
1021 }
1022 } else if (*c == '?') {
1023 userconf_common_dev(dev, len, 0,
1024 FSTATE_FOUND1, UC_FIND'f');
1025 } else if (*c == 'q' || *c == 'Q') {
1026 ok = 1;
1027 } else {
1028 printf("Unknown argument\n");
1029 }
1030 } else {
1031 ok = 1;
1032 }
1033 }
1034}
1035
1036void
1037userconf_add(char *dev, int len, short unit, short state)
1038{
1039 int found = 0;
1040 struct cfdata new;
1041 int max_unit, star_unit;
1042 long i = 0, val, orig;
1043
1044 memset(&new, 0, sizeof(struct cfdata))__builtin_memset((&new), (0), (sizeof(struct cfdata)));
1045
1046 if (userconf_maxdev == userconf_totdev) {
1047 printf("No more space for new devices.\n");
1048 return;
1049 }
1050
1051 if (state == FSTATE_FOUND1) {
1052 printf("Device not complete number or * is missing\n");
1053 return;
1054 }
1055
1056 for (i = 0; cfdata[i].cf_driver; i++)
1057 if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1058 strncasecmp(dev, cfdata[i].cf_driver->cd_name, len) == 0)
1059 found = 1;
1060
1061 if (!found) {
1062 printf("No device of this type exists.\n");
1063 return;
1064 }
1065
1066 userconf_add_read("Clone Device (DevNo, 'q' or '?')",
1067 'a', dev, len, &val);
1068
1069 if (val != -1) {
1070 orig = val;
1071 new = cfdata[val];
1072 new.cf_unit = unit;
1073 new.cf_fstate = state;
1074 userconf_add_read("Insert before Device (DevNo, 'q' or '?')",
1075 'i', dev, len, &val);
1076 }
1077
1078 if (val != -1) {
1079 /* XXX add cmd 'a' <orig> <val> eoc */
1080 userconf_hist_cmd('a');
1081 userconf_hist_int(orig);
1082 userconf_hist_int(unit);
1083 userconf_hist_int(state);
1084 userconf_hist_int(val);
1085 userconf_hist_eoc();
1086
1087 /* Insert the new record */
1088 for (i = userconf_maxdev; val <= i; i--)
1089 cfdata[i+1] = cfdata[i];
1090 cfdata[val] = new;
1091
1092 /* Fix indexs in pv */
1093 for (i = 0; i < pv_size; i++) {
1094 if (pv[i] != -1 && pv[i] >= val)
1095 pv[i]++;
1096 }
1097
1098 /* Fix indexs in cfroots */
1099 for (i = 0; i < cfroots_size; i++) {
1100 if (cfroots[i] != -1 && cfroots[i] >= val)
1101 cfroots[i]++;
1102 }
1103
1104 userconf_maxdev++;
1105
1106 max_unit = -1;
1107
1108 /* Find max unit number of the device type */
1109
1110 i = 0;
1111 while (cfdata[i].cf_attach != NULL((void *)0)) {
1112 if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1113 strncasecmp(dev, cfdata[i].cf_driver->cd_name,
1114 len) == 0) {
1115 switch (cfdata[i].cf_fstate) {
1116 case FSTATE_NOTFOUND0:
1117 case FSTATE_DNOTFOUND3:
1118 if (cfdata[i].cf_unit > max_unit)
1119 max_unit = cfdata[i].cf_unit;
1120 break;
1121 default:
1122 break;
1123 }
1124 }
1125 i++;
1126 }
1127
1128 /*
1129 * For all * entries set unit number to max+1, and update
1130 * cf_starunit1 if necessary.
1131 */
1132 max_unit++;
1133 star_unit = -1;
1134
1135 i = 0;
1136 while (cfdata[i].cf_attach != NULL((void *)0)) {
1137 if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1138 strncasecmp(dev, cfdata[i].cf_driver->cd_name,
1139 len) == 0) {
1140 switch (cfdata[i].cf_fstate) {
1141 case FSTATE_NOTFOUND0:
1142 case FSTATE_DNOTFOUND3:
1143 if (cfdata[i].cf_unit > star_unit)
1144 star_unit = cfdata[i].cf_unit;
1145 break;
1146 default:
1147 break;
1148 }
1149 }
1150 i++;
1151 }
1152 star_unit++;
1153
1154 i = 0;
1155 while (cfdata[i].cf_attach != NULL((void *)0)) {
1156 if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1157 strncasecmp(dev, cfdata[i].cf_driver->cd_name,
1158 len) == 0) {
1159 switch (cfdata[i].cf_fstate) {
1160 case FSTATE_STAR2:
1161 case FSTATE_DSTAR4:
1162 cfdata[i].cf_unit = max_unit;
1163 if (cfdata[i].cf_starunit1 < star_unit)
1164 cfdata[i].cf_starunit1 =
1165 star_unit;
1166 break;
1167 default:
1168 break;
1169 }
1170 }
1171 i++;
1172 }
1173 userconf_pdev(val);
1174 }
1175
1176 /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags,
1177 cf_parents, cf_locnames, and cf_locnames */
1178}
1179
1180int
1181userconf_parse(char *cmd)
1182{
1183 char *c, *v;
1184 int i = 0, j = 0, k;
1185 long a;
1186 short unit, state;
1187
1188 c = cmd;
1189 while (*c == ' ' || *c == '\t')
1190 c++;
1191 v = c;
1192 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
1193 c++;
1194 i++;
1195 }
1196
1197 k = -1;
1198 while (*userconf_cmds[j] != '\0') {
1199 if (strlen(userconf_cmds[j]) == i) {
1200 if (strncasecmp(v, userconf_cmds[j], i) == 0)
1201 k = j;
1202 }
1203 j += 2;
1204 }
1205
1206 while (*c == ' ' || *c == '\t' || *c == '\n')
1207 c++;
1208
1209 if (k == -1) {
1210 if (*v != '\n')
1211 printf("Unknown command, try help\n");
1212 } else {
1213 switch (*userconf_cmds[k+1]) {
1214 case 'L':
1215 if (*c == '\0')
1216 printf("Argument expected\n");
1217 else if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0)
1218 userconf_lines = a;
1219 else
1220 printf("Unknown argument\n");
1221 break;
1222 case 'a':
1223 if (*c == '\0')
1224 printf("Dev expected\n");
1225 else if (userconf_device(c, &a, &unit, &state) == 0)
1226 userconf_add(c, a, unit, state);
1227 else
1228 printf("Unknown argument\n");
1229 break;
1230 case 'b':
1231 if (*c == '\0')
1232 printf("8|10|16 expected\n");
1233 else if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0) {
1234 if (a == 8 || a == 10 || a == 16) {
1235 userconf_base = a;
1236 } else {
1237 printf("8|10|16 expected\n");
1238 }
1239 } else
1240 printf("Unknown argument\n");
1241 break;
1242 case 'c':
1243 if (*c == '\0')
1244 printf("DevNo or Dev expected\n");
1245 else if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0)
1246 userconf_change(a);
1247 else if (userconf_device(c, &a, &unit, &state) == 0)
1248 userconf_common_dev(c, a, unit, state, UC_CHANGE'c');
1249 else
1250 printf("Unknown argument\n");
1251 break;
1252#if defined(DDB1)
1253 case 'D':
1254 db_enter();
1255 break;
1256#endif
1257 case 'd':
1258 if (*c == '\0')
1259 printf("Attr, DevNo or Dev expected\n");
1260 else if (userconf_attr(c, &a) == 0)
1261 userconf_common_attr(c, a, UC_DISABLE'd');
1262 else if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0)
1263 userconf_disable(a);
1264 else if (userconf_device(c, &a, &unit, &state) == 0)
1265 userconf_common_dev(c, a, unit, state, UC_DISABLE'd');
1266 else
1267 printf("Unknown argument\n");
1268 break;
1269 case 'e':
1270 if (*c == '\0')
1271 printf("Attr, DevNo or Dev expected\n");
1272 else if (userconf_attr(c, &a) == 0)
1273 userconf_common_attr(c, a, UC_ENABLE'e');
1274 else if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0)
1275 userconf_enable(a);
1276 else if (userconf_device(c, &a, &unit, &state) == 0)
1277 userconf_common_dev(c, a, unit, state, UC_ENABLE'e');
1278 else
1279 printf("Unknown argument\n");
1280 break;
1281 case 'f':
1282 if (*c == '\0')
1283 printf("DevNo or Dev expected\n");
1284 else if (userconf_number(c, &a, INT_MAX0x7fffffff) == 0)
1285 userconf_pdev(a);
1286 else if (userconf_device(c, &a, &unit, &state) == 0)
1287 userconf_common_dev(c, a, unit, state, UC_FIND'f');
1288 else
1289 printf("Unknown argument\n");
1290 break;
1291 case 'h':
1292 userconf_help();
1293 break;
1294 case 'l':
1295 if (*c == '\0')
1296 userconf_list();
1297 else
1298 printf("Unknown argument\n");
1299 break;
1300 case 'q':
1301 /* XXX add cmd 'q' eoc */
1302 userconf_hist_cmd('q');
1303 userconf_hist_eoc();
1304 return(-1);
1305 break;
1306 case 's':
1307 if (*c == '\0')
1308 userconf_show();
1309 else
1310 userconf_show_attr(c);
1311 break;
1312 case 'v':
1313 autoconf_verbose = !autoconf_verbose;
1314 printf("autoconf verbose %sabled\n",
1315 autoconf_verbose ? "en" : "dis");
1316 break;
1317 default:
1318 printf("Unknown command\n");
1319 break;
1320 }
1321 }
1322 return(0);
1323}
1324
1325void
1326user_config(void)
1327{
1328 userconf_init();
1329 printf("User Kernel Config\n");
1330
1331 cnpollc(1);
1332 while (1) {
1333 printf("UKC> ");
1334 if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 &&
1335 userconf_parse(userconf_cmdbuf))
1336 break;
1337 }
1338 cnpollc(0);
1339
1340 printf("Continuing...\n");
1341}