1064 lines
23 KiB
Bash
Executable File
1064 lines
23 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Kernel config script for OS/161.
|
|
#
|
|
# Usage: ./config conf-name
|
|
#
|
|
# WARNING! IF YOU JUST RUN "config" INSTEAD OF "./config" YOU WILL
|
|
# PROBABLY GET THE HOST SYSTEM'S KERNEL CONFIG INSTEAD OF THIS ONE,
|
|
# WHICH WILL CAUSE WEIRD THINGS TO HAPPEN. DON'T DO IT.
|
|
#
|
|
#
|
|
# Recognized directives:
|
|
#
|
|
# file <filename> use source file
|
|
# debug turn on debug info
|
|
# defoption <sym> define an option
|
|
# optfile <sym> <file> if option <sym> is enabled, use file <file>
|
|
# optofffile <sym> <file> if option <sym> is disabled, use file <file>
|
|
# defdevice <dev> <file> define a device
|
|
# defattach <dev> <bus> <file>
|
|
# define an attachment for a device to a bus
|
|
# pseudoattach <dev> define a pseudo-attachment for a device
|
|
#
|
|
# options <sym> enable an option
|
|
# device <dev> [at <bus>] enable a particular device [on a particular bus]
|
|
#
|
|
# include <filename> get additional directives from another file
|
|
#
|
|
# Filenames are relative to the top of the kernel tree.
|
|
#
|
|
# The comment character is '#'.
|
|
#
|
|
# The idea is that the first group of directives is used to set up a
|
|
# static description of all possible configurations for each supported
|
|
# architecture. Then a kernel config file uses the second group of
|
|
# directives to specify a particular configuration. Then this script
|
|
# is used to first check that the configuration is one of the possible
|
|
# ones, and then to set up the compile directory, makefiles, and
|
|
# associated material necessary to actually build that configuration.
|
|
#
|
|
# Further documentation is at the top of conf.kern.
|
|
#
|
|
|
|
|
|
#
|
|
# Make sure we're in the right place.
|
|
#
|
|
if [ ! -d ../dev ]; then
|
|
echo "$0: Run me from src/kern/conf"
|
|
exit 1
|
|
fi
|
|
|
|
########################################
|
|
#
|
|
# 1. Get configuration name and config file.
|
|
#
|
|
|
|
CONFNAME=$1
|
|
if [ "x$CONFNAME" = x ]; then
|
|
echo "Usage: $0 CONFIG-NAME"
|
|
exit 1
|
|
fi
|
|
|
|
FOO=`echo $CONFNAME | tr -d 'a-zA-Z0-9_-'`
|
|
if [ "x$FOO" != x ]; then
|
|
echo "Illegal configuration name $CONFNAME"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f $CONFNAME ]; then
|
|
echo "$0: $CONFNAME not found"
|
|
exit 1
|
|
fi
|
|
echo "Configuration $CONFNAME"
|
|
|
|
COMPILEDIR="../compile/$CONFNAME"
|
|
|
|
########################################
|
|
#
|
|
# 2. Process includes.
|
|
# Also strip comments.
|
|
# Simultaneously, do a basic syntax check.
|
|
#
|
|
# For an introduction to awk, see
|
|
# http://www.hcs.harvard.edu/~dholland/computers/awk.html
|
|
#
|
|
|
|
CONFTMP=.conftmp
|
|
|
|
rm -f $CONFTMP
|
|
|
|
echo "$CONFNAME" $CONFTMP | awk '
|
|
BEGIN {
|
|
#
|
|
# Initialize list of directives and required numbers of words for each.
|
|
#
|
|
nfields["include"] = 2;
|
|
nfields["file"] = 2;
|
|
nfields["debug"] = 1;
|
|
nfields["defoption"] = 2;
|
|
nfields["optfile"] = 3;
|
|
nfields["optofffile"] = 3;
|
|
nfields["defdevice"] = 3;
|
|
nfields["defattach"] = 4;
|
|
nfields["pseudoattach"] = 2;
|
|
nfields["options"] = 2;
|
|
nfields["device"] = 4; # actually 2 or 4, handled specially
|
|
#
|
|
# Directives that can be made machine-dependent with "machine"
|
|
# or "platform".
|
|
#
|
|
okmd["file"] = 1;
|
|
okmd["optfile"] = 1;
|
|
okmd["optofffile"] = 1;
|
|
}
|
|
|
|
function doinclude(file, lineno) {
|
|
#
|
|
# Include a file.
|
|
#
|
|
# lineno is a local.
|
|
#
|
|
# Read lines and hand them off recursively to processline().
|
|
#
|
|
lineno = 1;
|
|
while (getline < file) {
|
|
if (ERRNO) {
|
|
printf "%s: %s\n", file, ERRNO;
|
|
exit(1);
|
|
}
|
|
processline(file, lineno);
|
|
lineno++;
|
|
}
|
|
}
|
|
|
|
function processline(filename, lineno) {
|
|
#
|
|
# Handle a single config line.
|
|
#
|
|
|
|
# Strip comments.
|
|
sub("#.*", "", $0);
|
|
|
|
# Ignore blank lines.
|
|
if (NF==0) return;
|
|
|
|
direct = $1;
|
|
foundfields = NF;
|
|
|
|
if (direct == "machine" && NF > 2 && okmd[$3]) {
|
|
# machine mips file ...
|
|
direct = $3;
|
|
foundfields -= 2;
|
|
}
|
|
else if (direct == "platform" && NF > 2 && okmd[$3]) {
|
|
# platform sys161 file ...
|
|
direct = $3;
|
|
foundfields -= 2;
|
|
}
|
|
|
|
# Syntax check: reject unknown directives
|
|
if (!nfields[direct]) {
|
|
printf "%s: %d: Unknown directive %s\n", filename, lineno, direct;
|
|
exit(1);
|
|
}
|
|
|
|
# Syntax check: require correct # of args.
|
|
if (direct=="device") {
|
|
# special case - device directive can have 2 or 4 words
|
|
if ((NF!=2 && NF!=4) || (NF==4 && $3!="at")) {
|
|
msg = sprintf("%s: Invalid arguments", direct);
|
|
printf "%s: %d: %s\n", filename, lineno, msg;
|
|
exit(1);
|
|
}
|
|
}
|
|
else if (nfields[direct]!=foundfields) {
|
|
printf "%s: %d: %s: Invalid arguments\n", filename, lineno, direct;
|
|
exit(1);
|
|
}
|
|
|
|
# Now actually process the directives we need at this stage - which
|
|
# is only "include". Handle includes.
|
|
|
|
if (direct == "include") {
|
|
doinclude("../" $2);
|
|
}
|
|
else {
|
|
print >> outfile;
|
|
}
|
|
}
|
|
|
|
#
|
|
# Code called for lines input on stdin.
|
|
# There is only one - the one generated above with echo, which
|
|
# gives us the names of the input and output files to use.
|
|
#
|
|
{
|
|
outfile = $2;
|
|
doinclude($1);
|
|
}
|
|
' || exit 1
|
|
|
|
########################################
|
|
#
|
|
# 3. Create compile dir.
|
|
#
|
|
|
|
if [ ! -d "$COMPILEDIR" ]; then
|
|
mkdir -p $COMPILEDIR
|
|
fi
|
|
|
|
echo -n 'Generating files...'
|
|
|
|
########################################
|
|
#
|
|
# 4. Process device attachments into $CONFTMP.attach.
|
|
# Also add device/attachment files to $CONFTMP.files.
|
|
#
|
|
|
|
rm -f $CONFTMP.files
|
|
rm -f $CONFTMP.attach
|
|
|
|
awk < $CONFTMP '
|
|
|
|
#
|
|
# Function to grab the "0" off "le0" or the "*" off "wd*".
|
|
#
|
|
function getunit(invalmsg, d, u, tmp) {
|
|
u = d;
|
|
sub("^[a-zA-Z_]*", "", u);
|
|
|
|
if (u!="*") {
|
|
tmp = u;
|
|
sub("[0-9]*", "", tmp);
|
|
if (tmp!="") {
|
|
printf "\n%s: Invalid device/unit specification\n", invalmsg;
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
return u;
|
|
}
|
|
|
|
#
|
|
# Function to grab the "le" off "le0" or the "wd" off "wd*".
|
|
#
|
|
function getbase(invalmsg, d, base) {
|
|
base = d;
|
|
sub("[\\*0-9]*$", "", base);
|
|
|
|
if (!use[base]) {
|
|
printf "\n%s: No such device\n", invalmsg;
|
|
exit(1);
|
|
}
|
|
|
|
return base;
|
|
}
|
|
|
|
#
|
|
# Routine invoked for "defdevice" directive lines.
|
|
#
|
|
$1=="defdevice" {
|
|
dev = $2;
|
|
file = $3;
|
|
|
|
# Check for illegal characters in device name
|
|
# (must be legal C symbol, and at this point must not have unit number)
|
|
tmp = dev;
|
|
sub("[a-zA-Z_]*", "", tmp);
|
|
if (tmp!="") {
|
|
printf "\ndefdevice %s: Illegal device name\n", dev;
|
|
exit(1);
|
|
}
|
|
|
|
# Device must not have been already defined.
|
|
if (use[dev]) {
|
|
printf "\ndefdevice %s: %s already exists\n", dev, dev;
|
|
exit(1);
|
|
}
|
|
|
|
# Note that it exists, but is not in use, and remember the
|
|
# source file for later.
|
|
use[dev] = "no";
|
|
files[dev] = file;
|
|
}
|
|
|
|
#
|
|
# Routine called for "defattach" directive lines.
|
|
#
|
|
$1=="defattach" {
|
|
dev = $2;
|
|
bus = $3;
|
|
file = $4;
|
|
|
|
# Even though we do not use basebus, busunit, or devunit,
|
|
# call the routines to compute them, because they check the
|
|
# syntax.
|
|
|
|
devmsg = "defattach: device " dev;
|
|
devunit = getunit(devmsg, dev);
|
|
basedev = getbase(devmsg, dev);
|
|
|
|
busmsg = "defattach: bus " bus;
|
|
busunit = getunit(busmsg, bus);
|
|
basebus = getbase(busmsg, bus);
|
|
|
|
if (pseudo[basedev]) {
|
|
printf "\n%s: Already declared pseudoattach\n", devmsg;
|
|
exit(1);
|
|
}
|
|
|
|
# The attachment is the pair of bus and device.
|
|
# We remember the specific names, including the unit numbers.
|
|
# This is because "le* at sbus*" is different from "le0 at sbus0"
|
|
# - the former allows le0 to be at sbus1, allows le1, etc.
|
|
|
|
attachment = bus "." dev;
|
|
attach[attachment] = "no";
|
|
files[attachment] = file;
|
|
|
|
# Remember that attachments are defined for this device. If
|
|
# attachments are defined, when the device is turned on later
|
|
# an attachment must be specified.
|
|
attachable[basedev] = 1;
|
|
}
|
|
|
|
#
|
|
# Routine called for "pseudoattach" directive lines.
|
|
#
|
|
$1=="pseudoattach" {
|
|
dev = $2;
|
|
|
|
devmsg = "pseudoattach: device " dev;
|
|
devunit = getunit(devmsg, dev);
|
|
basedev = getbase(devmsg, dev);
|
|
|
|
if (attachable[basedev]) {
|
|
printf "\n%s: Attachments already declared\n", devmsg;
|
|
exit(1);
|
|
}
|
|
|
|
# Remember that this device is a pseudo-device.
|
|
pseudo[basedev] = 1;
|
|
}
|
|
|
|
#
|
|
# Helper function for the "device" code.
|
|
#
|
|
function tryattach(combo) {
|
|
if (!attachok && attach[combo]) {
|
|
# This attachment is defined. Note to compile it in, and report
|
|
# success.
|
|
attach[combo] = "yes";
|
|
attachok = 1;
|
|
}
|
|
}
|
|
|
|
#
|
|
# Routine called for "device" directive lines.
|
|
#
|
|
$1=="device" {
|
|
dev = $2;
|
|
if (NF==4) {
|
|
devmsg = "device: " dev " at " $4;
|
|
}
|
|
else {
|
|
devmsg = "device: device " dev;
|
|
}
|
|
devunit = getunit(devmsg, dev);
|
|
basedev = getbase(devmsg, dev);
|
|
gendev = basedev "*";
|
|
|
|
if (NF==4) {
|
|
#
|
|
# The longer form, with an attachment ("bus").
|
|
#
|
|
bus = $4;
|
|
busmsg = "device: " dev " at " bus ": " bus;
|
|
busunit = getunit(busmsg, bus);
|
|
basebus = getbase(busmsg, bus);
|
|
genbus = basebus "*";
|
|
|
|
if (use[basebus]!="yes") {
|
|
printf "\ndevice: bus %s: Bus device is not enabled\n", bus;
|
|
exit(1);
|
|
}
|
|
|
|
# If the line was "le0 at sbus0", we try to attach it using
|
|
# the following attachments:
|
|
# First, the exact thing that was requested:
|
|
# sbus0.le0 (le0 at sbus0)
|
|
# Second, for any such device on that bus:
|
|
# sbus*.le0 (le0 at sbus*)
|
|
# Third, for that device on any such bus:
|
|
# sbus0.le* (le* at sbus0)
|
|
# Fourth, for any such device on any such bus:
|
|
# sbus*.le* (le* at sbus*)
|
|
#
|
|
# If the line was "le* at sbus0", some of these will be
|
|
# redundant, but that is ok.
|
|
|
|
attachok = 0;
|
|
tryattach(bus "." dev);
|
|
tryattach(bus "." gendev);
|
|
tryattach(genbus "." dev);
|
|
tryattach(genbus "." gendev);
|
|
if (!attachok) {
|
|
# No matching attachment found.
|
|
printf "\ndevice: %s at %s: Undefined attachment\n", dev, bus;
|
|
exit(1);
|
|
}
|
|
|
|
devattach = sprintf("%s %s", basedev, devunit);
|
|
baseattach = sprintf("%s %s", basebus, busunit);
|
|
printf "attach %s at %s\n", devattach, baseattach >> attachfile;
|
|
}
|
|
else {
|
|
# No bus specified to attach the device to (really, to find the
|
|
# device attached on.) This is only legal if no attachments
|
|
# at all were defined for the device, which is the case if the
|
|
# device is in fact not attached to anything else (like the main
|
|
# system bus, or a device like /dev/null that has no hardware.)
|
|
|
|
|
|
# The opposite check to this is not required in the
|
|
# preceding section because no attachment can be found if
|
|
# attachable[basedev] is false.
|
|
|
|
if (attachable[basedev]) {
|
|
printf "\ndevice %s: attachment required\n", dev;
|
|
exit(1);
|
|
}
|
|
|
|
if (pseudo[basedev]) {
|
|
if (devunit=="*") {
|
|
printf "\n%s: May not use wildcard units here\n", devmsg;
|
|
exit(1);
|
|
}
|
|
printf "pseudo %s %s\n", basedev, devunit >> attachfile;
|
|
}
|
|
else {
|
|
printf "noattach %s\n", basedev >> attachfile;
|
|
}
|
|
}
|
|
|
|
use[basedev] = "yes";
|
|
}
|
|
|
|
#
|
|
# Routine invoked when we have seen all the input.
|
|
#
|
|
END {
|
|
# Print out the source filenames for the devices and attachments
|
|
# we are using.
|
|
|
|
for (dev in use) {
|
|
if (use[dev]=="yes") {
|
|
printf "* * %s\n", files[dev] >> filelistfile;
|
|
}
|
|
}
|
|
for (att in attach) {
|
|
if (attach[att]=="yes") {
|
|
printf "* * %s\n", files[att] >> filelistfile;
|
|
}
|
|
}
|
|
}
|
|
|
|
' "attachfile=$CONFTMP.attach" "filelistfile=$CONFTMP.files" || exit 1
|
|
|
|
########################################
|
|
#
|
|
# 5. Process options.
|
|
#
|
|
|
|
awk < $CONFTMP '
|
|
|
|
#
|
|
# Routine for a defoption line.
|
|
#
|
|
$1=="defoption" {
|
|
opt = $2;
|
|
options[opt] = "no";
|
|
}
|
|
|
|
#
|
|
# Routine for an optfile line.
|
|
#
|
|
$1=="optfile" || (($1=="machine" || $1=="platform") && $3=="optfile") {
|
|
if ($1 == "optfile") {
|
|
opt = $2;
|
|
file = $3;
|
|
platform = "*";
|
|
machine = "*";
|
|
}
|
|
else {
|
|
if ($1=="machine") {
|
|
platform = "*";
|
|
machine = $2;
|
|
}
|
|
else {
|
|
platform = $2;
|
|
machine = "*";
|
|
}
|
|
opt = $4;
|
|
file = $5;
|
|
}
|
|
|
|
if (!options[opt]) {
|
|
printf "\noptfile %s %s: No such option %s\n", opt, file, opt;
|
|
exit(1);
|
|
}
|
|
|
|
controllers[file] = opt;
|
|
platforms[file] = platform;
|
|
machines[file] = machine;
|
|
}
|
|
|
|
#
|
|
# Routine for an optofffile line.
|
|
#
|
|
$1=="optofffile" || (($1=="machine" || $1=="platform") &&$3=="optofffile"){
|
|
if ($1 == "optofffile") {
|
|
opt = $2;
|
|
file = $3;
|
|
platform = "*";
|
|
machine = "*";
|
|
}
|
|
else {
|
|
if ($1=="machine") {
|
|
platform = "*";
|
|
machine = $2;
|
|
}
|
|
else {
|
|
platform = $2;
|
|
machine = "*";
|
|
}
|
|
opt = $4;
|
|
file = $5;
|
|
}
|
|
|
|
if (!options[opt]) {
|
|
printf "\noptofffile %s %s: No such option %s\n", opt, file, opt;
|
|
exit(1);
|
|
}
|
|
|
|
offcontrollers[file] = opt;
|
|
platforms[file] = platform;
|
|
machines[file] = machine;
|
|
}
|
|
|
|
#
|
|
# Routine for an options line.
|
|
#
|
|
$1=="options" {
|
|
opt = $2;
|
|
|
|
if (!options[$2]) {
|
|
printf "\noptions %s: No such option\n", opt;
|
|
exit(1);
|
|
}
|
|
|
|
options[$2] = "yes";
|
|
}
|
|
|
|
#
|
|
# Routine invoked when we have seen everything.
|
|
#
|
|
END {
|
|
#
|
|
# First, add any files to the list of sources we are building.
|
|
#
|
|
for (file in controllers) {
|
|
if (options[controllers[file]]=="yes") {
|
|
line = sprintf("%s %s %s",
|
|
platforms[file], machines[file], file);
|
|
printf "%s\n", line >> filelistfile;
|
|
}
|
|
}
|
|
for (file in offcontrollers) {
|
|
if (options[offcontrollers[file]]=="no") {
|
|
line = sprintf("%s %s %s",
|
|
platforms[file], machines[file], file);
|
|
printf "%s\n", line >> filelistfile;
|
|
}
|
|
}
|
|
close(filelistfile);
|
|
|
|
#
|
|
# Now, generate the .h file for every option
|
|
# (both the ones that are on and the ones that are off)
|
|
#
|
|
for (opt in options) {
|
|
realfile = compiledir "/opt-" opt ".h";
|
|
file = realfile ".new";
|
|
sym = toupper(opt);
|
|
printf "/* Automatically generated; do not edit */\n" > file;
|
|
printf "#ifndef _OPT_%s_H_\n", sym >> file;
|
|
printf "#define _OPT_%s_H_\n", sym >> file;
|
|
val = options[opt]=="yes" ? 1 : 0;
|
|
printf "#define OPT_%s %d\n", sym, val >> file;
|
|
printf "#endif /* _OPT_%s_H_ */\n", sym >> file;
|
|
close(file);
|
|
}
|
|
}
|
|
|
|
' "compiledir=$COMPILEDIR" "filelistfile=$CONFTMP.files" || exit 1
|
|
|
|
# Avoid changing the actual headers if they aren't different, so as to
|
|
# reduce unnecessary recompiles.
|
|
|
|
(
|
|
cd $COMPILEDIR
|
|
for NF in opt-*.h.new; do
|
|
OF=`echo $NF | sed 's/\.new$//'`
|
|
if diff $OF $NF >/dev/null 2>&1; then
|
|
rm -f $NF # unchanged
|
|
else
|
|
mv -f $NF $OF # it changed
|
|
fi
|
|
echo -n " $OF"
|
|
done
|
|
)
|
|
|
|
########################################
|
|
#
|
|
# 6. Add in the unconditional files.
|
|
#
|
|
|
|
awk < $CONFTMP '
|
|
$1=="file" {
|
|
printf "* * %s\n", $2 >> filelistfile;
|
|
}
|
|
$1=="machine" && $3=="file" {
|
|
printf "* %s %s\n", $2, $4 >> filelistfile;
|
|
}
|
|
$1=="platform" && $3=="file" {
|
|
printf "%s * %s\n", $2, $4 >> filelistfile;
|
|
}
|
|
|
|
' "filelistfile=$CONFTMP.files" || exit 1
|
|
|
|
#
|
|
# autoconf.c (which we generate further down) is always compiled in but
|
|
# is not in the list yet. Note that the path to it is where we are about
|
|
# to put it: it lives in the build directory, because it's part of a
|
|
# particular build.
|
|
#
|
|
echo "* * compile/$CONFNAME/autoconf.c" >> $CONFTMP.files
|
|
|
|
########################################
|
|
#
|
|
# 7. We now have the compile file list.
|
|
# Generate files.mk.
|
|
#
|
|
|
|
#
|
|
# Validate list first.
|
|
#
|
|
# We allow C++ files, because the makefile rules we generate are
|
|
# sufficient to compile them. However, some low-level kernel hacking
|
|
# will be needed to actually use C++ in OS/161.
|
|
#
|
|
|
|
awk < $CONFTMP.files '
|
|
/\.cc$/ { next; }
|
|
/\.cpp$/ { next; }
|
|
/\.C$/ { next; }
|
|
/\.c$/ { next; }
|
|
#/\.l$/ { next; } # will require some makefile hacking to make work
|
|
#/\.y$/ { next; } # will require some makefile hacking to make work
|
|
/\.S$/ { next; }
|
|
/\.o$/ { next; }
|
|
{
|
|
printf "\n%s: Unrecognized source file type\n", $1;
|
|
exit(1);
|
|
}
|
|
' || exit 1;
|
|
|
|
#
|
|
# Check for files with the same basename.
|
|
#
|
|
awk < $CONFTMP.files '
|
|
{
|
|
path = $3;
|
|
base = path;
|
|
sub("^.*/", "", base);
|
|
sub("\\.[^\\.]*$", "", base);
|
|
if (seen[base]) {
|
|
msg = sprintf("%s: object file name %s.o conflicts with %s",
|
|
path, base, seen[base]);
|
|
printf "\n%s\n", msg;
|
|
failed = 1;
|
|
}
|
|
seen[base] = path;
|
|
}
|
|
END {
|
|
if (failed) {
|
|
exit(1);
|
|
}
|
|
}
|
|
' || exit 1
|
|
|
|
#
|
|
# Do it.
|
|
# Generate a make rule for each file.
|
|
#
|
|
|
|
sort < $CONFTMP.files | awk '
|
|
BEGIN {
|
|
printf "# Automatically generated by config; do not edit\n";
|
|
}
|
|
|
|
{
|
|
platform = $1;
|
|
machine = $2;
|
|
file = $3;
|
|
|
|
# get basename
|
|
basename = file;
|
|
sub(".*/", "", basename);
|
|
|
|
# get extension
|
|
ext = basename;
|
|
sub(".*\\.", "", ext);
|
|
sub("\\.[^\\.]*$", "", basename);
|
|
|
|
if (file ~ "^\\.\\./") {
|
|
sub("^...", "", file);
|
|
path = "$(TOP)/" file;
|
|
}
|
|
else {
|
|
path = "$(KTOP)/" file;
|
|
}
|
|
|
|
#
|
|
# For now a file cannot be both platform-dependent and
|
|
# machine-dependent, so this sequence of tests is enough.
|
|
#
|
|
if (platform != "*") {
|
|
printf "SRCS.PLATFORM.%s+=%s\n", platform, path;
|
|
}
|
|
else if (machine != "*") {
|
|
printf "SRCS.MACHINE.%s+=%s\n", machine, path;
|
|
}
|
|
else {
|
|
printf "SRCS+=%s\n", path;
|
|
}
|
|
}
|
|
' > $COMPILEDIR/files.mk
|
|
|
|
rm -f $CONFTMP.files
|
|
|
|
echo -n ' files.mk'
|
|
|
|
########################################
|
|
#
|
|
# 8. (reserved)
|
|
#
|
|
|
|
########################################
|
|
#
|
|
# 9. Generate Makefile
|
|
#
|
|
|
|
(
|
|
echo "# Automatically generated by config; do not edit."
|
|
echo "#"
|
|
echo
|
|
echo '# Top of the kernel tree'
|
|
echo 'KTOP=../..'
|
|
echo '# Top of the whole tree'
|
|
echo 'TOP=$(KTOP)/..'
|
|
|
|
echo '# Debug vs. optimize'
|
|
awk < $CONFTMP '
|
|
# Default: optimize.
|
|
BEGIN { debugflags="-O2"; }
|
|
$1=="debug" {
|
|
debugflags="-g";
|
|
}
|
|
|
|
END {
|
|
printf "KDEBUG=%s\n", debugflags;
|
|
}
|
|
'
|
|
echo '# Name of the kernel config file'
|
|
echo "CONFNAME=$CONFNAME"
|
|
echo
|
|
echo '.include "$(TOP)/mk/os161.config.mk"'
|
|
echo '.include "files.mk"'
|
|
echo '.include "$(TOP)/mk/os161.kernel.mk"'
|
|
|
|
) > $COMPILEDIR/Makefile || exit 1
|
|
|
|
echo -n ' Makefile'
|
|
|
|
########################################
|
|
#
|
|
# 10. (reserved)
|
|
#
|
|
|
|
########################################
|
|
#
|
|
# 11. Process attachment list.
|
|
# Generate autoconf.[ch].
|
|
#
|
|
|
|
ACHREAL=$COMPILEDIR/autoconf.h
|
|
ACH=$COMPILEDIR/autoconf.h.new
|
|
ACC=$COMPILEDIR/autoconf.c
|
|
|
|
echo '/* Automatically generated; do not edit */' > $ACH
|
|
echo '/* Automatically generated; do not edit */' > $ACC
|
|
|
|
echo '#ifndef _AUTOCONF_H_' >> $ACH
|
|
echo '#define _AUTOCONF_H_' >> $ACH
|
|
|
|
#
|
|
# first, declare struct foo_softc for all devices foo.
|
|
#
|
|
|
|
echo >> $ACH
|
|
awk < $CONFTMP.attach '{ printf "struct %s_softc;\n", $2 }' >> $ACH
|
|
|
|
#
|
|
# second, declare the autoconf_foo functions for unattached devices.
|
|
#
|
|
# The autoconf_foo functions for attached devices are file-static
|
|
# in autoconf.c.
|
|
#
|
|
|
|
echo >> $ACH
|
|
awk < $CONFTMP.attach '$1=="noattach" { print $2 }' | sort -u | awk '
|
|
{
|
|
printf "void autoconf_%s(struct %s_softc *dev, int unit);\n", $1, $1;
|
|
}
|
|
' >> $ACH
|
|
|
|
#
|
|
# third, declare the attach functions.
|
|
#
|
|
|
|
echo >> $ACH
|
|
awk < $CONFTMP.attach '
|
|
$1=="attach" {
|
|
dev = $2;
|
|
bus = $5;
|
|
f = sprintf("struct %s_softc *attach_%s_to_%s", dev, dev, bus);
|
|
printf "%s(int devunit, struct %s_softc *bus);\n", f, bus;
|
|
}
|
|
$1=="pseudo" {
|
|
dev = $2;
|
|
printf "struct %s_softc *pseudoattach_%s(int devunit);\n", dev, dev;
|
|
}
|
|
' >> $ACH
|
|
|
|
#
|
|
# fourth, declare the config functions.
|
|
#
|
|
|
|
echo >> $ACH
|
|
awk < $CONFTMP.attach '
|
|
$1=="attach" {
|
|
dev = $2;
|
|
printf "int config_%s(struct %s_softc *dev, int unit);\n", dev, dev;
|
|
}
|
|
' >> $ACH
|
|
|
|
#
|
|
# Declare pseudoconfig()
|
|
#
|
|
echo >> $ACH
|
|
echo 'void pseudoconfig(void);' >> $ACH
|
|
echo >> $ACH
|
|
|
|
#
|
|
# Done with the header file.
|
|
#
|
|
echo '#endif /* _AUTOCONF_H_ */' >> $ACH
|
|
|
|
#
|
|
# Avoid changing the actual autoconf.h if it's not different, so as to
|
|
# reduce unnecessary recompiles.
|
|
#
|
|
|
|
if diff $ACHREAL $ACH >/dev/null 2>&1; then
|
|
rm -f $ACH # unchanged
|
|
else
|
|
mv -f $ACH $ACHREAL # it changed
|
|
fi
|
|
|
|
echo -n ' autoconf.h'
|
|
|
|
#
|
|
# now, autoconf.c
|
|
#
|
|
|
|
echo '#include <types.h>' >> $ACC
|
|
echo '#include <lib.h>' >> $ACC
|
|
echo '#include "autoconf.h"' >> $ACC
|
|
|
|
#
|
|
# first, declare the static autoconf_foo functions and the nextunit_foo vars
|
|
#
|
|
echo >> $ACC
|
|
awk < $CONFTMP.attach '$1=="attach" || $1=="pseudo" { print $2 }' | sort -u |\
|
|
awk '
|
|
{
|
|
printf "static void autoconf_%s(struct %s_softc *, int);\n", $1, $1;
|
|
}
|
|
' >> $ACC
|
|
awk < $CONFTMP.attach '$1=="attach" { print $2 }' | sort -u | awk '
|
|
{
|
|
printf "static int nextunit_%s;\n", $1;
|
|
}
|
|
' >> $ACC
|
|
echo >> $ACC
|
|
|
|
#
|
|
# Now generate the tryattach_ functions.
|
|
#
|
|
|
|
awk < $CONFTMP.attach '
|
|
$1=="attach" {
|
|
dev = $2;
|
|
bus = $5;
|
|
printf "static\n";
|
|
printf "int\n";
|
|
printf "tryattach_%s_to_%s", dev, bus;
|
|
printf "(int devunit, struct %s_softc *bus, int busunit)\n", bus;
|
|
printf "{\n";
|
|
printf "\tstruct %s_softc *dev;\n", dev;
|
|
printf "\tint result;\n", dev;
|
|
printf "\n";
|
|
printf "\tdev = attach_%s_to_%s(devunit, bus);\n", dev, bus;
|
|
printf "\tif (dev==NULL) {\n";
|
|
printf "\t\treturn -1;\n";
|
|
printf "\t}\n";
|
|
printf "\tkprintf(\"%s%%d at %s%%d\", devunit, busunit);\n", dev, bus;
|
|
printf "\tresult = config_%s(dev, devunit);\n", dev;
|
|
printf "\tif (result != 0) {\n";
|
|
printf "\t\tkprintf(\": %%s\\n\", strerror(result));\n";
|
|
# Note: we leak the device softc instead of trying
|
|
# to clean it up.
|
|
printf "\t\t/* should really clean up dev */\n";
|
|
printf "\t\treturn result;\n";
|
|
printf "\t}\n";
|
|
printf "\tkprintf(\"\\n\");\n";
|
|
printf "\tnextunit_%s = devunit+1;\n", dev;
|
|
printf "\tautoconf_%s(dev, devunit);\n", dev;
|
|
printf "\treturn 0;\n";
|
|
printf "}\n";
|
|
printf "\n";
|
|
}
|
|
' >> $ACC
|
|
echo >> $ACC
|
|
|
|
|
|
#
|
|
# Now comes the tricky part, actually writing those autoconf
|
|
# functions. We need one for every device. In each one, there needs
|
|
# to be a probe section for each line in $CONFTMP.attach in which that
|
|
# device appears on the *right hand* (bus) side.
|
|
#
|
|
|
|
awk < $CONFTMP.attach '
|
|
BEGIN { nlines=0; npseudo=0; }
|
|
$1=="attach" {
|
|
devs[nlines] = $2;
|
|
devunits[nlines] = $3;
|
|
buses[nlines] = $5;
|
|
busunits[nlines] = $6;
|
|
alldevs[$2] = 1;
|
|
nlines++;
|
|
}
|
|
$1=="noattach" {
|
|
alldevs[$2] = 0;
|
|
}
|
|
$1=="pseudo" {
|
|
alldevs[$2] = 0;
|
|
pseudodevs[npseudo] = $2;
|
|
pseudounits[npseudo] = $3;
|
|
npseudo++;
|
|
}
|
|
|
|
function genprobe(dev, devunit, bus, busunit) {
|
|
|
|
tryfunc = sprintf("tryattach_%s_to_%s", dev, bus);
|
|
|
|
if (busunit!="*") {
|
|
printf "\tif (busunit==%d) {\n", busunit;
|
|
}
|
|
else {
|
|
printf "\t{\n";
|
|
}
|
|
|
|
if (devunit!="*") {
|
|
printf "\t\tif (nextunit_%s <= %d) {\n", dev, devunit;
|
|
printf "\t\t\t%s(%d, bus, busunit);\n", tryfunc, devunit;
|
|
printf "\t\t}\n";
|
|
}
|
|
else {
|
|
printf "\t\tint result, devunit=nextunit_%s;\n", dev;
|
|
printf "\t\tdo {\n";
|
|
printf "\t\t\tresult = %s(devunit, bus, busunit);\n", tryfunc;
|
|
printf "\t\t\tdevunit++;\n";
|
|
printf "\t\t} while (result==0);\n";
|
|
}
|
|
|
|
printf "\t}\n";
|
|
}
|
|
|
|
END {
|
|
for (bus in alldevs) {
|
|
softc = sprintf("struct %s_softc", bus);
|
|
|
|
if (alldevs[bus]) printf "static\n";
|
|
printf "void\n";
|
|
printf "autoconf_%s(%s *bus, int busunit)\n", bus, softc;
|
|
printf "{\n";
|
|
printf "\t(void)bus; (void)busunit;\n";
|
|
|
|
for (i=0; i<nlines; i++) {
|
|
if (buses[i]==bus) {
|
|
genprobe(devs[i], devunits[i], buses[i], busunits[i]);
|
|
}
|
|
}
|
|
|
|
printf "}\n\n";
|
|
}
|
|
|
|
printf "void\n";
|
|
printf "pseudoconfig(void)\n";
|
|
printf "{\n";
|
|
for (i=0; i<npseudo; i++) {
|
|
dev = pseudodevs[i];
|
|
unit = pseudounits[i];
|
|
printf "\t{\n";
|
|
printf "\t\tstruct %s_softc *s;\n", dev;
|
|
printf "\t\t\n";
|
|
printf "\t\ts = pseudoattach_%s(%s);\n", dev, unit;
|
|
printf "\t\tif (s!=NULL) {\n";
|
|
printf "\t\t\tkprintf(\"%s%d (virtual)\\n\");\n", dev, unit;
|
|
printf "\t\t\tautoconf_%s(s, %s);\n", dev, unit;
|
|
printf "\t\t}\n";
|
|
printf "\t}\n";
|
|
}
|
|
printf "}\n\n";
|
|
}
|
|
' >> $ACC
|
|
|
|
echo -n ' autoconf.c'
|
|
|
|
rm -f $CONFTMP $CONFTMP.attach
|
|
|
|
########################################
|
|
#
|
|
# Done.
|
|
#
|
|
|
|
echo
|
|
echo "Configuration in ../compile/$CONFNAME done"
|
|
echo "Remember to make depend"
|