summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMats O Jansson <maja@cvs.openbsd.org>1996-06-23 19:34:31 +0000
committerMats O Jansson <maja@cvs.openbsd.org>1996-06-23 19:34:31 +0000
commit0054b6760baba431af85a223b4b5e8fd0ea83a11 (patch)
treea461bafc9b092794b5d855da239d0d9a884f9cd3 /sys/kern
parent8cd996a3c97256f705e7445d234ffd4fd85fd0db (diff)
Added support for user modifiable kernel at boot (-c) /maja
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/subr_autoconf.c8
-rw-r--r--sys/kern/subr_userconf.c790
2 files changed, 797 insertions, 1 deletions
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c
index 7eb5217034b..3ba36c02b75 100644
--- a/sys/kern/subr_autoconf.c
+++ b/sys/kern/subr_autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_autoconf.c,v 1.7 1996/06/18 09:43:44 deraadt Exp $ */
+/* $OpenBSD: subr_autoconf.c,v 1.8 1996/06/23 19:34:30 maja Exp $ */
/* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */
/*
@@ -179,6 +179,9 @@ config_search(fn, parent, aux)
*/
if (cf->cf_fstate == FSTATE_FOUND)
continue;
+ if (cf->cf_fstate == FSTATE_DNOTFOUND |
+ cf->cf_fstate == FSTATE_DSTAR)
+ continue;
for (p = cf->cf_parents; *p >= 0; p++)
if (parent->dv_cfdata == &(t->tab)[*p])
mapply(&m, cf);
@@ -215,6 +218,9 @@ config_scan(fn, parent)
*/
if (cf->cf_fstate == FSTATE_FOUND)
continue;
+ if (cf->cf_fstate == FSTATE_DNOTFOUND |
+ cf->cf_fstate == FSTATE_DSTAR)
+ continue;
for (p = cf->cf_parents; *p >= 0; p++)
if (parent->dv_cfdata == &(t->tab)[*p]) {
if (indirect)
diff --git a/sys/kern/subr_userconf.c b/sys/kern/subr_userconf.c
new file mode 100644
index 00000000000..3559e9b8297
--- /dev/null
+++ b/sys/kern/subr_userconf.c
@@ -0,0 +1,790 @@
+/* $OpenBSD: subr_userconf.c,v 1.1 1996/06/23 19:34:30 maja 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.
+ */
+
+#ifdef BOOT_CONFIG
+#include <sys/param.h>
+#include <sys/device.h>
+
+extern char *locnames[];
+extern short locnamp[];
+extern struct cfdata cfdata[];
+extern cfroots[];
+
+int userconf_base = 16;
+int userconf_maxdev = -1;
+int userconf_maxlocnames = -1;
+int userconf_cnt = -1;
+int userconf_lines = 12;
+char userconf_cmdbuf[40];
+
+#define UC_CHANGE 'c'
+#define UC_DISABLE 'd'
+#define UC_ENABLE 'e'
+#define UC_FIND 'f'
+
+char *userconf_cmds[] = {
+/* "add", "a", */
+ "base", "b",
+ "change", "c",
+ "disable", "d",
+ "enable", "e",
+ "exit", "q",
+ "find", "f",
+ "help", "h",
+ "list", "l",
+ "lines", "L",
+ "quit", "q",
+ "show", "s",
+ "?", "h",
+ "", "",
+};
+
+userconf_init()
+{
+ int i = 0;
+ struct cfdata *cd;
+ short *p;
+ int *l;
+ int ln;
+
+ while(cfdata[i].cf_attach != 0) {
+
+ userconf_maxdev = i;
+
+ cd = &cfdata[i];
+ ln=cd->cf_locnames;
+ while (locnamp[ln] != -1) {
+ if (locnamp[ln] > userconf_maxlocnames) {
+ userconf_maxlocnames = locnamp[ln];
+ };
+ ln++;
+ }
+ i++;
+ }
+}
+
+userconf_more()
+{
+ char c;
+
+ if (userconf_cnt != -1) {
+ if (userconf_cnt == userconf_lines) {
+ printf("--- more ---");
+ c = cngetc();
+ userconf_cnt = 0;
+ printf("\r");
+ }
+ userconf_cnt++;
+ }
+}
+
+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;
+ }
+ }
+}
+
+userconf_pdevnam(dev)
+short dev;
+{
+ struct cfdata *cd;
+
+ cd = &cfdata[dev];
+ printf(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;
+ }
+}
+
+userconf_pdev(devno)
+short devno;
+{
+ struct cfdata *cd;
+ short *p;
+ int *l;
+ int ln;
+ char c;
+
+ if (devno > userconf_maxdev) {
+ printf("Unknown devno (max is %d)\n",userconf_maxdev);
+ return;
+ }
+
+
+ userconf_more();
+
+ cd = &cfdata[devno];
+
+ printf("%3d",devno);
+ switch(cd->cf_fstate) {
+ case FSTATE_NOTFOUND:
+ case FSTATE_FOUND:
+ case FSTATE_STAR:
+ printf(" E ");
+ break;
+ case FSTATE_DNOTFOUND:
+ case FSTATE_DSTAR:
+ printf(" D ");
+ break;
+ default:
+ printf(" ? ");
+ break;
+ }
+
+ 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='|';
+ };
+ l=cd->cf_loc;
+ ln=cd->cf_locnames;
+ while (locnamp[ln] != -1) {
+ printf(" %s",locnames[locnamp[ln]]);
+ ln++;
+ userconf_pnum(*l++);
+ }
+ printf("\n");
+
+}
+
+int
+userconf_number(c,val)
+char *c;
+int *val;
+{
+ u_int number=0;
+ int base=10;
+ int neg=1;
+
+ if (*c == '0') base = 8;
+ while (*c != ' ' & *c != '\t' & *c != '\n' & *c != '\000') {
+ if (*c == '-') {
+ neg = neg*-1;
+ }
+ else if (*c >= '0' & *c <= '9') {
+ number=number*base + (*c - '0');
+ }
+ else if (*c == '8' | *c == '9') {
+ if (base == 8) return(-1);
+ number=number*base + (*c - '0');
+ }
+ else if (*c >= 'A' & *c <= 'F') {
+ if (base < 16) return(-1);
+ number=number*base + (*c - 'A' + 10);
+ }
+ else if (*c >= 'a' & *c <= 'f') {
+ if (base < 16) return(-1);
+ number=number*base + (*c - 'a' + 10);
+ }
+ else if (*c == 'x' | *c == 'X') {
+ base=16;
+ } else {
+ return(-1);
+ }
+ c++;
+ }
+
+ *val=(int)(number*neg);
+ 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 == '\000') {
+ *len = l;
+ *unit = u;
+ *state = s;
+ return(0);
+ }
+
+ return(-1);
+}
+
+userconf_modify(item, val)
+char *item;
+int *val;
+{
+ int ok = 0, a;
+ char *c;
+ int i;
+
+ while(!ok) {
+ printf("%s [",item);
+ userconf_pnum(*val);
+ printf("] ? ");
+
+ i = getsn(userconf_cmdbuf,sizeof(userconf_cmdbuf));
+
+ c = userconf_cmdbuf;
+ while (*c == ' ' | *c == '\t' | *c == '\n') c++;
+
+ if (*c != '\000') {
+ if (userconf_number(c,&a) == 0) {
+ *val = a;
+ ok = 1;
+ } else {
+ printf("Unknown argument\n");
+ }
+ } else {
+ ok = 1;
+ }
+ }
+}
+
+userconf_change(devno)
+int devno;
+{
+ struct cfdata *cd;
+ char c = '\000';
+ int *l;
+ int ln;
+
+ 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') {
+
+ cd = &cfdata[devno];
+ l=cd->cf_loc;
+ ln=cd->cf_locnames;
+
+ while (locnamp[ln] != -1) {
+ userconf_modify(locnames[locnamp[ln]],
+ l);
+ ln++;
+ l++;
+ }
+
+ printf("%3d ",devno);
+ userconf_pdevnam(devno);
+ printf(" changed\n");
+ userconf_pdev(devno);
+
+ }
+
+ } else {
+ printf("Unknown devno (max is %d)\n",userconf_maxdev);
+ }
+
+}
+
+userconf_disable(devno)
+int devno;
+{
+
+ 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:
+ printf("Already disabled\n");
+ break;
+ default:
+ printf("Error unknown state\n");
+ break;
+ }
+
+ printf("%3d ",devno);
+ userconf_pdevnam(devno);
+ printf(" disabled\n");
+
+ } else {
+ printf("Unknown devno (max is %d)\n",userconf_maxdev);
+ }
+
+}
+
+userconf_enable(devno)
+int devno;
+{
+
+ 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:
+ printf("Already enabled\n");
+ break;
+ default:
+ printf("Error unknown state\n");
+ break;
+ }
+
+ printf("%3d ",devno);
+ userconf_pdevnam(devno);
+ printf(" enabled\n");
+
+ } else {
+ printf("Unknown devno (max is %d)\n",userconf_maxdev);
+ }
+
+}
+
+userconf_help()
+{
+ int j = 0,k;
+
+ printf("command args description\n");
+ while(*userconf_cmds[j] != '\000') {
+ 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 %s","change");
+ break;
+ case 'd':
+ printf("devno|dev %s","disable");
+ break;
+ case 'e':
+ printf("devno|dev %s","enable");
+ break;
+ case 'f':
+ printf("devno|dev %s","find");
+ break;
+ case 'h':
+ printf(" %s","this message");
+ break;
+ case 'l':
+ printf(" %s","list configuration");
+ break;
+ case 'q':
+ printf(" %s","leave UKC");
+ break;
+ case 's':
+ printf("[attr [val]] show known attributes");
+ break;
+ default:
+ printf(" %s","don't know");
+ break;
+ }
+ printf("\n");
+ j++; j++;
+ }
+
+}
+
+userconf_list(count)
+int count;
+{
+ int i = 0;
+
+ userconf_cnt = 0;
+
+ while(cfdata[i].cf_attach != 0) {
+ userconf_pdev(i++);
+ };
+
+ userconf_cnt = -1;
+
+}
+
+userconf_show()
+{
+ int i = 0;
+
+ userconf_cnt = 0;
+
+ while(i <= userconf_maxlocnames) {
+ userconf_more();
+ printf("%s\n",locnames[i++]);
+ }
+
+ userconf_cnt = -1;
+}
+
+userconf_show_attr_val(attr, val)
+short attr;
+int *val;
+{
+ struct cfdata *cd;
+ int *l;
+ int ln;
+ int i = 0;
+
+ userconf_cnt = 0;
+
+ while(i <= userconf_maxdev) {
+ cd = &cfdata[i];
+ l=cd->cf_loc;
+ ln=cd->cf_locnames;
+ while (locnamp[ln] != -1) {
+ if (locnamp[ln] == attr) {
+ if (val == NULL) {
+ userconf_pdev(i);
+ } else {
+ if (*val == *l) {
+ userconf_pdev(i);
+ }
+ }
+ }
+ ln++;
+ l++;
+ }
+ i++;
+ }
+
+ userconf_cnt = -1;
+
+}
+
+userconf_show_attr(cmd)
+char *cmd;
+{
+ char *c;
+ short attr = -1, i = 0, l = 0;
+ int a;
+
+ c = cmd;
+ while (*c != ' ' & *c != '\t' & *c != '\n' & *c != '\000') {
+ c++; l++;
+ }
+ while (*c == ' ' | *c == '\t' | *c == '\n') {
+ c++;
+ }
+
+ while(i <= userconf_maxlocnames) {
+ if (strlen(locnames[i]) == l) {
+ if (strncasecmp(cmd,locnames[i],l) == 0) {
+ attr = i;
+ }
+ }
+ i++;
+ }
+
+ if (attr == -1) {
+ printf("Unknown attribute\n");
+ return;
+ }
+
+ if (*c == '\000') {
+ userconf_show_attr_val(attr,NULL);
+ } else {
+ if (userconf_number(c,&a) == 0) {
+ userconf_show_attr_val(attr,&a);
+ } else {
+ printf("Unknown argument\n");
+ }
+ }
+}
+
+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) {
+ if (strncasecmp(dev,cfdata[i].cf_driver->cd_name,
+ len) == 0 &
+ (state == FSTATE_FOUND |
+ ((cfdata[i].cf_unit == unit |
+ cfdata[i].cf_fstate == FSTATE_STAR) &
+ cfdata[i].cf_fstate == state))) {
+ 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;
+ }
+
+}
+
+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 != '\000') {
+ c++; i++;
+ }
+
+ k = -1;
+ while(*userconf_cmds[j] != '\000') {
+ if (strlen(userconf_cmds[j]) == i) {
+ if (strncasecmp(v,userconf_cmds[j],i) == 0) {
+ k = j;
+ }
+ }
+ j++; j++;
+ }
+
+ 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 == '\000') {
+ printf("Argument expected\n");
+ } else if (userconf_number(c,&a) == 0) {
+ userconf_lines = a;
+ } else {
+ printf("Unknown argument\n");
+ }
+ break;
+ case 'b':
+ if (*c == '\000') {
+ 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 == '\000') {
+ 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 == '\000') {
+ printf("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 == '\000') {
+ printf("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 == '\000') {
+ 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 == '\000') {
+ userconf_list();
+ } else {
+ printf("Unknown argument\n");
+ }
+ break;
+ case 'q':
+ return(-1);
+ break;
+ case 's':
+ if (*c == '\000') {
+ userconf_show();
+ } else {
+ userconf_show_attr(c);
+ }
+ break;
+ default:
+ printf("Unknown command\n");
+ break;
+ }
+ }
+ return(0);
+}
+
+user_config()
+{
+ static char prompt[] = "UKC> ";
+ int i;
+
+ userconf_init();
+ printf("User Kernel Config\n");
+
+ printf(prompt);
+ while (i = getsn(userconf_cmdbuf,sizeof(userconf_cmdbuf)) != 0) {
+ if (userconf_parse(&userconf_cmdbuf)) break;
+ printf(prompt);
+ }
+ printf("Continuing...\n");
+}
+#else BOOT_CONFIG
+user_config()
+{
+ printf("User Kernel Config isn't supported in this kernel\n");
+}
+#endif