In-kernel device configuration manager - allows modification

of device locators at run-time.

Written by Mats O Jansson <moj@stacken.kth.se>.  Reworked by
Jun-ichiro itojun Hagino <itojun@netbsd.org>.
This commit is contained in:
gmcgarry 2001-07-01 02:56:20 +00:00
parent 32fc55d6d2
commit d6182a9e77
10 changed files with 1131 additions and 13 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.374 2001/06/27 23:11:31 wiz Exp $
# $NetBSD: mi,v 1.375 2001/07/01 02:56:21 gmcgarry Exp $
./usr/share/info/am-utils.info man-amd-info
./usr/share/info/as.info man-computil-info
./usr/share/info/awk.info man-util-info
@ -869,6 +869,7 @@
./usr/share/man/cat4/usb.0 man-sys-catman
./usr/share/man/cat4/uscanner.0 man-sys-catman
./usr/share/man/cat4/usscanner.0 man-sys-catman
./usr/share/man/cat4/userconf.0 man-sys-catman
./usr/share/man/cat4/uvisor.0 man-sys-catman
./usr/share/man/cat4/uyap.0 man-sys-catman
./usr/share/man/cat4/vax/acc.0 man-sys-catman
@ -2409,6 +2410,7 @@
./usr/share/man/man4/usb.4 man-sys-man
./usr/share/man/man4/uscanner.4 man-sys-man
./usr/share/man/man4/usscanner.4 man-sys-man
./usr/share/man/man4/userconf.4 man-sys-man
./usr/share/man/man4/uvisor.4 man-sys-man
./usr/share/man/man4/uyap.4 man-sys-man
./usr/share/man/man4/vax/acc.4 man-sys-man

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.207 2001/06/28 21:12:01 fredette Exp $
# $NetBSD: Makefile,v 1.208 2001/07/01 02:56:21 gmcgarry Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= adv.4 adw.4 ahb.4 ahc.4 an.4 aria.4 atalk.4 audio.4 auich.4 auvia.4 \
@ -17,8 +17,8 @@ MAN= adv.4 adw.4 ahb.4 ahc.4 an.4 aria.4 atalk.4 audio.4 auich.4 auvia.4 \
rtk.4 sbus.4 scsi.4 sd.4 se.4 ses.4 sf.4 siop.4 sip.4 sl.4 sm.4 \
speaker.4 spp.4 sqphy.4 ss.4 st.4 ste.4 sv.4 strip.4 tb.4 tcp.4 \
termios.4 ti.4 tl.4 tlp.4 tlphy.4 tp.4 tr.4 tty.4 tun.4 tqphy.4 twe.4 \
udp.4 uha.4 uk.4 ukphy.4 unix.4 vga.4 vlan.4 vnd.4 vr.4 wd.4 \
wdc.4 wi.4 wscons.4 wsdisplay.4 wskbd.4 wsmouse.4 \
udp.4 uha.4 uk.4 ukphy.4 unix.4 userconf.4 vga.4 vlan.4 vnd.4 \
vr.4 wd.4 wdc.4 wi.4 wscons.4 wsdisplay.4 wskbd.4 wsmouse.4 \
wsmux.4 yds.4 ym.4 zero.4 zstty.4
# USB devices

150
share/man/man4/userconf.4 Normal file
View File

@ -0,0 +1,150 @@
.\" $NetBSD: userconf.4,v 1.1 2001/07/01 02:56:21 gmcgarry Exp $
.\"
.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Gregory McGarry.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd July 1, 2001
.Dt USERCONF 9
.Os
.Sh NAME
.Nm userconf
.Nd in-kernel device configuration manager
.Sh SYNOPSIS
.Cd options USERCONF
.Sh DESCRIPTION
.Nm
is the in-kernel device configuration manager. It is used to alter
the kernel autoconfiguration framework at runtime.
.Nm
is activated from the boot loader by passing the
-c
option to the kernel.
.Sh COMMAND SYNTAX
The general command syntax is:
.Bd -ragged -offset indent
.Ic command Op Ar option
.Ed
.Pp
.Nm
has a
.Xr more 1 -like
functionality; if a number of lines in a command's output exceeds the
number defined in the lines variable, then
.Nm displays
.Dq "-- more --"
and waits for a response, which may be one of:
.Bl -tag -offset indent -width "<return>"
.It <return>
one more line.
.It <space>
one more page.
.It Ic q
abort the current command, and return to the command input mode.
.El
.Pp
.Sh COMMANDS
.Nm
supports the following commands:
.Bl -tag -width 5n
.It Xo
.Ic lines
.Ar count
.Xc
Specify the number of lines before more.
.It Xo
.Ic base
.Ar 8 |
.Ar 10 |
.Ar 16
.Xc
Base for displaying large numbers.
.It Xo
.Ic change
.Ar devno |
.Ar dev
.Xc
Change devices.
.It Xo
.Ic disable
.Ar devno |
.Ar dev
.Xc
Disable devices.
.It Xo
.Ic enable
.Ar devno |
.Ar dev
.Xc
Enable devices.
.It Xo
.Ic exit
.Xc
A synonym for
.Ic quit .
.It Xo
.Ic find
.Ar devno |
.Ar dev
.Xc
Find devices.
.It Xo
.Ic help
.Xc
Display online help.
.It Xo
.Ic list
.Xc
List current configuration.
.It Xo
.Ic quit
.Xc
Leave userconf.
.It Xo
.Ic ?
.Xc
A synomym for
.Ic help .
.El
.Sh AUTHOR
The
.Nm
framework was written by
.An Mats O Jansson
.Aq moj@stacken.kth.se .
.Sh HISTORY
The
.Nm
framework appeared in
.Nx 1.6 .

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.448 2001/06/19 17:58:41 jdolecek Exp $
# $NetBSD: files,v 1.449 2001/07/01 02:56:20 gmcgarry Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@ -122,6 +122,9 @@ defopt RAID_AUTOCONFIG
# buffer cache size options
defopt opt_bufcache.h BUFCACHE BUFPAGES
# userconf
defopt opt_userconf.h USERCONF
# Not entirely MI, but present on multiple arch's
@ -862,6 +865,7 @@ file kern/subr_pool.c
file kern/subr_prf.c
file kern/subr_prof.c
file kern/subr_rmap.c
file kern/subr_userconf.c userconf
file kern/subr_xxx.c
file kern/sys_generic.c
file kern/sys_pipe.c new_pipe

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_autoconf.c,v 1.56 2001/05/28 16:40:31 thorpej Exp $ */
/* $NetBSD: subr_autoconf.c,v 1.57 2001/07/01 02:56:20 gmcgarry Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@ -82,7 +82,7 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.56 2001/05/28 16:40:31 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.57 2001/07/01 02:56:20 gmcgarry Exp $");
#include <sys/param.h>
#include <sys/device.h>
@ -93,6 +93,12 @@ __KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.56 2001/05/28 16:40:31 thorpej E
#include <sys/proc.h>
#include <machine/limits.h>
#include "opt_userconf.h"
#ifdef USERCONF
#include <sys/userconf.h>
#include <sys/reboot.h>
#endif
/*
* Autoconfiguration subroutines.
*/
@ -150,6 +156,11 @@ configure(void)
TAILQ_INIT(&interrupt_config_queue);
TAILQ_INIT(&alldevs);
#ifdef USERCONF
if (boothowto & RB_USERCONF)
user_config();
#endif
/*
* Do the machine-dependent portion of autoconfiguration. This
* sets the configuration machinery here in motion by "finding"

904
sys/kern/subr_userconf.c Normal file
View File

@ -0,0 +1,904 @@
/* $NetBSD: subr_userconf.c,v 1.1 2001/07/01 02:56:20 gmcgarry Exp $ */
/*
* Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Mats O Jansson.
* 4. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* OpenBSD: subr_userconf.c,v 1.19 2000/01/08 23:23:37 d Exp
*/
#include "opt_userconf.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/time.h>
#include <dev/cons.h>
extern struct cfdata cfdata[];
int userconf_base = 16; /* Base for "large" numbers */
int userconf_maxdev = -1; /* # of used device slots */
int userconf_totdev = -1; /* # of device slots */
int userconf_maxlocnames = -1; /* # of locnames */
int userconf_cnt = -1; /* Line counter for ... */
int userconf_lines = 12; /* ... # of lines per page */
int userconf_histlen = 0;
int userconf_histcur = 0;
char userconf_history[1024];
int userconf_histsz = sizeof(userconf_history);
char userconf_argbuf[40]; /* Additional input */
char userconf_cmdbuf[40]; /* Command line */
char userconf_histbuf[40];
void userconf_init __P((void));
int userconf_more __P((void));
void userconf_modify __P((const char *, int*));
void userconf_hist_cmd __P((char));
void userconf_hist_int __P((int));
void userconf_hist_eoc __P((void));
void userconf_pnum __P((int));
void userconf_pdevnam __P((short));
void userconf_pdev __P((short));
int userconf_number __P((char *, int *));
int userconf_device __P((char *, int *, short *, short *));
void userconf_change __P((int));
void userconf_disable __P((int));
void userconf_enable __P((int));
void userconf_help __P((void));
void userconf_list __P((void));
void userconf_common_dev __P((char *, int, short, short, char));
void userconf_add_read __P((char *, char, char *, int, int *));
int userconf_parse __P((char *));
static int getsn __P((char *, int));
#define UC_CHANGE 'c'
#define UC_DISABLE 'd'
#define UC_ENABLE 'e'
#define UC_FIND 'f'
#define UC_SHOW 's'
char *userconf_cmds[] = {
"base", "b",
"change", "c",
"disable", "d",
"enable", "e",
"exit", "q",
"find", "f",
"help", "h",
"list", "l",
"lines", "L",
"quit", "q",
"?", "h",
"", "",
};
void
userconf_init()
{
int i;
struct cfdata *cf;
i = 0;
for (cf = cfdata; cf->cf_driver; cf++)
i++;
userconf_maxdev = i - 1;
userconf_totdev = i - 1;
}
int
userconf_more()
{
int quit = 0;
char c = '\0';
if (userconf_cnt != -1) {
if (userconf_cnt == userconf_lines) {
printf("-- more --");
c = cngetc();
userconf_cnt = 0;
printf("\r \r");
}
userconf_cnt++;
if (c == 'q' || c == 'Q')
quit = 1;
}
return (quit);
}
void
userconf_hist_cmd(cmd)
char cmd;
{
userconf_histcur = userconf_histlen;
if (userconf_histcur < userconf_histsz) {
userconf_history[userconf_histcur] = cmd;
userconf_histcur++;
}
}
void
userconf_hist_int(val)
int val;
{
sprintf(userconf_histbuf," %d",val);
if ((userconf_histcur + strlen(userconf_histbuf)) < userconf_histsz) {
bcopy(userconf_histbuf,
&userconf_history[userconf_histcur],
strlen(userconf_histbuf));
userconf_histcur = userconf_histcur + strlen(userconf_histbuf);
}
}
void
userconf_hist_eoc()
{
if (userconf_histcur < userconf_histsz) {
userconf_history[userconf_histcur] = '\n';
userconf_histcur++;
userconf_histlen = userconf_histcur;
}
}
void
userconf_pnum(val)
int val;
{
if (val > -2 && val < 16) {
printf("%d",val);
} else {
switch (userconf_base) {
case 8:
printf("0%o",val);
break;
case 10:
printf("%d",val);
break;
case 16:
default:
printf("0x%x",val);
break;
}
}
}
void
userconf_pdevnam(dev)
short dev;
{
struct cfdata *cd;
cd = &cfdata[dev];
printf("%s", cd->cf_driver->cd_name);
switch (cd->cf_fstate) {
case FSTATE_NOTFOUND:
case FSTATE_DNOTFOUND:
printf("%d", cd->cf_unit);
break;
case FSTATE_FOUND:
printf("*FOUND*");
break;
case FSTATE_STAR:
case FSTATE_DSTAR:
printf("*");
break;
default:
printf("*UNKNOWN*");
break;
}
}
void
userconf_pdev(devno)
short devno;
{
struct cfdata *cd;
short *p;
int *l;
const char **ln;
char c;
if (devno > userconf_maxdev) {
printf("Unknown devno (max is %d)\n", userconf_maxdev);
return;
}
cd = &cfdata[devno];
printf("[%3d] ", devno);
userconf_pdevnam(devno);
printf(" at");
c = ' ';
p = cd->cf_parents;
if (*p == -1)
printf(" root");
while (*p != -1) {
printf("%c", c);
userconf_pdevnam(*p++);
c = '|';
}
switch (cd->cf_fstate) {
case FSTATE_NOTFOUND:
case FSTATE_FOUND:
case FSTATE_STAR:
break;
case FSTATE_DNOTFOUND:
case FSTATE_DSTAR:
printf(" disable");
break;
default:
printf(" ???");
break;
}
l = cd->cf_loc;
ln = cd->cf_locnames;
while (ln && *ln) {
printf(" %s ", *ln++);
userconf_pnum(*l++);
}
printf("\n");
}
int
userconf_number(c, val)
char *c;
int *val;
{
u_int num = 0;
int neg = 0;
int base = 10;
if (*c == '-') {
neg = 1;
c++;
}
if (*c == '0') {
base = 8;
c++;
if (*c == 'x' || *c == 'X') {
base = 16;
c++;
}
}
while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') {
u_char cc = *c;
if (cc >= '0' && cc <= '9')
cc = cc - '0';
else if (cc >= 'a' && cc <= 'f')
cc = cc - 'a' + 10;
else if (cc >= 'A' && cc <= 'F')
cc = cc - 'A' + 10;
else
return (-1);
if (cc > base)
return (-1);
num = num * base + cc;
c++;
}
if (neg && num > INT_MAX) /* overflow */
return (1);
*val = neg ? - num : num;
return (0);
}
int
userconf_device(cmd, len, unit, state)
char *cmd;
int *len;
short *unit, *state;
{
short u = 0, s = FSTATE_FOUND;
int l = 0;
char *c;
c = cmd;
while (*c >= 'a' && *c <= 'z') {
l++;
c++;
}
if (*c == '*') {
s = FSTATE_STAR;
c++;
} else {
while (*c >= '0' && *c <= '9') {
s = FSTATE_NOTFOUND;
u = u*10 + *c - '0';
c++;
}
}
while (*c == ' ' || *c == '\t' || *c == '\n')
c++;
if (*c == '\0') {
*len = l;
*unit = u;
*state = s;
return(0);
}
return(-1);
}
void
userconf_modify(item, val)
const char *item;
int *val;
{
int ok = 0;
int a;
char *c;
int i;
while (!ok) {
printf("%s [", item);
userconf_pnum(*val);
printf("] ? ");
i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
c = userconf_argbuf;
while (*c == ' ' || *c == '\t' || *c == '\n') c++;
if (*c != '\0') {
if (userconf_number(c, &a) == 0) {
*val = a;
ok = 1;
} else {
printf("Unknown argument\n");
}
} else {
ok = 1;
}
}
}
void
userconf_change(devno)
int devno;
{
struct cfdata *cd;
char c = '\0';
int *l;
int ln;
const char **locnames;
if (devno <= userconf_maxdev) {
userconf_pdev(devno);
while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
printf("change (y/n) ?");
c = cngetc();
printf("\n");
}
if (c == 'y' || c == 'Y') {
/* XXX add cmd 'c' <devno> */
userconf_hist_cmd('c');
userconf_hist_int(devno);
cd = &cfdata[devno];
l = cd->cf_loc;
locnames = cd->cf_locnames;
ln = 0;
while (locnames[ln])
{
userconf_modify(locnames[ln], l);
/* XXX add *l */
userconf_hist_int(*l);
ln++;
l++;
}
#ifdef __OpenSBD__
if (share) {
if (bcmp(cd->cf_loc, lk, sizeof(int) * i))
cd->cf_loc = lk;
else
free(lk, M_TEMP);
}
#endif
printf("[%3d] ", devno);
userconf_pdevnam(devno);
printf(" changed\n");
userconf_pdev(devno);
/* XXX add eoc */
userconf_hist_eoc();
}
} else {
printf("Unknown devno (max is %d)\n", userconf_maxdev);
}
}
void
userconf_disable(devno)
int devno;
{
int done = 0;
if (devno <= userconf_maxdev) {
switch (cfdata[devno].cf_fstate) {
case FSTATE_NOTFOUND:
cfdata[devno].cf_fstate = FSTATE_DNOTFOUND;
break;
case FSTATE_STAR:
cfdata[devno].cf_fstate = FSTATE_DSTAR;
break;
case FSTATE_DNOTFOUND:
case FSTATE_DSTAR:
done = 1;
break;
default:
printf("Error unknown state\n");
break;
}
printf("[%3d] ", devno);
userconf_pdevnam(devno);
if (done) {
printf(" already");
} else {
/* XXX add cmd 'd' <devno> eoc */
userconf_hist_cmd('d');
userconf_hist_int(devno);
userconf_hist_eoc();
}
printf(" disabled\n");
} else {
printf("Unknown devno (max is %d)\n", userconf_maxdev);
}
}
void
userconf_enable(devno)
int devno;
{
int done = 0;
if (devno <= userconf_maxdev) {
switch (cfdata[devno].cf_fstate) {
case FSTATE_DNOTFOUND:
cfdata[devno].cf_fstate = FSTATE_NOTFOUND;
break;
case FSTATE_DSTAR:
cfdata[devno].cf_fstate = FSTATE_STAR;
break;
case FSTATE_NOTFOUND:
case FSTATE_STAR:
done = 1;
break;
default:
printf("Error unknown state\n");
break;
}
printf("[%3d] ", devno);
userconf_pdevnam(devno);
if (done) {
printf(" already");
} else {
/* XXX add cmd 'e' <devno> eoc */
userconf_hist_cmd('d');
userconf_hist_int(devno);
userconf_hist_eoc();
}
printf(" enabled\n");
} else {
printf("Unknown devno (max is %d)\n", userconf_maxdev);
}
}
void
userconf_help()
{
int j = 0, k;
printf("command args description\n");
while (*userconf_cmds[j] != '\0') {
printf(userconf_cmds[j]);
k = strlen(userconf_cmds[j]);
while (k < 10) {
printf(" ");
k++;
}
switch (*userconf_cmds[j+1]) {
case 'L':
printf("[count] number of lines before more");
break;
case 'b':
printf("8|10|16 base on large numbers");
break;
case 'c':
printf("devno|dev change devices");
break;
case 'd':
printf("devno|dev disable devices");
break;
case 'e':
printf("devno|dev enable devices");
break;
case 'f':
printf("devno|dev find devices");
break;
case 'h':
printf(" this message");
break;
case 'l':
printf(" list configuration");
break;
case 'q':
printf(" leave userconf");
break;
default:
printf(" don't know");
break;
}
printf("\n");
j += 2;
}
}
void
userconf_list()
{
int i = 0;
userconf_cnt = 0;
while (cfdata[i].cf_attach != 0) {
if (userconf_more())
break;
userconf_pdev(i++);
}
userconf_cnt = -1;
}
void
userconf_common_dev(dev, len, unit, state, routine)
char *dev;
int len;
short unit, state;
char routine;
{
int i = 0;
switch (routine) {
case UC_CHANGE:
break;
default:
userconf_cnt = 0;
break;
}
while (cfdata[i].cf_attach != 0) {
if (strlen(cfdata[i].cf_driver->cd_name) == len) {
/*
* Ok, if device name is correct
* If state == FSTATE_FOUND, look for "dev"
* If state == FSTATE_STAR, look for "dev*"
* If state == FSTATE_NOTFOUND, look for "dev0"
*/
if (strncasecmp(dev, cfdata[i].cf_driver->cd_name,
len) == 0 &&
(state == FSTATE_FOUND ||
(state == FSTATE_STAR &&
(cfdata[i].cf_fstate == FSTATE_STAR ||
cfdata[i].cf_fstate == FSTATE_DSTAR)) ||
(state == FSTATE_NOTFOUND &&
cfdata[i].cf_unit == unit &&
(cfdata[i].cf_fstate == FSTATE_NOTFOUND ||
cfdata[i].cf_fstate == FSTATE_DNOTFOUND)))) {
if (userconf_more())
break;
switch (routine) {
case UC_CHANGE:
userconf_change(i);
break;
case UC_ENABLE:
userconf_enable(i);
break;
case UC_DISABLE:
userconf_disable(i);
break;
case UC_FIND:
userconf_pdev(i);
break;
default:
printf("Unknown routine /%c/\n",
routine);
break;
}
}
}
i++;
}
switch (routine) {
case UC_CHANGE:
break;
default:
userconf_cnt = -1;
break;
}
}
void
userconf_add_read(prompt, field, dev, len, val)
char *prompt;
char field;
char *dev;
int len;
int *val;
{
int ok = 0;
int a;
char *c;
int i;
*val = -1;
while (!ok) {
printf("%s ? ", prompt);
i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
c = userconf_argbuf;
while (*c == ' ' || *c == '\t' || *c == '\n') c++;
if (*c != '\0') {
if (userconf_number(c, &a) == 0) {
if (a > userconf_maxdev) {
printf("Unknown devno (max is %d)\n",
userconf_maxdev);
} else if (strncasecmp(dev,
cfdata[a].cf_driver->cd_name, len) != 0 &&
field == 'a') {
printf("Not same device type\n");
} else {
*val = a;
ok = 1;
}
} else if (*c == '?') {
userconf_common_dev(dev, len, 0,
FSTATE_FOUND, UC_FIND);
} else if (*c == 'q' || *c == 'Q') {
ok = 1;
} else {
printf("Unknown argument\n");
}
} else {
ok = 1;
}
}
}
int
userconf_parse(cmd)
char *cmd;
{
char *c, *v;
int i = 0, j = 0, k, a;
short unit, state;
c = cmd;
while (*c == ' ' || *c == '\t')
c++;
v = c;
while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
c++;
i++;
}
k = -1;
while (*userconf_cmds[j] != '\0') {
if (strlen(userconf_cmds[j]) == i) {
if (strncasecmp(v, userconf_cmds[j], i) == 0)
k = j;
}
j += 2;
}
while (*c == ' ' || *c == '\t' || *c == '\n')
c++;
if (k == -1) {
if (*v != '\n')
printf("Unknown command, try help\n");
} else {
switch (*userconf_cmds[k+1]) {
case 'L':
if (*c == '\0')
printf("Argument expected\n");
else if (userconf_number(c, &a) == 0)
userconf_lines = a;
else
printf("Unknown argument\n");
break;
case 'b':
if (*c == '\0')
printf("8|10|16 expected\n");
else if (userconf_number(c, &a) == 0) {
if (a == 8 || a == 10 || a == 16) {
userconf_base = a;
} else {
printf("8|10|16 expected\n");
}
} else
printf("Unknown argument\n");
break;
case 'c':
if (*c == '\0')
printf("DevNo or Dev expected\n");
else if (userconf_number(c, &a) == 0)
userconf_change(a);
else if (userconf_device(c, &a, &unit, &state) == 0)
userconf_common_dev(c, a, unit, state, UC_CHANGE);
else
printf("Unknown argument\n");
break;
case 'd':
if (*c == '\0')
printf("Attr, DevNo or Dev expected\n");
else if (userconf_number(c, &a) == 0)
userconf_disable(a);
else if (userconf_device(c, &a, &unit, &state) == 0)
userconf_common_dev(c, a, unit, state, UC_DISABLE);
else
printf("Unknown argument\n");
break;
case 'e':
if (*c == '\0')
printf("Attr, DevNo or Dev expected\n");
else if (userconf_number(c, &a) == 0)
userconf_enable(a);
else if (userconf_device(c, &a, &unit, &state) == 0)
userconf_common_dev(c, a, unit, state, UC_ENABLE);
else
printf("Unknown argument\n");
break;
case 'f':
if (*c == '\0')
printf("DevNo or Dev expected\n");
else if (userconf_number(c, &a) == 0)
userconf_pdev(a);
else if (userconf_device(c, &a, &unit, &state) == 0)
userconf_common_dev(c, a, unit, state, UC_FIND);
else
printf("Unknown argument\n");
break;
case 'h':
userconf_help();
break;
case 'l':
if (*c == '\0')
userconf_list();
else
printf("Unknown argument\n");
break;
case 'q':
/* XXX add cmd 'q' eoc */
userconf_hist_cmd('q');
userconf_hist_eoc();
return(-1);
break;
case 's':
default:
printf("Unknown command\n");
break;
}
}
return(0);
}
extern void user_config __P((void));
void
user_config()
{
char prompt[] = "uc> ";
userconf_init();
printf("userconf: configure system autoconfiguration:\n");
while (1) {
printf(prompt);
if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 &&
userconf_parse(userconf_cmdbuf))
break;
}
printf("Continuing...\n");
}
/*
* XXX shouldn't this be a common function?
*/
static int
getsn(cp, size)
char *cp;
int size;
{
char *lp;
int c, len;
cnpollc(1);
lp = cp;
len = 0;
for (;;) {
c = cngetc();
switch (c) {
case '\n':
case '\r':
printf("\n");
*lp++ = '\0';
cnpollc(0);
return (len);
case '\b':
case '\177':
case '#':
if (len) {
--len;
--lp;
printf("\b \b");
}
continue;
case '@':
case 'u'&037:
len = 0;
lp = cp;
printf("\n");
continue;
default:
if (len + 1 >= size || c < ' ') {
printf("\007");
continue;
}
printf("%c", c);
++len;
*lp++ = c;
}
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: boot_flag.h,v 1.2 2001/04/30 01:13:20 lukem Exp $ */
/* $NetBSD: boot_flag.h,v 1.3 2001/07/01 02:56:21 gmcgarry Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -53,6 +53,9 @@
case 'b': /* always halt, never reboot */ \
(retval) |= RB_HALT; \
break; \
case 'c': /* userconf */ \
(retval) |= RB_USERCONF; \
break; \
case 'd': /* break into the kernel debugger ASAP (if compiled in) */ \
(retval) |= RB_KDB; \
break; \

View File

@ -1,4 +1,4 @@
/* $NetBSD: device.h,v 1.45 2000/12/01 02:07:04 simonb Exp $ */
/* $NetBSD: device.h,v 1.46 2001/07/01 02:56:20 gmcgarry Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@ -176,6 +176,8 @@ struct cfdata {
#define FSTATE_NOTFOUND 0 /* has not been found */
#define FSTATE_FOUND 1 /* has been found */
#define FSTATE_STAR 2 /* duplicable */
#define FSTATE_DSTAR 3 /* has not been found, and disabled */
#define FSTATE_DNOTFOUND 4 /* duplicate, and disabled */
typedef int (*cfmatch_t)(struct device *, struct cfdata *, void *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: reboot.h,v 1.18 2000/09/24 12:32:31 jdolecek Exp $ */
/* $NetBSD: reboot.h,v 1.19 2001/07/01 02:56:20 gmcgarry Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1993, 1994
@ -56,6 +56,7 @@
#define RB_MINIROOT 0x200 /* mini-root present in memory at boot time */
#define RB_STRING 0x400 /* use provided bootstr */
#define RB_POWERDOWN (RB_HALT|0x800) /* turn power off (or at least halt) */
#define RB_USERCONF 0x1000 /* change configured devices */
/*
* Extra autoboot flags (passed by boot prog to kernel). See also

41
sys/sys/userconf.h Normal file
View File

@ -0,0 +1,41 @@
/* $NetBSD: userconf.h,v 1.1 2001/07/01 02:56:21 gmcgarry Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_USERCONF_H_
#define _SYS_USERCON_H_
void user_config __P((void));
#endif