From 349a158056c65e74ca63c0dfb2a929e06a14023a Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Thu, 13 Oct 2011 12:27:30 +0000 Subject: [PATCH] base system hooks for pkgsrc drivers . rc script and service know to look in /usr/pkg/.. for extra binaries and conf files . service split into parsing config and doing RS request so that a new utility (printconfig) can just print the config in machine-parseable format for netconf integration . converted all base system eth drivers/netconf --- commands/netconf/netconf.sh | 103 ++- commands/service/Makefile | 7 +- commands/service/config.h | 7 + commands/service/parse.c | 1137 ++++++++++++++++++++++++++++++ commands/service/parse.h | 23 + commands/service/print.c | 97 +++ commands/service/proto.h | 3 + commands/service/service.c | 1134 ++--------------------------- commands/service/util.c | 17 + common/include/minix/minlib.h | 2 + drivers/atl2/Makefile | 4 + drivers/atl2/atl2.conf | 15 + drivers/dec21140A/Makefile | 4 + drivers/dec21140A/dec21140A.conf | 17 + drivers/e1000/Makefile | 4 + drivers/e1000/e1000.conf | 20 + drivers/fxp/Makefile | 4 + drivers/fxp/fxp.conf | 22 + drivers/lance/Makefile | 4 + drivers/lance/lance.conf | 14 + drivers/rtl8139/Makefile | 4 + drivers/rtl8139/rtl8139.conf | 32 + drivers/rtl8169/Makefile | 4 + drivers/rtl8169/rtl8169.conf | 25 + etc/Makefile | 3 + etc/minix.rc.conf | 11 + etc/mtree/minix.tree | 1 + etc/rc.conf | 4 + etc/system.conf | 127 ---- etc/usr/rc | 22 +- include/paths.h | 1 + nbsd_include/minix/paths.h | 1 + 32 files changed, 1617 insertions(+), 1256 deletions(-) create mode 100644 commands/service/config.h create mode 100644 commands/service/parse.c create mode 100644 commands/service/parse.h create mode 100644 commands/service/print.c create mode 100644 commands/service/proto.h create mode 100644 commands/service/util.c create mode 100644 drivers/atl2/atl2.conf create mode 100644 drivers/dec21140A/dec21140A.conf create mode 100644 drivers/e1000/e1000.conf create mode 100644 drivers/fxp/fxp.conf create mode 100644 drivers/lance/lance.conf create mode 100644 drivers/rtl8139/rtl8139.conf create mode 100644 drivers/rtl8169/rtl8169.conf create mode 100644 etc/minix.rc.conf diff --git a/commands/netconf/netconf.sh b/commands/netconf/netconf.sh index 8d29b31f1..ca51df4a5 100644 --- a/commands/netconf/netconf.sh +++ b/commands/netconf/netconf.sh @@ -5,12 +5,17 @@ # Changes: # +# Get system config +. /etc/rc.conf + LOCALRC=/usr/etc/rc.local INETCONF=/etc/inet.conf RCNET=/etc/rc.net HOSTS=/etc/hosts HOSTNAME=/etc/hostname.file USRKBFILE=/.usrkb +LSPCI=/tmp/lspci.$$ +DEVICES=/tmp/devices.$$ step1="" step2="" @@ -81,7 +86,7 @@ card() shift 2 while [ $# -gt 0 ] do - lspci | grep > /dev/null "^$1" && card_avail=1 + cat $LSPCI | grep > /dev/null "^$1" && card_avail=1 shift done if [ $card_avail -gt 0 ] @@ -94,29 +99,23 @@ card() printf "%2d. %s %s\n" "$card_number" "$card_mark" "$card_name" } +first_pcicard=4 + cards() { card 0 "No Ethernet card (no networking)" - card 1 "Intel Pro/100" "8086:103D" "8086:1064" "8086:1229" "8086:2449" \ - "8086:1031" "8086:1032" - card 2 "3Com 501 or 3Com 509 based card" - card 3 "Realtek 8139 based card (also emulated by KVM)" \ - "10EC:8139" "02AC:1012" "1065:8139" "1113:1211" "1186:1300" \ - "1186:1340" "11DB:1234" "1259:A117" "1259:A11E" "126C:1211" \ - "13D1:AB06" "1432:9130" "14EA:AB06" "14EA:AB07" "1500:1360" \ - "1743:8139" "4033:1360" - card 4 "Realtek 8169 based card" \ - "10EC:8129" "10EC:8167" "10EC:8169" "1186:4300" "1259:C107" \ - "1385:8169" "16EC:0116" "1737:1032" "10EC:8168" - card 5 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029" - card 6 "NE2000, 3com 503 or WD based card (also emulated by Bochs)" - card 7 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000" - card 8 "Intel PRO/1000 Gigabit" \ - "8086:100E" "8086:107C" "8086:10CD" "8086:10D3" "8086:10DE" - - card 9 "Attansic/Atheros L2 FastEthernet" "1969:2048" - card 10 "DEC Tulip 21140A in VirtualPC" "1011:0009" - card 11 "Different Ethernet card (no networking)" + card 1 "3Com 501 or 3Com 509 based card" + card 2 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029" + card 3 "NE2000, 3com 503 or WD based card (also emulated by Bochs)" + n=$first_pcicard + for pcicard in $pci_list + do var=\$pci_descr$pcicard; descr="`eval echo $var`" + var=\$pci_pcilist$pcicard; pcilist="`eval echo $var`" + card $n "$descr" $pcilist + n="`expr $n + 1`" + done + + card $first_after_pci "Different Ethernet card (no networking)" } warn() @@ -124,6 +123,35 @@ warn() echo -e "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b ! $1" } +config_pci_cards() { + rm -f $DEVICES + + n=0 + + # Collect configs from network devices + for dir in $SYSTEM_CONF_DIRS + do for f in $dir/$SYSTEM_CONF_SUBDIR/* + do if [ -f $f ] + then printconfig $f | grep 'type net.*pci device' + fi + done + done >$DEVICES + while read devline + do pcilist="`echo $devline | sed 's/.*pci device //' | sed 's/,.*//'`" + descr="`echo $devline | sed 's/.*,descr //' | sed 's/,.*//'`" + label="`echo $devline | sed 's/.*service //' | sed 's/,.*//'`" + pci_list="$pci_list $n" + eval "pci_pcilist$n=\"$pcilist\"" + eval "pci_descr$n=\"$descr\"" + eval "pci_label$n=\"$label\"" + n="`expr $n + 1`" + done <$DEVICES + + first_after_pci=`expr $first_pcicard + $n` + + rm -f $DEVICES +} + do_step1() { eth_default=0 @@ -146,26 +174,28 @@ do_step1() drv_params() { + # If this is a known pci device, we only have to set + # the driver. + if [ $1 -ge $first_pcicard -a $1 -lt $first_after_pci ] + then pcicard="`expr $1 - $first_pcicard`" + var=\$pci_label$pcicard; driver="`eval echo $var`" + return + fi + + # Other possibilities. case "$1" in 0) driver=psip0; ;; - 1) driver=fxp; ;; - 2) driver=dpeth; driverargs="#dpeth_arg='DPETH0=port:irq:memory'"; + 1) driver=dpeth; driverargs="#dpeth_arg='DPETH0=port:irq:memory'"; test "$v" = 1 && echo "" test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration." ;; - 4) driver=rtl8169; ;; - 3) driver=rtl8139; ;; - 5) driver=dp8390; driverargs="dp8390_arg='DPETH0=pci'"; ;; - 6) driver=dp8390; driverargs="dp8390_arg='DPETH0=240:9'"; + 2) driver=dp8390; driverargs="dp8390_arg='DPETH0=pci'"; ;; + 3) driver=dp8390; driverargs="dp8390_arg='DPETH0=240:9'"; test "$v" = 1 && echo "" test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration." test "$v" = 1 && echo " chose option 4, the defaults for emulation by Bochs have been set." ;; - 7) driver="lance"; ;; - 8) driver="e1000"; ;; - 9) driver="atl2"; ;; - 10) driver="dec21140A"; ;; - 11) driver="psip0"; ;; + $first_after_pci) driver="psip0"; ;; *) warn "choose a number" esac } @@ -253,6 +283,9 @@ do_step2() fi } +# Find pci cards we know about +config_pci_cards + # Parse options while getopts ":qe:p:aH:i:n:g:d:s:hc" arg; do case "$arg" in @@ -279,6 +312,9 @@ while getopts ":qe:p:aH:i:n:g:d:s:hc" arg; do esac done +# Run lspci once to a temp file +lspci >$LSPCI || exit + # Verify parameter count if [ "$dhcp" != "yes" ] ; then if [ $manual_opts -gt 0 ] ; then @@ -329,6 +365,9 @@ else fi echo "$driverargs" > $LOCALRC +# Remove temporary lspci output +rm -f $LSPCI + if [ -n "$manual" ] then # Backup config file if it exists and we're not running from CD diff --git a/commands/service/Makefile b/commands/service/Makefile index 3669beeb8..77557867a 100644 --- a/commands/service/Makefile +++ b/commands/service/Makefile @@ -1,8 +1,11 @@ # Makefile for service -PROG= service +PROGS= service printconfig +SRCS.service=service.c parse.c util.c +SRCS.printconfig=print.c parse.c util.c BINDIR= /bin -MAN= +MAN.service= +MAN.printconfig= CPPFLAGS+= -I${MINIXSRCDIR} diff --git a/commands/service/config.h b/commands/service/config.h new file mode 100644 index 000000000..25aa27081 --- /dev/null +++ b/commands/service/config.h @@ -0,0 +1,7 @@ + +struct rs_config { + struct rs_start rs_start; /* RS parameters */ + const char *descr; /* human-readable description, if specified */ + char *type; /* service type, if specified */ +}; + diff --git a/commands/service/parse.c b/commands/service/parse.c new file mode 100644 index 000000000..20096e0e0 --- /dev/null +++ b/commands/service/parse.c @@ -0,0 +1,1137 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "kernel/proc.h" + +#include "config.h" +#include "proto.h" + +PRIVATE int class_recurs; /* Nesting level of class statements */ +#define MAX_CLASS_RECURS 100 /* Max nesting level for classes */ + +#include "parse.h" + +#define SERVICE_LOGIN "service" /* passwd file entry for services */ + +FORWARD void do_service(config_t *cpe, config_t *config, struct rs_config *); + +PRIVATE void do_class(config_t *cpe, config_t *config, struct rs_config *rs_config) +{ + config_t *cp, *cp1; + + if (class_recurs > MAX_CLASS_RECURS) + { + fatal( + "do_class: nesting level too high for class '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + class_recurs++; + + /* Process classes */ + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_class: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_uid: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + /* Find entry for the class */ + for (cp= config; cp; cp= cp->next) + { + if (!(cp->flags & CFG_SUBLIST)) + { + fatal("do_class: expected list at %s:%d", + cp->file, cp->line); + } + cp1= cp->list; + if ((cp1->flags & CFG_STRING) || + (cp1->flags & CFG_SUBLIST)) + { + fatal("do_class: expected word at %s:%d", + cp1->file, cp1->line); + } + + /* At this place we expect the word KW_SERVICE */ + if (strcmp(cp1->word, KW_SERVICE) != 0) + fatal("do_class: exected word '%S' at %s:%d", + KW_SERVICE, cp1->file, cp1->line); + + cp1= cp1->next; + if ((cp1->flags & CFG_STRING) || + (cp1->flags & CFG_SUBLIST)) + { + fatal("do_class: expected word at %s:%d", + cp1->file, cp1->line); + } + + /* At this place we expect the name of the service */ + if (strcmp(cp1->word, cpe->word) == 0) + break; + } + if (cp == NULL) + { + fatal( + "do_class: no entry found for class '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + do_service(cp1->next, config, rs_config); + } + + class_recurs--; +} + +PRIVATE void do_uid(config_t *cpe, struct rs_start *rs_start) +{ + uid_t uid; + struct passwd *pw; + char *check; + + /* Process a uid */ + if (cpe->next != NULL) + { + fatal("do_uid: just one uid/login expected at %s:%d", + cpe->file, cpe->line); + } + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_uid: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_uid: unexpected string at %s:%d", + cpe->file, cpe->line); + } + pw= getpwnam(cpe->word); + if (pw != NULL) + uid= pw->pw_uid; + else + { + uid= strtol(cpe->word, &check, 0); + if (check[0] != '\0') + { + fatal("do_uid: bad uid/login '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + } + + rs_start->rss_uid= uid; +} + +PRIVATE void do_sigmgr(config_t *cpe, struct rs_start *rs_start) +{ + endpoint_t sigmgr_ep; + int r; + + /* Process a signal manager value */ + if (cpe->next != NULL) + { + fatal("do_sigmgr: just one sigmgr value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_sigmgr: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_sigmgr: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + if(!strcmp(cpe->word, "SELF")) { + sigmgr_ep = SELF; + } + else { + if((r = minix_rs_lookup(cpe->word, &sigmgr_ep))) { + fatal("do_sigmgr: unknown sigmgr %s at %s:%d", + cpe->word, cpe->file, cpe->line); + } + } + + rs_start->rss_sigmgr= sigmgr_ep; +} + +PRIVATE void do_type(config_t *cpe, struct rs_config *rs_config) +{ + if (cpe->next != NULL) + { + fatal("do_type: just one type value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_type: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if ((cpe->flags & CFG_STRING)) + { + fatal("do_type: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + if(rs_config->type) + fatal("do_type: another type at %s:%d", + cpe->file, cpe->line); + + if(!strcmp(cpe->word, KW_NET)) + rs_config->type = KW_NET; + else + fatal("do_type: odd type at %s:%d", + cpe->file, cpe->line); +} + +PRIVATE void do_descr(config_t *cpe, struct rs_config *rs_config) +{ + if (cpe->next != NULL) + { + fatal("do_descr: just one description expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_descr: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (!(cpe->flags & CFG_STRING)) + { + fatal("do_descr: expected string at %s:%d", + cpe->file, cpe->line); + } + + if(rs_config->descr) + fatal("do_descr: another descr at %s:%d", + cpe->file, cpe->line); + rs_config->descr = cpe->word; +} + +PRIVATE void do_scheduler(config_t *cpe, struct rs_start *rs_start) +{ + endpoint_t scheduler_ep; + int r; + + /* Process a scheduler value */ + if (cpe->next != NULL) + { + fatal("do_scheduler: just one scheduler value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_scheduler: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_scheduler: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + if(!strcmp(cpe->word, "KERNEL")) { + scheduler_ep = KERNEL; + } + else { + if((r = minix_rs_lookup(cpe->word, &scheduler_ep))) { + fatal("do_scheduler: unknown scheduler %s at %s:%d", + cpe->word, cpe->file, cpe->line); + } + } + + rs_start->rss_scheduler= scheduler_ep; +} + +PRIVATE void do_priority(config_t *cpe, struct rs_start *rs_start) +{ + int priority_val; + char *check; + + /* Process a priority value */ + if (cpe->next != NULL) + { + fatal("do_priority: just one priority value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_priority: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_priority: unexpected string at %s:%d", + cpe->file, cpe->line); + } + priority_val= strtol(cpe->word, &check, 0); + if (check[0] != '\0') + { + fatal("do_priority: bad priority value '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + + if (priority_val < 0 || priority_val >= NR_SCHED_QUEUES) + { + fatal("do_priority: priority %d out of range at %s:%d", + priority_val, cpe->file, cpe->line); + } + rs_start->rss_priority= priority_val; +} + +PRIVATE void do_quantum(config_t *cpe, struct rs_start *rs_start) +{ + int quantum_val; + char *check; + + /* Process a quantum value */ + if (cpe->next != NULL) + { + fatal("do_quantum: just one quantum value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_quantum: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_quantum: unexpected string at %s:%d", + cpe->file, cpe->line); + } + quantum_val= strtol(cpe->word, &check, 0); + if (check[0] != '\0') + { + fatal("do_quantum: bad quantum value '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + + if (quantum_val <= 0) + { + fatal("do_quantum: quantum %d out of range at %s:%d", + quantum_val, cpe->file, cpe->line); + } + rs_start->rss_quantum= quantum_val; +} + +PRIVATE void do_cpu(config_t *cpe, struct rs_start *rs_start) +{ + int cpu; + char *check; + + /* Process a quantum value */ + if (cpe->next != NULL) + { + fatal("do_cpu: just one value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_cpu: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_cpu: unexpected string at %s:%d", + cpe->file, cpe->line); + } + cpu= strtol(cpe->word, &check, 0); + if (check[0] != '\0') + { + fatal("do_cpu: bad value '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + + if (cpu < 0) + { + fatal("do_cpu: %d out of range at %s:%d", + cpu, cpe->file, cpe->line); + } + rs_start->rss_cpu= cpu; +} + +PRIVATE void do_irq(config_t *cpe, struct rs_start *rs_start) +{ + int irq; + int first; + char *check; + + /* Process a list of IRQs */ + first = TRUE; + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_irq: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_irq: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + /* No IRQ allowed? (default) */ + if(!strcmp(cpe->word, KW_NONE)) { + if(!first || cpe->next) { + fatal("do_irq: %s keyword not allowed in list", + KW_NONE); + } + break; + } + + /* All IRQs are allowed? */ + if(!strcmp(cpe->word, KW_ALL)) { + if(!first || cpe->next) { + fatal("do_irq: %s keyword not allowed in list", + KW_ALL); + } + rs_start->rss_nr_irq = RSS_IO_ALL; + break; + } + + /* Set single IRQs as specified in the configuration. */ + irq= strtoul(cpe->word, &check, 0); + if (check[0] != '\0') + { + fatal("do_irq: bad irq '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + if (rs_start->rss_nr_irq >= RSS_NR_IRQ) + fatal("do_irq: too many IRQs (max %d)", RSS_NR_IRQ); + rs_start->rss_irq[rs_start->rss_nr_irq]= irq; + rs_start->rss_nr_irq++; + first = FALSE; + } +} + +PRIVATE void do_io(config_t *cpe, struct rs_start *rs_start) +{ + unsigned base, len; + int first; + char *check; + + /* Process a list of I/O ranges */ + first = TRUE; + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_io: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_io: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + /* No range allowed? (default) */ + if(!strcmp(cpe->word, KW_NONE)) { + if(!first || cpe->next) { + fatal("do_io: %s keyword not allowed in list", + KW_NONE); + } + break; + } + + /* All ranges are allowed? */ + if(!strcmp(cpe->word, KW_ALL)) { + if(!first || cpe->next) { + fatal("do_io: %s keyword not allowed in list", + KW_ALL); + } + rs_start->rss_nr_io = RSS_IO_ALL; + break; + } + + /* Set single ranges as specified in the configuration. */ + base= strtoul(cpe->word, &check, 0x10); + len= 1; + if (check[0] == ':') + { + len= strtoul(check+1, &check, 0x10); + } + if (check[0] != '\0') + { + fatal("do_io: bad I/O range '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + + if (rs_start->rss_nr_io >= RSS_NR_IO) + fatal("do_io: too many I/O ranges (max %d)", RSS_NR_IO); + rs_start->rss_io[rs_start->rss_nr_io].base= base; + rs_start->rss_io[rs_start->rss_nr_io].len= len; + rs_start->rss_nr_io++; + first = FALSE; + } +} + +PRIVATE void do_pci_device(config_t *cpe, struct rs_start *rs_start) +{ + u16_t vid, did; + char *check, *check2; + + /* Process a list of PCI device IDs */ + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_pci_device: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_pci_device: unexpected string at %s:%d", + cpe->file, cpe->line); + } + vid= strtoul(cpe->word, &check, 0x10); + if (check[0] == '/') + did= strtoul(check+1, &check2, 0x10); + if (check[0] != '/' || check2[0] != '\0') + { + fatal("do_pci_device: bad ID '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + if (rs_start->rss_nr_pci_id >= RS_NR_PCI_DEVICE) + { + fatal("do_pci_device: too many device IDs (max %d)", + RS_NR_PCI_DEVICE); + } + rs_start->rss_pci_id[rs_start->rss_nr_pci_id].vid= vid; + rs_start->rss_pci_id[rs_start->rss_nr_pci_id].did= did; + rs_start->rss_nr_pci_id++; + } +} + +PRIVATE void do_pci_class(config_t *cpe, struct rs_start *rs_start) +{ + u8_t baseclass, subclass, interface; + u32_t class_id, mask; + char *check; + + /* Process a list of PCI device class IDs */ + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_pci_device: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_pci_device: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + baseclass= strtoul(cpe->word, &check, 0x10); + subclass= 0; + interface= 0; + mask= 0xff0000; + if (check[0] == '/') + { + subclass= strtoul(check+1, &check, 0x10); + mask= 0xffff00; + if (check[0] == '/') + { + interface= strtoul(check+1, &check, 0x10); + mask= 0xffffff; + } + } + + if (check[0] != '\0') + { + fatal("do_pci_class: bad class ID '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + class_id= (baseclass << 16) | (subclass << 8) | interface; + if (rs_start->rss_nr_pci_class >= RS_NR_PCI_CLASS) + { + fatal("do_pci_class: too many class IDs (max %d)", + RS_NR_PCI_CLASS); + } + rs_start->rss_pci_class[rs_start->rss_nr_pci_class].pciclass= + class_id; + rs_start->rss_pci_class[rs_start->rss_nr_pci_class].mask= mask; + rs_start->rss_nr_pci_class++; + } +} + +PRIVATE void do_pci(config_t *cpe, struct rs_start *rs_start) +{ + if (cpe == NULL) + return; /* Empty PCI statement */ + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_pci: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_pci: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + if (strcmp(cpe->word, KW_DEVICE) == 0) + { + do_pci_device(cpe->next, rs_start); + return; + } + if (strcmp(cpe->word, KW_CLASS) == 0) + { + do_pci_class(cpe->next, rs_start); + return; + } + fatal("do_pci: unexpected word '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); +} + +PRIVATE void do_ipc(config_t *cpe, struct rs_start *rs_start) +{ + char *list; + const char *word; + char *word_all = RSS_IPC_ALL; + char *word_all_sys = RSS_IPC_ALL_SYS; + size_t listsize, wordlen; + int first; + + list= NULL; + listsize= 1; + list= malloc(listsize); + if (list == NULL) + fatal("do_ipc: unable to malloc %d bytes", listsize); + list[0]= '\0'; + + /* Process a list of process names that are allowed to be + * contacted + */ + first = TRUE; + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_ipc: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_ipc: unexpected string at %s:%d", + cpe->file, cpe->line); + } + word = cpe->word; + + /* All (system) ipc targets are allowed? */ + if(!strcmp(word, KW_ALL) || !strcmp(word, KW_ALL_SYS)) { + if(!first || cpe->next) { + fatal("do_ipc: %s keyword not allowed in list", + word); + } + word = !strcmp(word, KW_ALL) ? word_all : word_all_sys; + } + + wordlen= strlen(word); + + listsize += 1 + wordlen; + list= realloc(list, listsize); + if (list == NULL) + { + fatal("do_ipc: unable to realloc %d bytes", + listsize); + } + strcat(list, " "); + strcat(list, word); + first = FALSE; + } +#if 0 + printf("do_ipc: got list '%s'\n", list); +#endif + + if (rs_start->rss_ipc) + fatal("do_ipc: req_ipc is set"); + rs_start->rss_ipc = list+1; + rs_start->rss_ipclen= strlen(rs_start->rss_ipc); +} + + +struct +{ + char *label; + int call_nr; +} vm_table[] = +{ + { "EXIT", VM_EXIT }, + { "FORK", VM_FORK }, + { "BRK", VM_BRK }, + { "EXEC_NEWMEM", VM_EXEC_NEWMEM }, + { "PUSH_SIG", VM_PUSH_SIG }, + { "WILLEXIT", VM_WILLEXIT }, + { "ADDDMA", VM_ADDDMA }, + { "DELDMA", VM_DELDMA }, + { "GETDMA", VM_GETDMA }, + { "REMAP", VM_REMAP }, + { "SHM_UNMAP", VM_SHM_UNMAP }, + { "GETPHYS", VM_GETPHYS }, + { "GETREF", VM_GETREF }, + { "RS_SET_PRIV", VM_RS_SET_PRIV }, + { "QUERY_EXIT", VM_QUERY_EXIT }, + { "WATCH_EXIT", VM_WATCH_EXIT }, + { "NOTIFY_SIG", VM_NOTIFY_SIG }, + { "INFO", VM_INFO }, + { "RS_UPDATE", VM_RS_UPDATE }, + { "RS_MEMCTL", VM_RS_MEMCTL }, + { NULL, 0 }, +}; + +PRIVATE void do_vm(config_t *cpe, struct rs_start *rs_start) +{ + int i, first; + + first = TRUE; + for (; cpe; cpe = cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_vm: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_vm: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + /* Only basic calls allowed? (default). */ + if(!strcmp(cpe->word, KW_BASIC)) { + if(!first || cpe->next) { + fatal("do_vm: %s keyword not allowed in list", + KW_NONE); + } + break; + } + + /* No calls allowed? */ + if(!strcmp(cpe->word, KW_NONE)) { + if(!first || cpe->next) { + fatal("do_vm: %s keyword not allowed in list", + KW_NONE); + } + rs_start->rss_flags &= ~RSS_VM_BASIC_CALLS; + break; + } + + /* All calls are allowed? */ + if(!strcmp(cpe->word, KW_ALL)) { + if(!first || cpe->next) { + fatal("do_vm: %s keyword not allowed in list", + KW_ALL); + } + for (i = 0; i < NR_VM_CALLS; i++) + SET_BIT(rs_start->rss_vm, i); + break; + } + + /* Set single calls as specified in the configuration. */ + for (i = 0; vm_table[i].label != NULL; i++) + if (!strcmp(cpe->word, vm_table[i].label)) + break; + if (vm_table[i].label == NULL) + fatal("do_vm: unknown call '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + SET_BIT(rs_start->rss_vm, vm_table[i].call_nr - VM_RQ_BASE); + first = FALSE; + } +} + +struct +{ + char *label; + int call_nr; +} system_tab[]= +{ + { "PRIVCTL", SYS_PRIVCTL }, + { "TRACE", SYS_TRACE }, + { "KILL", SYS_KILL }, + { "UMAP", SYS_UMAP }, + { "VIRCOPY", SYS_VIRCOPY }, + { "PHYSCOPY", SYS_PHYSCOPY }, + { "UMAP_REMOTE", SYS_UMAP_REMOTE }, + { "IRQCTL", SYS_IRQCTL }, + { "INT86", SYS_INT86 }, + { "DEVIO", SYS_DEVIO }, + { "SDEVIO", SYS_SDEVIO }, + { "VDEVIO", SYS_VDEVIO }, + { "ABORT", SYS_ABORT }, + { "IOPENABLE", SYS_IOPENABLE }, + { "READBIOS", SYS_READBIOS }, + { "STIME", SYS_STIME }, + { "VMCTL", SYS_VMCTL }, + { NULL, 0 } +}; + +PRIVATE void do_system(config_t *cpe, struct rs_start *rs_start) +{ + int i, first; + + /* Process a list of 'system' calls that are allowed */ + first = TRUE; + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_system: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_system: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + /* Only basic calls allowed? (default). */ + if(!strcmp(cpe->word, KW_BASIC)) { + if(!first || cpe->next) { + fatal("do_system: %s keyword not allowed in list", + KW_NONE); + } + break; + } + + /* No calls allowed? */ + if(!strcmp(cpe->word, KW_NONE)) { + if(!first || cpe->next) { + fatal("do_system: %s keyword not allowed in list", + KW_NONE); + } + rs_start->rss_flags &= ~RSS_SYS_BASIC_CALLS; + break; + } + + /* All calls are allowed? */ + if(!strcmp(cpe->word, KW_ALL)) { + if(!first || cpe->next) { + fatal("do_system: %s keyword not allowed in list", + KW_ALL); + } + for (i = 0; i < NR_SYS_CALLS; i++) + SET_BIT(rs_start->rss_system, i); + break; + } + + /* Set single calls as specified in the configuration. */ + for (i = 0; system_tab[i].label != NULL; i++) + if (!strcmp(cpe->word, system_tab[i].label)) + break; + if (system_tab[i].label == NULL) + fatal("do_system: unknown call '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + SET_BIT(rs_start->rss_system, system_tab[i].call_nr - KERNEL_CALL); + first = FALSE; + } +} + +PRIVATE void do_control(config_t *cpe, struct rs_start *rs_start) +{ + int nr_control = 0; + + /* Process a list of 'control' labels. */ + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_control: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_control: unexpected string at %s:%d", + cpe->file, cpe->line); + } + if (nr_control >= RS_NR_CONTROL) + { + fatal( + "do_control: RS_NR_CONTROL is too small (%d needed)", + nr_control+1); + } + + rs_start->rss_control[nr_control].l_addr = (char*) cpe->word; + rs_start->rss_control[nr_control].l_len = strlen(cpe->word); + rs_start->rss_nr_control = ++nr_control; + } +} + +PRIVATE void do_service(config_t *cpe, config_t *config, struct rs_config *rs_config) +{ + struct rs_start *rs_start = &rs_config->rs_start; + config_t *cp; + + /* At this point we expect one sublist that contains the varios + * resource allocations + */ + if (!(cpe->flags & CFG_SUBLIST)) + { + fatal("do_service: expected list at %s:%d", + cpe->file, cpe->line); + } + if (cpe->next != NULL) + { + cpe= cpe->next; + fatal("do_service: expected end of list at %s:%d", + cpe->file, cpe->line); + } + cpe= cpe->list; + + /* Process the list */ + for (cp= cpe; cp; cp= cp->next) + { + if (!(cp->flags & CFG_SUBLIST)) + { + fatal("do_service: expected list at %s:%d", + cp->file, cp->line); + } + cpe= cp->list; + if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) + { + fatal("do_service: expected word at %s:%d", + cpe->file, cpe->line); + } + + if (strcmp(cpe->word, KW_CLASS) == 0) + { + do_class(cpe->next, config, rs_config); + continue; + } + if (strcmp(cpe->word, KW_UID) == 0) + { + do_uid(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_SIGMGR) == 0) + { + do_sigmgr(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_TYPE) == 0) + { + do_type(cpe->next, rs_config); + continue; + } + if (strcmp(cpe->word, KW_DESCR) == 0) + { + do_descr(cpe->next, rs_config); + continue; + } + if (strcmp(cpe->word, KW_SCHEDULER) == 0) + { + do_scheduler(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_PRIORITY) == 0) + { + do_priority(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_QUANTUM) == 0) + { + do_quantum(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_CPU) == 0) + { + do_cpu(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_IRQ) == 0) + { + do_irq(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_IO) == 0) + { + do_io(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_PCI) == 0) + { + do_pci(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_SYSTEM) == 0) + { + do_system(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_IPC) == 0) + { + do_ipc(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_VM) == 0) + { + do_vm(cpe->next, rs_start); + continue; + } + if (strcmp(cpe->word, KW_CONTROL) == 0) + { + do_control(cpe->next, rs_start); + continue; + } + } +} + +PRIVATE const char *do_config(const char *label, char *filename, struct rs_config *rs_config) +{ + config_t *config, *cp, *cpe; + struct passwd *pw; + struct rs_start *rs_start = &rs_config->rs_start; + + if(!(config= config_read(filename, 0, NULL))) + return NULL; /* config file read failed. */ + + /* Set clean rs_start defaults. */ + memset(rs_config, 0, sizeof(*rs_config)); + if(!(pw= getpwnam(SERVICE_LOGIN))) + fatal("no passwd file entry for '%s'", SERVICE_LOGIN); + rs_start->rss_uid= pw->pw_uid; + rs_start->rss_sigmgr= DSRV_SM; + rs_start->rss_scheduler= DSRV_SCH; + rs_start->rss_priority= DSRV_Q; + rs_start->rss_quantum= DSRV_QT; + rs_start->rss_cpu = DSRV_CPU; + rs_start->rss_flags = RSS_VM_BASIC_CALLS | RSS_SYS_BASIC_CALLS; + + /* Find an entry for our service */ + for (cp= config; cp; cp= cp->next) + { + if (!(cp->flags & CFG_SUBLIST)) + { + fatal("do_config: expected list at %s:%d", + cp->file, cp->line); + } + cpe= cp->list; + if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) + { + fatal("do_config: expected word at %s:%d", + cpe->file, cpe->line); + } + + /* At this place we expect the word KW_SERVICE */ + if (strcmp(cpe->word, KW_SERVICE) != 0) + fatal("do_config: exected word '%S' at %s:%d", + KW_SERVICE, cpe->file, cpe->line); + + cpe= cpe->next; + if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) + { + fatal("do_config: expected word at %s:%d", + cpe->file, cpe->line); + } + + /* At this place we expect the name of the service. */ + if (!label || strcmp(cpe->word, label) == 0) { + label = cpe->word; + break; + } + } + if (cp == NULL) + { + fprintf(stderr, "service: service '%s' not found in '%s'\n", + label, filename); + exit(1); + } + + cpe= cpe->next; + + do_service(cpe, config, rs_config); + + { + char *default_ipc = RSS_IPC_ALL_SYS; + if(!rs_start->rss_ipc) { + rs_start->rss_ipc= default_ipc; + rs_start->rss_ipclen= strlen(default_ipc); + } + } + + /* config file read ok. */ + return label; +} + +/* returns failure */ +PUBLIC const char *parse_config(char *progname, int custom_config, char *req_config, + struct rs_config *rs_config) +{ + char *specificconfig, *specific_pkg_config; + const char *l; + + /* Config file specified? */ + if(custom_config) + return do_config(progname, req_config, rs_config); + + /* No specific config file. */ + if(asprintf(&specificconfig, "%s/%s", _PATH_SYSTEM_CONF_DIR, + progname) < 0) { + errx(1, "no memory"); + } + + if(asprintf(&specific_pkg_config, "%s/%s", _PATH_SYSTEM_CONF_PKG_DIR, + progname) < 0) { + errx(1, "no memory"); + } + + /* Try specific config filename first, in base system + * and package locations, * and only if it fails, the global + * system one. + */ + if((l=do_config(progname, specific_pkg_config, rs_config))) return l; + if((l=do_config(progname, specificconfig, rs_config))) return l; + if((l=do_config(progname, req_config, rs_config))) return l; + + return NULL; +} + diff --git a/commands/service/parse.h b/commands/service/parse.h new file mode 100644 index 000000000..08487b628 --- /dev/null +++ b/commands/service/parse.h @@ -0,0 +1,23 @@ +#define KW_SERVICE "service" +#define KW_UID "uid" +#define KW_SIGMGR "sigmgr" +#define KW_SCHEDULER "scheduler" +#define KW_PRIORITY "priority" +#define KW_QUANTUM "quantum" +#define KW_CPU "cpu" +#define KW_IRQ "irq" +#define KW_IO "io" +#define KW_PCI "pci" +#define KW_DEVICE "device" +#define KW_CLASS "class" +#define KW_SYSTEM "system" +#define KW_IPC "ipc" +#define KW_VM "vm" +#define KW_CONTROL "control" +#define KW_ALL "ALL" +#define KW_ALL_SYS "ALL_SYS" +#define KW_NONE "NONE" +#define KW_BASIC "BASIC" +#define KW_TYPE "type" /* set service type */ +#define KW_NET "net" /* ethernet driver type */ +#define KW_DESCR "descr" /* human-readable string */ diff --git a/commands/service/print.c b/commands/service/print.c new file mode 100644 index 000000000..52ea796d5 --- /dev/null +++ b/commands/service/print.c @@ -0,0 +1,97 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "config.h" +#include "proto.h" +#include "parse.h" + +#define MAXDEPTH 10 + +static struct { + const char *field, *str; +} configstack[MAXDEPTH]; + +int depth = 0; + +void printstack(void) +{ + int i; + for(i = 0; i < depth; i++) + printf("%s %s,", configstack[i].field, + configstack[i].str); +} + +void print(const char *field, const char *str) +{ + printstack(); + printf("%s %s\n", field, str); +} + +void push(const char *field, const char *str) +{ + assert(depth < MAXDEPTH); + configstack[depth].field = field; + configstack[depth].str = str; + depth++; + printstack(); + printf("\n"); +} + +int main(int argc, char **argv) +{ + struct rs_config config; + const char *label; + int id; + + if(argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + + memset(&config, 0, sizeof(config)); + if(!(label = parse_config(NULL, 1, argv[1], &config))) + errx(1, "parse_config failed"); + + push(KW_SERVICE, label); + if(config.type) push(KW_TYPE, config.type); + + if(config.descr) push(KW_DESCR, config.descr); + if(config.rs_start.rss_nr_pci_id > 0) { + printstack(); + printf("%s %s ", KW_PCI, KW_DEVICE); + for(id = 0; id < config.rs_start.rss_nr_pci_id; id++) { + printf("%04X:%04X ", + config.rs_start.rss_pci_id[id].vid, + config.rs_start.rss_pci_id[id].did); + } + printf("\n"); + } +} + diff --git a/commands/service/proto.h b/commands/service/proto.h new file mode 100644 index 000000000..48cfb78b2 --- /dev/null +++ b/commands/service/proto.h @@ -0,0 +1,3 @@ +void fatal(char *fmt, ...); +const char *parse_config(char *progname, int custom, char *configname, + struct rs_config *config); diff --git a/commands/service/service.c b/commands/service/service.c index 68314c8f6..8f2b56d66 100644 --- a/commands/service/service.c +++ b/commands/service/service.c @@ -33,8 +33,11 @@ #include #include +#include #include "kernel/proc.h" +#include "config.h" +#include "proto.h" /* This array defines all known requests. */ PRIVATE char *known_requests[] = { @@ -98,10 +101,6 @@ PRIVATE char *known_requests[] = { #define ARG_DEVMANID "-devid" /* the id of the devman device this driver should be able to access */ -#define SERVICE_LOGIN "service" /* passwd file entry for services */ - -#define MAX_CLASS_RECURS 100 /* Max nesting level for classes */ - /* The function parse_arguments() verifies and parses the command line * parameters passed to this utility. Request parameters that are needed * are stored globally in the following variables: @@ -117,19 +116,14 @@ PRIVATE int devman_id = 0; PRIVATE int req_dev_style = STYLE_NDEV; PRIVATE long req_period = 0; PRIVATE char *req_script = NULL; -PRIVATE char *req_ipc = NULL; PRIVATE char *req_config = PATH_CONFIG; PRIVATE int custom_config_file = 0; -PRIVATE int class_recurs; /* Nesting level of class statements */ PRIVATE int req_lu_state = DEFAULT_LU_STATE; PRIVATE int req_lu_maxtime = DEFAULT_LU_MAXTIME; /* Buffer to build "/command arg1 arg2 ..." string to pass to RS server. */ PRIVATE char command[4096]; -/* Arguments for RS to start a new service */ -PRIVATE struct rs_start rs_start; - /* An error occurred. Report the problem, print the usage, and exit. */ PRIVATE void print_usage(char *app_name, char *problem) @@ -161,7 +155,7 @@ PRIVATE void failure(int request) /* Parse and verify correctness of arguments. Report problem and exit if an * error is found. Store needed parameters in global variables. */ -PRIVATE int parse_arguments(int argc, char **argv) +PRIVATE int parse_arguments(int argc, char **argv, u32_t *rss_flags) { struct stat stat_buf; char *hz, *buff; @@ -226,28 +220,28 @@ PRIVATE int parse_arguments(int argc, char **argv) req_nr = RS_RQ_BASE + req_type; } - rs_start.rss_flags = RSS_SYS_BASIC_CALLS | RSS_VM_BASIC_CALLS; + *rss_flags = 0; if (req_nr == RS_UP || req_nr == RS_UPDATE || req_nr == RS_EDIT) { u32_t system_hz; if (c_flag) - rs_start.rss_flags |= RSS_COPY; + *rss_flags |= RSS_COPY; if(r_flag) - rs_start.rss_flags |= RSS_REUSE; + *rss_flags |= RSS_REUSE; if(n_flag) - rs_start.rss_flags |= RSS_NOBLOCK; + *rss_flags |= RSS_NOBLOCK; if(p_flag) - rs_start.rss_flags |= RSS_REPLICA; + *rss_flags |= RSS_REPLICA; req_path = argv[optind+ARG_PATH]; if(req_nr == RS_UPDATE && !strcmp(req_path, SELF_BINARY)) { /* Self update needs no real path or configuration file. */ req_config = NULL; req_path = req_path_self; - rs_start.rss_flags |= RSS_SELF_LU; + *rss_flags |= RSS_SELF_LU; } if (do_run) @@ -263,7 +257,7 @@ PRIVATE int parse_arguments(int argc, char **argv) } /* Verify the name of the binary of the system service. */ - if(!(rs_start.rss_flags & RSS_SELF_LU)) { + if(!(*rss_flags & RSS_SELF_LU)) { if (req_path[0] != '/') { print_usage(argv[ARG_NAME], "binary should be absolute path"); exit(EINVAL); @@ -406,7 +400,7 @@ PRIVATE int parse_arguments(int argc, char **argv) /* no extra arguments required */ } - label_required = (rs_start.rss_flags & RSS_SELF_LU) || (req_nr == RS_EDIT); + label_required = (*rss_flags & RSS_SELF_LU) || (req_nr == RS_EDIT); if(label_required && !req_label) { print_usage(argv[ARG_NAME], "label option mandatory for target action"); exit(EINVAL); @@ -416,1014 +410,6 @@ PRIVATE int parse_arguments(int argc, char **argv) return(req_nr); } -PRIVATE void fatal(char *fmt, ...) -{ - va_list ap; - - fprintf(stderr, "fatal error: "); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); - - exit(1); -} - -#define KW_SERVICE "service" -#define KW_UID "uid" -#define KW_SIGMGR "sigmgr" -#define KW_SCHEDULER "scheduler" -#define KW_PRIORITY "priority" -#define KW_QUANTUM "quantum" -#define KW_CPU "cpu" -#define KW_IRQ "irq" -#define KW_IO "io" -#define KW_PCI "pci" -#define KW_DEVICE "device" -#define KW_CLASS "class" -#define KW_SYSTEM "system" -#define KW_IPC "ipc" -#define KW_VM "vm" -#define KW_CONTROL "control" -#define KW_ALL "ALL" -#define KW_ALL_SYS "ALL_SYS" -#define KW_NONE "NONE" -#define KW_BASIC "BASIC" - -FORWARD void do_service(config_t *cpe, config_t *config); - -PRIVATE void do_class(config_t *cpe, config_t *config) -{ - config_t *cp, *cp1; - - if (class_recurs > MAX_CLASS_RECURS) - { - fatal( - "do_class: nesting level too high for class '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - class_recurs++; - - /* Process classes */ - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_class: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_uid: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - /* Find entry for the class */ - for (cp= config; cp; cp= cp->next) - { - if (!(cp->flags & CFG_SUBLIST)) - { - fatal("do_class: expected list at %s:%d", - cp->file, cp->line); - } - cp1= cp->list; - if ((cp1->flags & CFG_STRING) || - (cp1->flags & CFG_SUBLIST)) - { - fatal("do_class: expected word at %s:%d", - cp1->file, cp1->line); - } - - /* At this place we expect the word KW_SERVICE */ - if (strcmp(cp1->word, KW_SERVICE) != 0) - fatal("do_class: exected word '%S' at %s:%d", - KW_SERVICE, cp1->file, cp1->line); - - cp1= cp1->next; - if ((cp1->flags & CFG_STRING) || - (cp1->flags & CFG_SUBLIST)) - { - fatal("do_class: expected word at %s:%d", - cp1->file, cp1->line); - } - - /* At this place we expect the name of the service */ - if (strcmp(cp1->word, cpe->word) == 0) - break; - } - if (cp == NULL) - { - fatal( - "do_class: no entry found for class '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - do_service(cp1->next, config); - } - - class_recurs--; -} - -PRIVATE void do_uid(config_t *cpe) -{ - uid_t uid; - struct passwd *pw; - char *check; - - /* Process a uid */ - if (cpe->next != NULL) - { - fatal("do_uid: just one uid/login expected at %s:%d", - cpe->file, cpe->line); - } - - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_uid: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_uid: unexpected string at %s:%d", - cpe->file, cpe->line); - } - pw= getpwnam(cpe->word); - if (pw != NULL) - uid= pw->pw_uid; - else - { - uid= strtol(cpe->word, &check, 0); - if (check[0] != '\0') - { - fatal("do_uid: bad uid/login '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - } - - rs_start.rss_uid= uid; -} - -PRIVATE void do_sigmgr(config_t *cpe) -{ - endpoint_t sigmgr_ep; - int r; - - /* Process a signal manager value */ - if (cpe->next != NULL) - { - fatal("do_sigmgr: just one sigmgr value expected at %s:%d", - cpe->file, cpe->line); - } - - - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_sigmgr: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_sigmgr: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - if(!strcmp(cpe->word, "SELF")) { - sigmgr_ep = SELF; - } - else { - r = minix_rs_lookup(cpe->word, &sigmgr_ep); - if(r != OK) { - fatal("do_sigmgr: unknown sigmgr %s at %s:%d", - cpe->word, cpe->file, cpe->line); - } - } - - rs_start.rss_sigmgr= sigmgr_ep; -} - -PRIVATE void do_scheduler(config_t *cpe) -{ - endpoint_t scheduler_ep; - int r; - - /* Process a scheduler value */ - if (cpe->next != NULL) - { - fatal("do_scheduler: just one scheduler value expected at %s:%d", - cpe->file, cpe->line); - } - - - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_scheduler: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_scheduler: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - if(!strcmp(cpe->word, "KERNEL")) { - scheduler_ep = KERNEL; - } - else { - r = minix_rs_lookup(cpe->word, &scheduler_ep); - if(r != OK) { - fatal("do_scheduler: unknown scheduler %s at %s:%d", - cpe->word, cpe->file, cpe->line); - } - } - - rs_start.rss_scheduler= scheduler_ep; -} - -PRIVATE void do_priority(config_t *cpe) -{ - int priority_val; - char *check; - - /* Process a priority value */ - if (cpe->next != NULL) - { - fatal("do_priority: just one priority value expected at %s:%d", - cpe->file, cpe->line); - } - - - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_priority: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_priority: unexpected string at %s:%d", - cpe->file, cpe->line); - } - priority_val= strtol(cpe->word, &check, 0); - if (check[0] != '\0') - { - fatal("do_priority: bad priority value '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - - if (priority_val < 0 || priority_val >= NR_SCHED_QUEUES) - { - fatal("do_priority: priority %d out of range at %s:%d", - priority_val, cpe->file, cpe->line); - } - rs_start.rss_priority= priority_val; -} - -PRIVATE void do_quantum(config_t *cpe) -{ - int quantum_val; - char *check; - - /* Process a quantum value */ - if (cpe->next != NULL) - { - fatal("do_quantum: just one quantum value expected at %s:%d", - cpe->file, cpe->line); - } - - - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_quantum: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_quantum: unexpected string at %s:%d", - cpe->file, cpe->line); - } - quantum_val= strtol(cpe->word, &check, 0); - if (check[0] != '\0') - { - fatal("do_quantum: bad quantum value '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - - if (quantum_val <= 0) - { - fatal("do_quantum: quantum %d out of range at %s:%d", - quantum_val, cpe->file, cpe->line); - } - rs_start.rss_quantum= quantum_val; -} - -PRIVATE void do_cpu(config_t *cpe) -{ - int cpu; - char *check; - - /* Process a quantum value */ - if (cpe->next != NULL) - { - fatal("do_cpu: just one value expected at %s:%d", - cpe->file, cpe->line); - } - - - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_cpu: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_cpu: unexpected string at %s:%d", - cpe->file, cpe->line); - } - cpu= strtol(cpe->word, &check, 0); - if (check[0] != '\0') - { - fatal("do_cpu: bad value '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - - if (cpu < 0) - { - fatal("do_cpu: %d out of range at %s:%d", - cpu, cpe->file, cpe->line); - } - rs_start.rss_cpu= cpu; -} - -PRIVATE void do_irq(config_t *cpe) -{ - int irq; - int first; - char *check; - - /* Process a list of IRQs */ - first = TRUE; - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_irq: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_irq: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - /* No IRQ allowed? (default) */ - if(!strcmp(cpe->word, KW_NONE)) { - if(!first || cpe->next) { - fatal("do_irq: %s keyword not allowed in list", - KW_NONE); - } - break; - } - - /* All IRQs are allowed? */ - if(!strcmp(cpe->word, KW_ALL)) { - if(!first || cpe->next) { - fatal("do_irq: %s keyword not allowed in list", - KW_ALL); - } - rs_start.rss_nr_irq = RSS_IO_ALL; - break; - } - - /* Set single IRQs as specified in the configuration. */ - irq= strtoul(cpe->word, &check, 0); - if (check[0] != '\0') - { - fatal("do_irq: bad irq '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - if (rs_start.rss_nr_irq >= RSS_NR_IRQ) - fatal("do_irq: too many IRQs (max %d)", RSS_NR_IRQ); - rs_start.rss_irq[rs_start.rss_nr_irq]= irq; - rs_start.rss_nr_irq++; - first = FALSE; - } -} - -PRIVATE void do_io(config_t *cpe) -{ - unsigned base, len; - int first; - char *check; - - /* Process a list of I/O ranges */ - first = TRUE; - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_io: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_io: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - /* No range allowed? (default) */ - if(!strcmp(cpe->word, KW_NONE)) { - if(!first || cpe->next) { - fatal("do_io: %s keyword not allowed in list", - KW_NONE); - } - break; - } - - /* All ranges are allowed? */ - if(!strcmp(cpe->word, KW_ALL)) { - if(!first || cpe->next) { - fatal("do_io: %s keyword not allowed in list", - KW_ALL); - } - rs_start.rss_nr_io = RSS_IO_ALL; - break; - } - - /* Set single ranges as specified in the configuration. */ - base= strtoul(cpe->word, &check, 0x10); - len= 1; - if (check[0] == ':') - { - len= strtoul(check+1, &check, 0x10); - } - if (check[0] != '\0') - { - fatal("do_io: bad I/O range '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - - if (rs_start.rss_nr_io >= RSS_NR_IO) - fatal("do_io: too many I/O ranges (max %d)", RSS_NR_IO); - rs_start.rss_io[rs_start.rss_nr_io].base= base; - rs_start.rss_io[rs_start.rss_nr_io].len= len; - rs_start.rss_nr_io++; - first = FALSE; - } -} - -PRIVATE void do_pci_device(config_t *cpe) -{ - u16_t vid, did; - char *check, *check2; - - /* Process a list of PCI device IDs */ - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_pci_device: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_pci_device: unexpected string at %s:%d", - cpe->file, cpe->line); - } - vid= strtoul(cpe->word, &check, 0x10); - if (check[0] == '/') - did= strtoul(check+1, &check2, 0x10); - if (check[0] != '/' || check2[0] != '\0') - { - fatal("do_pci_device: bad ID '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - if (rs_start.rss_nr_pci_id >= RS_NR_PCI_DEVICE) - { - fatal("do_pci_device: too many device IDs (max %d)", - RS_NR_PCI_DEVICE); - } - rs_start.rss_pci_id[rs_start.rss_nr_pci_id].vid= vid; - rs_start.rss_pci_id[rs_start.rss_nr_pci_id].did= did; - rs_start.rss_nr_pci_id++; - } -} - -PRIVATE void do_pci_class(config_t *cpe) -{ - u8_t baseclass, subclass, interface; - u32_t class_id, mask; - char *check; - - /* Process a list of PCI device class IDs */ - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_pci_device: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_pci_device: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - baseclass= strtoul(cpe->word, &check, 0x10); - subclass= 0; - interface= 0; - mask= 0xff0000; - if (check[0] == '/') - { - subclass= strtoul(check+1, &check, 0x10); - mask= 0xffff00; - if (check[0] == '/') - { - interface= strtoul(check+1, &check, 0x10); - mask= 0xffffff; - } - } - - if (check[0] != '\0') - { - fatal("do_pci_class: bad class ID '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - } - class_id= (baseclass << 16) | (subclass << 8) | interface; - if (rs_start.rss_nr_pci_class >= RS_NR_PCI_CLASS) - { - fatal("do_pci_class: too many class IDs (max %d)", - RS_NR_PCI_CLASS); - } - rs_start.rss_pci_class[rs_start.rss_nr_pci_class].pciclass= - class_id; - rs_start.rss_pci_class[rs_start.rss_nr_pci_class].mask= mask; - rs_start.rss_nr_pci_class++; - } -} - -PRIVATE void do_pci(config_t *cpe) -{ - if (cpe == NULL) - return; /* Empty PCI statement */ - - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_pci: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_pci: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - if (strcmp(cpe->word, KW_DEVICE) == 0) - { - do_pci_device(cpe->next); - return; - } - if (strcmp(cpe->word, KW_CLASS) == 0) - { - do_pci_class(cpe->next); - return; - } - fatal("do_pci: unexpected word '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); -} - -PRIVATE void do_ipc(config_t *cpe) -{ - char *list, *word; - char *word_all = RSS_IPC_ALL; - char *word_all_sys = RSS_IPC_ALL_SYS; - size_t listsize, wordlen; - int first; - - list= NULL; - listsize= 1; - list= malloc(listsize); - if (list == NULL) - fatal("do_ipc: unable to malloc %d bytes", listsize); - list[0]= '\0'; - - /* Process a list of process names that are allowed to be - * contacted - */ - first = TRUE; - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_ipc: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_ipc: unexpected string at %s:%d", - cpe->file, cpe->line); - } - word = cpe->word; - - /* All (system) ipc targets are allowed? */ - if(!strcmp(word, KW_ALL) || !strcmp(word, KW_ALL_SYS)) { - if(!first || cpe->next) { - fatal("do_ipc: %s keyword not allowed in list", - word); - } - word = !strcmp(word, KW_ALL) ? word_all : word_all_sys; - } - - wordlen= strlen(word); - - listsize += 1 + wordlen; - list= realloc(list, listsize); - if (list == NULL) - { - fatal("do_ipc: unable to realloc %d bytes", - listsize); - } - strcat(list, " "); - strcat(list, word); - first = FALSE; - } -#if 0 - printf("do_ipc: got list '%s'\n", list); -#endif - - if (req_ipc) - fatal("do_ipc: req_ipc is set"); - req_ipc= list; -} - -struct -{ - char *label; - int call_nr; -} vm_table[] = -{ - { "EXIT", VM_EXIT }, - { "FORK", VM_FORK }, - { "BRK", VM_BRK }, - { "EXEC_NEWMEM", VM_EXEC_NEWMEM }, - { "PUSH_SIG", VM_PUSH_SIG }, - { "WILLEXIT", VM_WILLEXIT }, - { "ADDDMA", VM_ADDDMA }, - { "DELDMA", VM_DELDMA }, - { "GETDMA", VM_GETDMA }, - { "REMAP", VM_REMAP }, - { "SHM_UNMAP", VM_SHM_UNMAP }, - { "GETPHYS", VM_GETPHYS }, - { "GETREF", VM_GETREF }, - { "RS_SET_PRIV", VM_RS_SET_PRIV }, - { "QUERY_EXIT", VM_QUERY_EXIT }, - { "WATCH_EXIT", VM_WATCH_EXIT }, - { "NOTIFY_SIG", VM_NOTIFY_SIG }, - { "INFO", VM_INFO }, - { "RS_UPDATE", VM_RS_UPDATE }, - { "RS_MEMCTL", VM_RS_MEMCTL }, - { NULL, 0 }, -}; - -PRIVATE void do_vm(config_t *cpe) -{ - int i, first; - - first = TRUE; - for (; cpe; cpe = cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_vm: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_vm: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - /* Only basic calls allowed? (default). */ - if(!strcmp(cpe->word, KW_BASIC)) { - if(!first || cpe->next) { - fatal("do_vm: %s keyword not allowed in list", - KW_NONE); - } - break; - } - - /* No calls allowed? */ - if(!strcmp(cpe->word, KW_NONE)) { - if(!first || cpe->next) { - fatal("do_vm: %s keyword not allowed in list", - KW_NONE); - } - rs_start.rss_flags &= ~RSS_VM_BASIC_CALLS; - break; - } - - /* All calls are allowed? */ - if(!strcmp(cpe->word, KW_ALL)) { - if(!first || cpe->next) { - fatal("do_vm: %s keyword not allowed in list", - KW_ALL); - } - for (i = 0; i < NR_VM_CALLS; i++) - SET_BIT(rs_start.rss_vm, i); - break; - } - - /* Set single calls as specified in the configuration. */ - for (i = 0; vm_table[i].label != NULL; i++) - if (!strcmp(cpe->word, vm_table[i].label)) - break; - if (vm_table[i].label == NULL) - fatal("do_vm: unknown call '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - SET_BIT(rs_start.rss_vm, vm_table[i].call_nr - VM_RQ_BASE); - first = FALSE; - } -} - -struct -{ - char *label; - int call_nr; -} system_tab[]= -{ - { "PRIVCTL", SYS_PRIVCTL }, - { "TRACE", SYS_TRACE }, - { "KILL", SYS_KILL }, - { "UMAP", SYS_UMAP }, - { "VIRCOPY", SYS_VIRCOPY }, - { "PHYSCOPY", SYS_PHYSCOPY }, - { "UMAP_REMOTE", SYS_UMAP_REMOTE }, - { "IRQCTL", SYS_IRQCTL }, - { "INT86", SYS_INT86 }, - { "DEVIO", SYS_DEVIO }, - { "SDEVIO", SYS_SDEVIO }, - { "VDEVIO", SYS_VDEVIO }, - { "ABORT", SYS_ABORT }, - { "IOPENABLE", SYS_IOPENABLE }, - { "READBIOS", SYS_READBIOS }, - { "STIME", SYS_STIME }, - { "VMCTL", SYS_VMCTL }, - { NULL, 0 } -}; - -PRIVATE void do_system(config_t *cpe) -{ - int i, first; - - /* Process a list of 'system' calls that are allowed */ - first = TRUE; - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_system: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_system: unexpected string at %s:%d", - cpe->file, cpe->line); - } - - /* Only basic calls allowed? (default). */ - if(!strcmp(cpe->word, KW_BASIC)) { - if(!first || cpe->next) { - fatal("do_system: %s keyword not allowed in list", - KW_NONE); - } - break; - } - - /* No calls allowed? */ - if(!strcmp(cpe->word, KW_NONE)) { - if(!first || cpe->next) { - fatal("do_system: %s keyword not allowed in list", - KW_NONE); - } - rs_start.rss_flags &= ~RSS_SYS_BASIC_CALLS; - break; - } - - /* All calls are allowed? */ - if(!strcmp(cpe->word, KW_ALL)) { - if(!first || cpe->next) { - fatal("do_system: %s keyword not allowed in list", - KW_ALL); - } - for (i = 0; i < NR_SYS_CALLS; i++) - SET_BIT(rs_start.rss_system, i); - break; - } - - /* Set single calls as specified in the configuration. */ - for (i = 0; system_tab[i].label != NULL; i++) - if (!strcmp(cpe->word, system_tab[i].label)) - break; - if (system_tab[i].label == NULL) - fatal("do_system: unknown call '%s' at %s:%d", - cpe->word, cpe->file, cpe->line); - SET_BIT(rs_start.rss_system, system_tab[i].call_nr - KERNEL_CALL); - first = FALSE; - } -} - -PRIVATE void do_control(config_t *cpe) -{ - int nr_control = 0; - - /* Process a list of 'control' labels. */ - for (; cpe; cpe= cpe->next) - { - if (cpe->flags & CFG_SUBLIST) - { - fatal("do_control: unexpected sublist at %s:%d", - cpe->file, cpe->line); - } - if (cpe->flags & CFG_STRING) - { - fatal("do_control: unexpected string at %s:%d", - cpe->file, cpe->line); - } - if (nr_control >= RS_NR_CONTROL) - { - fatal( - "do_control: RS_NR_CONTROL is too small (%d needed)", - nr_control+1); - } - - rs_start.rss_control[nr_control].l_addr = (char*) cpe->word; - rs_start.rss_control[nr_control].l_len = strlen(cpe->word); - rs_start.rss_nr_control = ++nr_control; - } -} - -PRIVATE void do_service(config_t *cpe, config_t *config) -{ - config_t *cp; - - /* At this point we expect one sublist that contains the varios - * resource allocations - */ - if (!(cpe->flags & CFG_SUBLIST)) - { - fatal("do_service: expected list at %s:%d", - cpe->file, cpe->line); - } - if (cpe->next != NULL) - { - cpe= cpe->next; - fatal("do_service: expected end of list at %s:%d", - cpe->file, cpe->line); - } - cpe= cpe->list; - - /* Process the list */ - for (cp= cpe; cp; cp= cp->next) - { - if (!(cp->flags & CFG_SUBLIST)) - { - fatal("do_service: expected list at %s:%d", - cp->file, cp->line); - } - cpe= cp->list; - if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) - { - fatal("do_service: expected word at %s:%d", - cpe->file, cpe->line); - } - - if (strcmp(cpe->word, KW_CLASS) == 0) - { - do_class(cpe->next, config); - continue; - } - if (strcmp(cpe->word, KW_UID) == 0) - { - do_uid(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_SIGMGR) == 0) - { - do_sigmgr(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_SCHEDULER) == 0) - { - do_scheduler(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_PRIORITY) == 0) - { - do_priority(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_QUANTUM) == 0) - { - do_quantum(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_CPU) == 0) - { - do_cpu(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_IRQ) == 0) - { - do_irq(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_IO) == 0) - { - do_io(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_PCI) == 0) - { - do_pci(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_SYSTEM) == 0) - { - do_system(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_IPC) == 0) - { - do_ipc(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_VM) == 0) - { - do_vm(cpe->next); - continue; - } - if (strcmp(cpe->word, KW_CONTROL) == 0) - { - do_control(cpe->next); - continue; - } - } -} - -PRIVATE int do_config(char *label, char *filename) -{ - config_t *config, *cp, *cpe; - - config= config_read(filename, 0, NULL); - if (config == NULL) - { - /* config file read failed. */ - return 1; - } - - /* Find an entry for our service */ - for (cp= config; cp; cp= cp->next) - { - if (!(cp->flags & CFG_SUBLIST)) - { - fatal("do_config: expected list at %s:%d", - cp->file, cp->line); - } - cpe= cp->list; - if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) - { - fatal("do_config: expected word at %s:%d", - cpe->file, cpe->line); - } - - /* At this place we expect the word KW_SERVICE */ - if (strcmp(cpe->word, KW_SERVICE) != 0) - fatal("do_config: exected word '%S' at %s:%d", - KW_SERVICE, cpe->file, cpe->line); - - cpe= cpe->next; - if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) - { - fatal("do_config: expected word at %s:%d", - cpe->file, cpe->line); - } - - /* At this place we expect the name of the service. */ - if (strcmp(cpe->word, label) == 0) - break; - } - if (cp == NULL) - { - fprintf(stderr, "service: service '%s' not found in '%s'\n", - label, filename); - exit(1); - } - - cpe= cpe->next; - - do_service(cpe, config); - - /* config file read ok. */ - return 0; -} - /* Main program. */ PUBLIC int main(int argc, char **argv) @@ -1432,14 +418,16 @@ PUBLIC int main(int argc, char **argv) int result = EXIT_SUCCESS; int request; char *progname = NULL; - struct passwd *pw; + /* Arguments for RS to start a new service */ + struct rs_config config; + u32_t rss_flags = 0; /* Verify and parse the command line arguments. All arguments are checked * here. If an error occurs, the problem is reported and exit(2) is called. * all needed parameters to perform the request are extracted and stored * global variables. */ - request = parse_arguments(argc, argv); + request = parse_arguments(argc, argv, &rss_flags); /* Arguments seem fine. Try to perform the request. Only valid requests * should end up here. The default is used for not yet supported requests. @@ -1460,78 +448,38 @@ PUBLIC int main(int argc, char **argv) command[strlen(req_path)] = ' '; strcpy(command+strlen(req_path)+1, req_args); - rs_start.rss_cmd= command; - rs_start.rss_cmdlen= strlen(command); - rs_start.rss_major= req_major; - rs_start.rss_dev_style= req_dev_style; - rs_start.rss_period= req_period; - rs_start.rss_script= req_script; - rs_start.devman_id= devman_id; - if(req_label) { - rs_start.rss_label.l_addr = req_label; - rs_start.rss_label.l_len = strlen(req_label); - } else { - rs_start.rss_label.l_addr = progname; - rs_start.rss_label.l_len = strlen(progname); - } - if (req_script) - rs_start.rss_scriptlen= strlen(req_script); - else - rs_start.rss_scriptlen= 0; - - pw= getpwnam(SERVICE_LOGIN); - if (pw == NULL) - fatal("no passwd file entry for '%s'", SERVICE_LOGIN); - rs_start.rss_uid= pw->pw_uid; - - rs_start.rss_sigmgr= DSRV_SM; - rs_start.rss_scheduler= DSRV_SCH; - rs_start.rss_priority= DSRV_Q; - rs_start.rss_quantum= DSRV_QT; - rs_start.rss_cpu = DSRV_CPU; - if (req_config) { - int config_fail = 0; assert(progname); - if(custom_config_file) { - config_fail = do_config(progname, req_config); - } else { - char *specificconfig; - if(asprintf(&specificconfig, "%s/%s", _PATH_SYSTEM_CONF_DIR, - progname) < 0) { - errx(1, "no memory"); - } - - /* Try specific config filename first, - * and only if it fails, the global system one. - */ - config_fail = - do_config(progname, specificconfig) && - do_config(progname, req_config); - } - - if(config_fail) { - fprintf(stderr, "config_read failed for %s\n", progname); - exit(1); - } + memset(&config, 0, sizeof(config)); + if(!parse_config(progname, custom_config_file, req_config, &config)) + errx(1, "couldn't parse config"); } - assert(rs_start.rss_priority < NR_SCHED_QUEUES); - assert(rs_start.rss_quantum > 0); - - if (req_ipc) - { - rs_start.rss_ipc= req_ipc+1; /* Skip initial space */ - rs_start.rss_ipclen= strlen(rs_start.rss_ipc); + /* Set specifics */ + config.rs_start.rss_cmd= command; + config.rs_start.rss_cmdlen= strlen(command); + config.rs_start.rss_major= req_major; + config.rs_start.rss_dev_style= req_dev_style; + config.rs_start.rss_period= req_period; + config.rs_start.rss_script= req_script; + config.rs_start.devman_id= devman_id; + config.rs_start.rss_flags |= rss_flags; + if(req_label) { + config.rs_start.rss_label.l_addr = req_label; + config.rs_start.rss_label.l_len = strlen(req_label); + } else { + config.rs_start.rss_label.l_addr = progname; + config.rs_start.rss_label.l_len = strlen(progname); } + if (req_script) + config.rs_start.rss_scriptlen= strlen(req_script); else - { - char *default_ipc = RSS_IPC_ALL_SYS; - rs_start.rss_ipc= default_ipc; - rs_start.rss_ipclen= strlen(default_ipc); - } + config.rs_start.rss_scriptlen= 0; + + assert(config.rs_start.rss_priority < NR_SCHED_QUEUES); + assert(config.rs_start.rss_quantum > 0); - m.RS_CMD_ADDR = (char *) &rs_start; + m.RS_CMD_ADDR = (char *) &config.rs_start; break; case RS_DOWN: case RS_REFRESH: diff --git a/commands/service/util.c b/commands/service/util.c new file mode 100644 index 000000000..6a36a8dad --- /dev/null +++ b/commands/service/util.c @@ -0,0 +1,17 @@ + +#include +#include +#include + +void fatal(char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "fatal error: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + exit(1); +} diff --git a/common/include/minix/minlib.h b/common/include/minix/minlib.h index 82f9cd998..7787a867a 100644 --- a/common/include/minix/minlib.h +++ b/common/include/minix/minlib.h @@ -9,7 +9,9 @@ _PROTOTYPE(char *itoa, (int _n)); #ifndef __NBSD_LIBC _PROTOTYPE(char *getpass, (const char *_prompt)); +#ifdef __ACK__ _PROTOTYPE(void swab, (char *_from, char *_to, int _count)); +#endif #endif /* !_NBSD_LIBC */ /* Miscellaneous MINIX. */ diff --git a/drivers/atl2/Makefile b/drivers/atl2/Makefile index 31d5a382d..22d8d492f 100644 --- a/drivers/atl2/Makefile +++ b/drivers/atl2/Makefile @@ -2,6 +2,10 @@ PROG= atl2 SRCS= atl2.c +FILES=$(PROG).conf +FILESNAME=$(PROG) +FILESDIR= /etc/system.conf.d + DPADD+= ${LIBNETDRIVER} ${LIBSYS} LDADD+= -lnetdriver -lsys diff --git a/drivers/atl2/atl2.conf b/drivers/atl2/atl2.conf new file mode 100644 index 000000000..4cfee56bc --- /dev/null +++ b/drivers/atl2/atl2.conf @@ -0,0 +1,15 @@ +service atl2 +{ + type net; + descr "Attansic/Atheros L2 FastEthernet"; + system + UMAP # 14 + IRQCTL # 19 + ; + pci device 1969/2048; + ipc + SYSTEM pm rs tty ds vm + pci inet lwip + ; +}; + diff --git a/drivers/dec21140A/Makefile b/drivers/dec21140A/Makefile index 42051f8ad..9b9522ffc 100644 --- a/drivers/dec21140A/Makefile +++ b/drivers/dec21140A/Makefile @@ -4,6 +4,10 @@ PROG= dec21140A SRCS= dec21140A.c +FILES=$(PROG).conf +FILESNAME=$(PROG) +FILESDIR= /etc/system.conf.d + DPADD+= ${LIBNETDRIVER} ${LIBSYS} LDADD+= -lnetdriver -lsys diff --git a/drivers/dec21140A/dec21140A.conf b/drivers/dec21140A/dec21140A.conf new file mode 100644 index 000000000..dd1199382 --- /dev/null +++ b/drivers/dec21140A/dec21140A.conf @@ -0,0 +1,17 @@ + +service dec21140A +{ + type net; + descr "DEC Tulip 21140A in VirtualPC"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + pci device 1011/0009; + ipc + SYSTEM pm rs log tty ds vm + pci inet lwip + ; +}; + diff --git a/drivers/e1000/Makefile b/drivers/e1000/Makefile index 91c8b43a8..aff128209 100644 --- a/drivers/e1000/Makefile +++ b/drivers/e1000/Makefile @@ -4,6 +4,10 @@ PROG= e1000 SRCS= e1000.c +FILES=$(PROG).conf +FILESNAME=$(PROG) +FILESDIR= /etc/system.conf.d + DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS} LDADD+= -lnetdriver -lsys -ltimers diff --git a/drivers/e1000/e1000.conf b/drivers/e1000/e1000.conf new file mode 100644 index 000000000..583f47525 --- /dev/null +++ b/drivers/e1000/e1000.conf @@ -0,0 +1,20 @@ +service e1000 +{ + type net; + descr "Intel PRO/1000 Gigabit"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + pci device 8086/100e; + pci device 8086/107c; + pci device 8086/10cd; + pci device 8086/10d3; + pci device 8086/10de; + pci device 8086/105e; + ipc + SYSTEM pm rs log tty ds vm + pci inet lwip ; +}; + diff --git a/drivers/fxp/Makefile b/drivers/fxp/Makefile index baa7dca9f..643c79390 100644 --- a/drivers/fxp/Makefile +++ b/drivers/fxp/Makefile @@ -2,6 +2,10 @@ PROG= fxp SRCS= fxp.c mii.c +FILES=$(PROG).conf +FILESNAME=$(PROG) +FILESDIR= /etc/system.conf.d + DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS} LDADD+= -lnetdriver -lsys -ltimers diff --git a/drivers/fxp/fxp.conf b/drivers/fxp/fxp.conf new file mode 100644 index 000000000..8f129ff95 --- /dev/null +++ b/drivers/fxp/fxp.conf @@ -0,0 +1,22 @@ + +service fxp +{ + type net; + descr "Intel PRO/100"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + pci device 8086/1031; + pci device 8086/1032; + pci device 8086/103d; + pci device 8086/1064; + pci device 8086/1229; + pci device 8086/2449; + ipc + SYSTEM pm rs log tty ds vm + pci inet lwip amddev + ; +}; + diff --git a/drivers/lance/Makefile b/drivers/lance/Makefile index edadb8d5e..46f8e2ac1 100644 --- a/drivers/lance/Makefile +++ b/drivers/lance/Makefile @@ -2,6 +2,10 @@ PROG= lance SRCS= lance.c +FILES=$(PROG).conf +FILESNAME=$(PROG) +FILESDIR= /etc/system.conf.d + DPADD+= ${LIBNETDRIVER} ${LIBSYS} LDADD+= -lnetdriver -lsys diff --git a/drivers/lance/lance.conf b/drivers/lance/lance.conf new file mode 100644 index 000000000..a25361fc7 --- /dev/null +++ b/drivers/lance/lance.conf @@ -0,0 +1,14 @@ + +service lance +{ + type net; + descr "AMD LANCE (also emulated by VMWare and VirtualBox)"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + pci device 1022/2000; + uid 0; +}; + diff --git a/drivers/rtl8139/Makefile b/drivers/rtl8139/Makefile index 51f54f33e..f694c3544 100644 --- a/drivers/rtl8139/Makefile +++ b/drivers/rtl8139/Makefile @@ -2,6 +2,10 @@ PROG= rtl8139 SRCS= rtl8139.c liveupdate.c +FILES=$(PROG).conf +FILESNAME=$(PROG) +FILESDIR= /etc/system.conf.d + DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS} LDADD+= -lnetdriver -lsys -ltimers diff --git a/drivers/rtl8139/rtl8139.conf b/drivers/rtl8139/rtl8139.conf new file mode 100644 index 000000000..bbab4eb40 --- /dev/null +++ b/drivers/rtl8139/rtl8139.conf @@ -0,0 +1,32 @@ +service rtl8139 +{ + type net; + descr "Realtek 8139 based card"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + pci device 10ec/8139; + pci device 02ac/1012; + pci device 1065/8139; + pci device 1113/1211; + pci device 1186/1300; + pci device 1186/1340; + pci device 11db/1234; + pci device 1259/a117; + pci device 1259/a11e; + pci device 126c/1211; + pci device 13d1/ab06; + pci device 1432/9130; + pci device 14ea/ab06; + pci device 14ea/ab07; + pci device 1500/1360; + pci device 1743/8139; + pci device 4033/1360; + ipc + SYSTEM pm rs log tty ds vm + pci inet lwip amddev + ; +}; + diff --git a/drivers/rtl8169/Makefile b/drivers/rtl8169/Makefile index ab4516ff1..4d238d5fc 100644 --- a/drivers/rtl8169/Makefile +++ b/drivers/rtl8169/Makefile @@ -2,6 +2,10 @@ PROG= rtl8169 SRCS= rtl8169.c +FILES=$(PROG).conf +FILESNAME=$(PROG) +FILESDIR= /etc/system.conf.d + DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS} LDADD+= -lnetdriver -lsys -ltimers diff --git a/drivers/rtl8169/rtl8169.conf b/drivers/rtl8169/rtl8169.conf new file mode 100644 index 000000000..b97a64278 --- /dev/null +++ b/drivers/rtl8169/rtl8169.conf @@ -0,0 +1,25 @@ + +service rtl8169 +{ + type net; + descr "Realtek 8169 based card"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + pci device 10ec/8129; + pci device 10ec/8167; + pci device 10ec/8169; + pci device 10ec/8168; + pci device 1186/4300; + pci device 1259/c107; + pci device 1385/8169; + pci device 16ec/0116; + pci device 1737/1032; + ipc + SYSTEM pm rs log tty ds vm + pci inet lwip amddev + ; +}; + diff --git a/etc/Makefile b/etc/Makefile index 008cb9b8e..693474a71 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -1,6 +1,7 @@ ETC=/etc/ USR=/usr/ USRETC=/usr/etc/ +DEFAULTS=/etc/defaults FILES1=group hostname.file inet.conf motd.install mtab profile \ protocols rc services termcap ttytab utmp rc.cd binary_sizes \ binary_sizes.big binary_sizes.xxl syslog.conf rc.daemons.dist \ @@ -9,6 +10,7 @@ FILES1=group hostname.file inet.conf motd.install mtab profile \ PWFILES=master.passwd FILES3=daily dhcptags.conf rc +DEFAULTFILES=minix.rc.conf USRFILES=Makefile TOOL_PWD_MKDB= pwd_mkdb @@ -23,6 +25,7 @@ install:: installpw # installpw needed to bootstrap pw db @echo "Making hierarchy.." sh mtree.sh mtree/minix.tree @for f in $(FILES3); do if [ -f $(USRETC)/$$f ]; then :; else cp usr/$$f $(USRETC); chmod 755 $(USRETC)/$$f; fi; done + for f in $(DEFAULTFILES); do cp $$f $(DEFAULTS); chmod 644 $(DEFAULTS)/$$f; done @echo "Making devices.." p=`pwd` && cd /dev && sh $$p/../commands/MAKEDEV/MAKEDEV.sh null p=`pwd` && cd /dev && sh $$p/../commands/MAKEDEV/MAKEDEV.sh std 2>/dev/null diff --git a/etc/minix.rc.conf b/etc/minix.rc.conf new file mode 100644 index 000000000..ba40b5fd3 --- /dev/null +++ b/etc/minix.rc.conf @@ -0,0 +1,11 @@ +# Minix-specific rc.conf default values + +# Where to find servers/drivers binaries +PKG_SERVICE_DIR=/usr/pkg/minixservices +SERVICES_DIRS="/usr/sbin $PKG_SERVICE_DIR" + +# Where to find system.conf files and system.conf.d directories +# for servers/drivers +SYSTEM_CONF_SUBDIR=system.conf.d +PKG_SYSTEM_CONF_DIR=/usr/pkg/etc +SYSTEM_CONF_DIRS="/etc $PKG_SYSTEM_CONF_DIR" diff --git a/etc/mtree/minix.tree b/etc/mtree/minix.tree index 3f6f2c1f1..b8a650273 100644 --- a/etc/mtree/minix.tree +++ b/etc/mtree/minix.tree @@ -4,6 +4,7 @@ 755 root operator /dev /dev/mouse -> /dev/kbdaux 755 root operator /etc +755 root operator /etc/defaults 755 root operator /etc/system.conf.d 755 root operator /boot 755 root operator /boot/image diff --git a/etc/rc.conf b/etc/rc.conf index 257ced00d..ef877d543 100644 --- a/etc/rc.conf +++ b/etc/rc.conf @@ -13,6 +13,10 @@ if [ -r /etc/defaults/rc.conf ]; then . /etc/defaults/rc.conf fi +if [ -r /etc/defaults/minix.rc.conf ]; then + . /etc/defaults/minix.rc.conf +fi + # If this is not set to YES, the system will drop into single-user mode. # (Doesn't matter for Minix.) rc_configured=NO diff --git a/etc/system.conf b/etc/system.conf index 4adfc1454..5e147631b 100644 --- a/etc/system.conf +++ b/etc/system.conf @@ -285,66 +285,6 @@ service dpeth uid 0; }; -service lance -{ - system - UMAP # 14 - IRQCTL # 19 - DEVIO # 21 - ; - pci device 1022/2000; - uid 0; -}; - -service rtl8139 -{ - system - UMAP # 14 - IRQCTL # 19 - DEVIO # 21 - ; - pci device 10ec/8139; - pci device 02ac/1012; - pci device 1065/8139; - pci device 1113/1211; - pci device 1186/1300; - pci device 1186/1340; - pci device 11db/1234; - pci device 1259/a117; - pci device 1259/a11e; - pci device 126c/1211; - pci device 13d1/ab06; - pci device 1432/9130; - pci device 14ea/ab06; - pci device 14ea/ab07; - pci device 1500/1360; - pci device 1743/8139; - pci device 4033/1360; - ipc - SYSTEM pm rs log tty ds vm - pci inet lwip amddev - ; -}; - -service fxp -{ - system - UMAP # 14 - IRQCTL # 19 - DEVIO # 21 - ; - pci device 8086/1031; - pci device 8086/1032; - pci device 8086/103d; - pci device 8086/1064; - pci device 8086/1229; - pci device 8086/2449; - ipc - SYSTEM pm rs log tty ds vm - pci inet lwip amddev - ; -}; - service inet { uid 0; @@ -552,28 +492,6 @@ service osscore uid 0; }; -service rtl8169 -{ - system - UMAP # 14 - IRQCTL # 19 - DEVIO # 21 - ; - pci device 10ec/8129; - pci device 10ec/8167; - pci device 10ec/8169; - pci device 10ec/8168; - pci device 1186/4300; - pci device 1259/c107; - pci device 1385/8169; - pci device 16ec/0116; - pci device 1737/1032; - ipc - SYSTEM pm rs log tty ds vm - pci inet lwip amddev - ; -}; - service filter { ipc @@ -587,51 +505,6 @@ service filter ; }; -service e1000 -{ - system - UMAP # 14 - IRQCTL # 19 - DEVIO # 21 - ; - pci device 8086/100e; - pci device 8086/107c; - pci device 8086/10cd; - pci device 8086/10d3; - pci device 8086/10de; - pci device 8086/105e; - ipc - SYSTEM pm rs log tty ds vm - pci inet lwip ; -}; - -service atl2 -{ - system - UMAP # 14 - IRQCTL # 19 - ; - pci device 1969/2048; - ipc - SYSTEM pm rs tty ds vm - pci inet lwip - ; -}; - -service dec21140A -{ - system - UMAP # 14 - IRQCTL # 19 - DEVIO # 21 - ; - pci device 1011/0009; - ipc - SYSTEM pm rs log tty ds vm - pci inet lwip - ; -}; - service hello { system diff --git a/etc/usr/rc b/etc/usr/rc index dafd371cb..a985e2287 100644 --- a/etc/usr/rc +++ b/etc/usr/rc @@ -3,6 +3,14 @@ RANDOM_FILE=/usr/adm/random.dat LOCAL_FILE=/usr/etc/rc.local +# Get $SERVICES_DIRS +. /etc/rc.conf + +# Directories to find services in +if [ ! "$SERVICES_DIRS" ] +then SERVICES_DIRS=/usr/sbin +fi + case "$#:$1" in 1:start|1:stop|1:down) action=$1 @@ -69,8 +77,18 @@ up() if disabled $service; then return; fi # Service is not disabled. Try to bring it up. - echo -n " $service" - service $opt up /usr/sbin/$service "$@" + found="" + for dir in $SERVICES_DIRS + do bin=$dir/$service + if [ -x $bin -a -z "$found" ] + then service $opt up $bin "$@" + echo -n " $service" + found=yes + fi + done + if [ -z "$found" ] + then echo " ($service not found in $SERVICES_DIRS)" + fi } get_eth_labels() { diff --git a/include/paths.h b/include/paths.h index 6ee679cdb..16985c9a6 100644 --- a/include/paths.h +++ b/include/paths.h @@ -63,6 +63,7 @@ #define _PATH_SERVICE "/bin/service" #define _PATH_SYSTEM_CONF "/etc/system.conf" #define _PATH_SYSTEM_CONF_DIR "/etc/system.conf.d" +#define _PATH_SYSTEM_CONF_PKG_DIR "/usr/pkg/etc/system.conf.d" /* Provide trailing slash, since mostly used for building pathnames. */ #define _PATH_DEV "/dev/" diff --git a/nbsd_include/minix/paths.h b/nbsd_include/minix/paths.h index 9d3cead17..65ea4325b 100644 --- a/nbsd_include/minix/paths.h +++ b/nbsd_include/minix/paths.h @@ -6,6 +6,7 @@ #define _PATH_SYSTEM_CONF "/etc/system.conf" #define _PATH_SYSTEM_CONF_DIR "/etc/system.conf.d" +#define _PATH_SYSTEM_CONF_PKG_DIR "/usr/pkg/etc/system.conf.d" #define _PATH_DHCPCONF "/etc/dhcp.conf" #define _PATH_DHCPPID "/usr/run/dhcpd.pid" -- 2.44.0