Subject: The smallest multi-user system
To: NetBSD - Users <netbsd-users@netbsd.org>
From: Brian Rose <lists@brianrose.net>
List: netbsd-users
Date: 08/21/2003 23:41:43
This is a pretty long email. There ... I warned you.
After much trial and error I have devised a small NetBSD system that will boot up and start a login session. I crunched this into a ramdrive image which I then embedded into a kernel. This kernel was configured to mount the internal ramdrive as the root, so the whole thing was wrapped up into one nice clean file. I then compressed this file (to about 1,068kB), stuck it on a floppy and booted from it. Below I will detail all the steps that are needed to produce a small system that will get you to the login prompt. Afterwards, I have the script files I used to automate this.
The first thing I did was create a kernel. Some code changes were needed in the 1.6.0 kernel that I was working with. This change was needed to prevent the kernel from going into single user mode when the ramdisk is root. Newer kernels may or may not need changes.
The configuration file needed the following lines to create the ramdisk and boot from it.
# Enable the hooks used for initializing the root memory-disk.
options MEMORY_DISK_HOOKS
options MEMORY_DISK_IS_ROOT # force root on memory disk
options MEMORY_DISK_SERVER=1 # userspace memory disk support
#options MEMORY_DISK_ROOT_SIZE=2880 # 1.44M, same as a floppy
options MEMORY_DISK_ROOT_SIZE=8192 # 4Meg
options MEMORY_RBFLAGS=0 # don't force single user
I also needed to change this code in my 1.6.0 kernel. The changes are noted by ##'s.
in sys/dev/md_root.c
/*
* This is called during open (i.e. mountroot)
*/
## #ifndef MEMORY_RBFLAGS
## #define MEMORY_RBFLAGS RB_SINGLE
## #endif
void
md_open_hook(int unit, struct md_conf *md)
{
## // ............................... added code
## if (unit == 0 && (MEMORY_RBFLAGS & RB_SINGLE) ) {
/* The root ramdisk only works single-user. */
boothowto |= RB_SINGLE;
}
}
Once this was done I built my kernel in the normal manner.
Next I had to populate the filesystem. The following files will be needed for the multiuser system.
/sbin/init
/sbin/mount
/sbin/mount_ffs
/sbin/mount_mfs
/sbin/umount
/sbin/ttyflags
/sbin/pwd_mkdb
/sbin/newfs
/usr/bin/passwd
/usr/bin/login
/bin/sh
/etc/rc
/etc/fstab
/etc/ttys
/etc/master.passwd
/etc/pwd.db
/etc/spwd.db
/etc/gettytab
/usr/share/misc/termcap
I copied the password files from my host system and removed the uneeded user entries manually. I also trimmed the termcap file to just the required entries. The termcap file is about 500k otherwise. The rc file is a simple shell script with the following contents.
echo Initializing system...
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
mount -ua
ttyflags -a
You will also need the /dev nodes. I first copied MAKEDEV into the filesystems dev directory and then did a './MAKEDEV floppy ramdisk wscons' from within that directory.
I then created an image file using makefs, embedded this image into a kernel using mdsetimage, compressed it and then copied it to a bootable floppy. Then I booted and there was much rejoicing!
Enjoy!
--
Brian
================= My crunchgen configuration file ========
srcdirs /usr/src/bin /usr/src/sbin /usr/src/usr.bin /usr/src/usr.sbin /usr/src/libexec
progs init mount newfs mount_ffs sh ttyflags getty pwd_mkdb passwd login reboot ls
ln sh -sh
ln newfs mount_mfs
# special init objpaths /usr/src/sbin/init/init.smallprog.o
# libraries used by the programs
# ---------------- Minimum single user files
# init : -lutil -lcrypt
# mount :
# newfs : -lutil
# mount_ffs :
# sh : -ll -ledit -ltermcap
# ---------------- Minimum multiuser files
# ttyflags :
# getty : -lutil -ltermcap
# pwd_mkdb : -lutil
# passwd : -lrpcsvc -lcrypt -lutil -lkrb5 -lcrypto -lasn1 -lcom_err -lroken
# login : -lutil -lcrypt -lskey -lkrb5 -lasn1 -lkrb -lcrypto -lroken -lcom_err
# ---------------- Useful utilities
# ls : -
# reboot : -lutil
# umount :
#
libs -lutil -ll -ledit -ltermcap -lcrypt -lrpcsvc -lkrb5 -lkrb -lcrypto -lasn1 -lcom_err -lroken -lskey
=================== Create the crunched binary ==============
#!/bin/sh
cd work
cp ../pcm5894.multi.conf .
crunchgen -m Makefile pcm5894.multi.conf
make -f Makefile objs exe
cd ..
ls -l work/pcm5894.multi
=================== Populate the filesystem =================
#!/bin/sh
# This file is used to populate a directory with the contents needed
# to run a minimal NetBSD system. As of now there are two parts to
# this. The first part consists of all the files needed to boot to
# a single-user shell and some utilities to move around the filesystem.
#
# The second part includes all the files needed to boot into a multi-user
# configuration, with a login screen and password authentication.
#######################################################
if test $1 ; then
echo Populating $1
else
echo "No directory specified"
exit
fi
rm -rf $1/*
echo -n "Creating directory strucutre..."
mkdir $1/bin $1/sbin $1/usr $1/etc $1/var $1/dev $1/tmp $1/root $1/home
mkdir $1/usr/bin $1/usr/sbin $1/usr/libexec
mkdir $1/var/run $1/var/db $1/var/crash
echo "Done."
#-------------------- Make the /dev nodes
echo -n "Creating the /dev nodes..."
cp /dev/MAKEDEV $1/dev
cd $1/dev
./MAKEDEV floppy ramdisk wscons
cd ../..
echo "Done."
#-------------------- Fill in the filesystem
echo -n "Creating the data files..."
echo "/dev/md0a / ffs rw 1 1" > $1/etc/fstab
#-------------------- Setup the basic rc script
echo "echo Initializing system..." > $1/etc/rc
echo "export PATH=/sbin:/bin:/usr/sbin:/usr/bin" >> $1/etc/rc
echo "" >> $1/etc/rc
echo "Done."
#######################################
# Files for a single boot system #
#######################################
echo -n "Creating single user links and files..."
cp work/pcm5894.multi $1/sbin/init
ln $1/sbin/init $1/bin/ls
ln $1/sbin/init $1/bin/cp
ln $1/sbin/init $1/bin/cat
ln $1/sbin/init $1/bin/mkdir
ln $1/sbin/init $1/sbin/mount
ln $1/sbin/init $1/sbin/mount_ffs
ln $1/sbin/init $1/sbin/mount_mfs
ln $1/sbin/init $1/sbin/umount
ln $1/sbin/init $1/bin/sh
#------------- Setup the single user rc script
echo "mount -ua" >> $1/etc/rc
echo "Done."
##############################################
# Files for a mutiuser system #
##############################################
echo -n "Adding multiuser links and files..."
#----------------------- Multiuser directories
mkdir $1/usr/share
mkdir $1/usr/share/misc
# -------------------- Multiuser program files
ln $1/sbin/init $1/usr/libexec/getty
ln $1/sbin/init $1/sbin/ttyflags
ln $1/sbin/init $1/sbin/pwd_mkdb
ln $1/sbin/init $1/usr/bin/passwd
ln $1/sbin/init $1/usr/bin/login
ln $1/sbin/init $1/sbin/reboot
ln $1/sbin/init $1/sbin/newfs
#------------------------ multiuser data files
cp /etc/ttys $1/etc
cp /etc/master.passwd $1/etc
cp /etc/pwd.db $1/etc
cp /etc/spwd.db $1/etc
cp /etc/passwd $1/etc
cp termcap.mini $1/usr/share/misc/termcap
cp /etc/gettytab $1/etc
#---------------- Setup the multiuser rc script
echo "ttyflags -a" >> $1/etc/rc
echo "Done."
#########################################
# Files for a minimal rc.d system #
#########################################
#-------------------- Directories
#-------------------- Programs
#-------------------- Data files
#-------------------- rc entries
================== Create the image and kernel ================
#!/bin/sh
if test $1 ; then
echo Building with filesystem in $1
else
echo "No directory specified"
exit
fi
makefs -s 4m -t ffs crunch.image $1
mdsetimage netbsd.nodebug crunch.image
gzip -c netbsd.nodebug > netbsd
ls -l netbsd