tinybsd revision 163017
1162485Sjulian#!/bin/sh -
2162485Sjulian# Copyright (c) 2006 Jean Milanez Melo <jmelo@freebsdbrasil.com.br>
3162485Sjulian#				       <jmelo@FreeBSD.org>
4162485Sjulian#		     Patrick Tracanelli <eksffa@freebsdbrasil.com.br>
5162485Sjulian#
6162485Sjulian# $FreeBSD: head/tools/tools/tinybsd/tinybsd 163017 2006-10-04 22:16:40Z julian $
7162485Sjulian#set -xv
8162485SjulianCURRENTDIR=/usr/src/tools/tools/tinybsd
9162485SjulianWORKDIR=/usr/obj/tinybsdbuild
10162485SjulianKERNCONF=TINYBSD
11162485SjulianDEFINSTARGS="-o 0 -g 0 -m 555"
12162485SjulianTS="=====>"
13162485Sjulian
14163017Sjuliansplitarg1 () {
15163017Sjulian   local IFS
16163017Sjulian   IFS='='
17163017Sjulian   set $1
18163017Sjulian   echo $1
19163017Sjulian}
20162485Sjulian
21163017Sjuliansplitarg2 () {
22163017Sjulian   local IFS
23163017Sjulian   IFS='='
24163017Sjulian   set $1
25163017Sjulian   echo $2
26163017Sjulian}
27162485Sjulian
28163017Sjuliangetargs () {
29163017Sjulian ARGS="$*"
30163017Sjulian for arg in $* 
31163017Sjulian do
32163017Sjulian   ARG=`splitarg1 $arg`
33163017Sjulian   VAL=`splitarg2 $arg`
34163017Sjulian   case $ARG in
35163017Sjulian     sectors)
36163017Sjulian        SECTUNIT=$VAL
37163017Sjulian        ;;
38163017Sjulian     heads)
39163017Sjulian        TRACKCYL=$VAL 
40163017Sjulian        ;;
41163017Sjulian     spt)
42163017Sjulian        SECTRACK=$VAL
43163017Sjulian        ;;
44163017Sjulian     conf)
45163017Sjulian        CONF=$VAL
46163017Sjulian        ;;
47163017Sjulian     mfsroot)
48163017Sjulian        MFSROOT=$VAL
49163017Sjulian        ;;
50163017Sjulian     image)
51163017Sjulian        IMG=$VAL
52163017Sjulian        ;;
53163017Sjulian     batch)
54163017Sjulian        NO_PROMPTS="YES"
55163017Sjulian        ;;
56163017Sjulian     new)
57163017Sjulian        NO_READ="YES"
58163017Sjulian        ;;
59163017Sjulian     *)
60163017Sjulian         usage
61163017Sjulian         ;;
62163017Sjulian    esac
63163017Sjulian done
64163017Sjulian}
65162485Sjulian
66163017Sjulianusage () {
67163017Sjulian    echo "Woops
68163017Sjulian    Usage: $0 sectors=<size of media> [80000]
69163017Sjulian              heads=<heads according to firmware>  [4]
70163017Sjulian              spt=<sectors per track according to firmware> [32]
71163017Sjulian              conf=<configuration name> (see conf/name) [default]
72163017Sjulian              mfsroot[=<yes|no>] [no]
73163017Sjulian              image=<tinybsd image name> [tinybsd.bin]
74163017Sjulian              batch[=<anything>]  (do not ask interactively)
75163017Sjulian              new[=<anything>]  (do not read previous values)
76162485Sjulian
77163017Sjulian     Examples:
78163017Sjulian    $0 sectors=65536 heads=8 spt=16 conf=wireless mfsroot=yes image=myimage.img batch
79162485Sjulian
80163017Sjulian     Default values are set in the program.
81163017Sjulian     Environment values override defaults.
82163017Sjulian     Previous values override environment values but can be disabled.
83163017Sjulian     Command arguments override previous values.
84163017Sjulian     Interactive values override command arguments but can be disabled. 
85163017Sjulian
86163017Sjulian     Run diskinfo(8) -v against your CF device to get correct information
87163017Sjulian     about your disk. USB keys do not need any specific geometry"
88163017Sjulian    exit 1
89163017Sjulian}
90163017Sjulian
91163017Sjulian########
92163017Sjulian# Load variables from stdin (could be a file)
93163017Sjulian# Look for lines that match foo=bar
94163017Sjulian# do not run the file.. that is asking for trouble
95163017Sjulian########
96163017Sjulianloadvars () {
97163017Sjulian  while :
98163017Sjulian  do
99163017Sjulian    OIFS=$IFS
100163017Sjulian    IFS="="
101163017Sjulian    if read PART1 PART2
102163017Sjulian    then
103163017Sjulian      IFS="$OIFS"
104163017Sjulian      case "$PART1" in
105163017Sjulian      \#*)
106163017Sjulian        echo "comment"
107163017Sjulian        ;;
108163017Sjulian      "")
109163017Sjulian        ;;
110163017Sjulian      *)
111163017Sjulian        set "${PART1}"
112163017Sjulian        if [ $# = "1" ]
113163017Sjulian        then
114163017Sjulian          eval "${PART1}='${PART2}'"
115163017Sjulian        fi
116163017Sjulian        ;;
117163017Sjulian      esac
118163017Sjulian    else
119163017Sjulian      IFS="$OIFS"
120163017Sjulian      return 0
121163017Sjulian    fi
122163017Sjulian  done
123163017Sjulian}
124163017Sjulian
125163017Sjulian########
126163017Sjulian# get values from the user
127163017Sjulian########
128163017Sjulianconfirm_action(){
129163017Sjulian    local ANSWER
130163017Sjulian    local MESSAGE
131163017Sjulian    ANSWER=$1
132163017Sjulian    MESSAGE=$2
133163017Sjulian    if [ "$NO_PROMPTS" != "YES" ]
134163017Sjulian    then
135163017Sjulian        echo -n "$MESSAGE [$ANSWER] use 'none' to clear ? " > /dev/tty
136163017Sjulian        read result
137163017Sjulian        [ "$result" != "" ] && ANSWER=$result
138163017Sjulian        [ "$result" = "none" ] && ANSWER=""
139163017Sjulian    fi
140163017Sjulian
141163017Sjulian    ANSWER=`eval "echo $ANSWER"`
142163017Sjulian    echo $ANSWER
143163017Sjulian}
144163017Sjulian
145163017Sjulian########
146163017Sjulian# These are only used the VERY first time you run the program (on this machine)
147163017Sjulian########
148163017Sjuliansetdefaults () {
149163017Sjulian  NO_PROMPTS=${NO_PROMPTS:-NO}
150163017Sjulian  NO_READ=${NO_READ:-NO}
151163017Sjulian  SECTUNIT=${SECTUNIT:-80000}; export SECTUNIT
152163017Sjulian  TRACKCYL=${TRACKCYL:-4}; export TRACKCYL
153163017Sjulian  SECTRACK=${SECTRACK:-32}; export SECTRACK
154163017Sjulian  CONF=${CONF:-default}; export CONF
155163017Sjulian  MFSROOT=${MFSROOT:-NO}; export MFSROOT
156163017Sjulian  IMG=${IMG:-tinybsd.bin}; export IMG
157163017Sjulian
158163017Sjulian}
159163017Sjulian
160163017Sjulian#######
161163017Sjulian# get ourselves set up.
162163017Sjulian# Partly by reading config files and partly from asking questions.
163163017Sjulian#######
164163017Sjulianloadconfig () {
165163017Sjulian  if [ "${NO_READ}" = "YES" ]
166163017Sjulian  then
167163017Sjulian    return
168163017Sjulian  fi
169163017Sjulian
170163017Sjulian  HOSTNAME=`hostname`
171163017Sjulian  HOSTPART=${HOSTNAME%%.*}
172163017Sjulian  FILENAME=".tinybsd.${HOSTPART}.${USER}"
173163017Sjulian  FULLFILENAME=$HOME/$FILENAME
174163017Sjulian
175163017Sjulian  if [ -f ${FULLFILENAME} ]
176163017Sjulian  then
177163017Sjulian    loadvars <${FULLFILENAME}
178163017Sjulian  fi
179163017Sjulian
180163017Sjulian  SECTUNIT=`confirm_action "$SECTUNIT" "512 byte sectors per unit?"`
181163017Sjulian  TRACKCYL=`confirm_action "$TRACKCYL" "Tracks per cylinder?"`
182163017Sjulian  SECTRACK=`confirm_action "$SECTRACK" "Sectors per track?"`
183163017Sjulian  CONF=`confirm_action "$CONF" "Configuration name?"`
184163017Sjulian  MFSROOT=`confirm_action "$MFSROOT" "Use an MFSROOT?"`
185163017Sjulian  IMG=`confirm_action "$IMG" "Image file to generate?"`
186163017Sjulian
187163017Sjulian# example of formatted value (NNN in this case)
188163017Sjulian#  #condition and format the number
189163017Sjulian#  if [ -z "${BUILDNUM}" ]
190163017Sjulian#  then
191163017Sjulian#    echo "Starting with build 001"
192163017Sjulian#    BUILDNUM="001"
193163017Sjulian#  else
194163017Sjulian#    BUILDNUM=`printf "%03d\n" $(($BUILDNUM))`
195163017Sjulian#  fi
196163017Sjulian
197163017Sjulian
198163017Sjulian}
199163017Sjulian
200163017Sjuliansaveconfig () {
201163017Sjulian  HOSTNAME=`hostname`
202163017Sjulian  HOSTPART=${HOSTNAME%%.*}
203163017Sjulian  FILENAME=".tinybsd.${HOSTPART}.${USER}"
204163017Sjulian  FULLFILENAME=$HOME/$FILENAME
205163017Sjulian  (
206163017Sjulian    echo "# written by tinybsd" `date` 
207163017Sjulian    echo "SECTUNIT=${SECTUNIT}"
208163017Sjulian    echo "TRACKCYL=${TRACKCYL}"
209163017Sjulian    echo "SECTRACK=${SECTRACK}"
210163017Sjulian    echo "CONF=${CONF}"
211163017Sjulian    echo "MFSROOT=${MFSROOT:-NO}"
212163017Sjulian    echo "IMG=${IMG}"
213163017Sjulian  ) >${FULLFILENAME}
214163017Sjulian}
215163017Sjulian
216162485Sjuliancheck_conf() {
217163017Sjulian        if [ ${CONF} = 'default' ]
218162485Sjulian        then
219162485Sjulian                echo "${TS} Alternative conf name not set; defaulting to 'default'"
220162485Sjulian        fi
221162485Sjulian}
222162485Sjulian
223162485Sjuliancheck_alt_imgname() {
224163017Sjulian	if [ ${IMG} = 'tinybsd.bin' ]
225162485Sjulian	then
226162485Sjulian		echo "${TS} Alternative image name not set; defaulting to 'tinybsd.bin'"
227162485Sjulian	fi
228162485Sjulian}
229162485Sjulian
230162485Sjulianremove_workdir() {
231162485Sjulian	chflags -R noschg ${WORKDIR}
232162485Sjulian	echo "${TS} Removing "${WORKDIR}
233162485Sjulian	rm -rf ${WORKDIR}
234162485Sjulian	echo "${TS} Removing Build Kernel Directory"
235162485Sjulian	rm -rf /usr/obj/usr/src/sys/${KERNCONF}
236162485Sjulian	echo "${TS}  done."
237162485Sjulian}
238162485Sjulian
239162485Sjulian
240162485Sjulianprework() {
241162485Sjulian	remove_workdir	
242162485Sjulian	mkdir -p ${WORKDIR}
243162485Sjulian}
244162485Sjulian
245162485Sjulian
246162485Sjuliancreate_tree() {
247162485Sjulian	echo "${TS} Creating directory hierarchy... "
248162485Sjulian	mtree -deU -f /etc/mtree/BSD.root.dist -p ${WORKDIR}
249162485Sjulian	mtree -deU -f /etc/mtree/BSD.usr.dist -p ${WORKDIR}/usr
250162485Sjulian	mtree -deU -f /etc/mtree/BSD.var.dist -p ${WORKDIR}/var
251162485Sjulian}
252162485Sjulian
253162485Sjulian
254162485Sjuliancopy_binaries() {
255162485Sjulian#set -xv
256162485Sjulian	for file in `cat ${CURRENTDIR}/conf/${CONF}/tinybsd.basefiles | grep -v "#" | \
257162485Sjulian		cut -f1 -d":" | sort | uniq` ; do
258162485Sjulian		echo "${TS} Copying "/${file}" to "${WORKDIR}/${file} 
259162485Sjulian		cp -fp /${file} ${WORKDIR}/${file} ;
260162485Sjulian	done
261162485Sjulian#set +xv
262162485Sjulian}
263162485Sjulian
264162485Sjulianmake_kernel() {
265162485Sjulian	echo "${TS} Building customized tiny beastie kernel... "
266162485Sjulian	cp -p ${CURRENTDIR}/conf/${CONF}/${KERNCONF} /usr/src/sys/i386/conf
267162485Sjulian	cd /usr/src
268162485Sjulian	make buildkernel KERNCONF=${KERNCONF} || exit 1
269162485Sjulian	gzip -9 /usr/obj/usr/src/sys/${KERNCONF}/kernel
270162485Sjulian	install ${DEFINSTARGS} /usr/obj/usr/src/sys/${KERNCONF}/kernel.gz ${WORKDIR}/boot/kernel/
271162485Sjulian	install ${DEFINSTARGS} \
272162485Sjulian	  /usr/obj/usr/src/sys/${KERNCONF}/modules/usr/src/sys/modules/acpi/acpi/acpi.ko \
273162485Sjulian	    ${WORKDIR}/boot/kernel
274162485Sjulian	install -o 0 -g 0 -m 444 /sys/i386/conf/GENERIC.hints ${WORKDIR}/boot/device.hints
275162485Sjulian}
276162485Sjulian
277162485Sjulian
278162485Sjuliancopy_libraries() {
279162485Sjulian#set -xv
280162485Sjulian	TDEPFILE="`mktemp -t deps`"
281162485Sjulian	TDEPFILES="`mktemp -t depsymlnk`"
282162485Sjulian
283162485Sjulian	cd ${CURRENTDIR}/conf/${CONF}
284162485Sjulian	for file in `cat tinybsd.basefiles | grep -v "#" | cut -f1 -d":"`; do
285162485Sjulian		ldd -f "%p\n" /${file} >> ${TDEPFILE} ; # don't worry on progs been "not dynamic"
286162485Sjulian	done
287162485Sjulian
288162485Sjulian	for libdeplib in `cat ${TDEPFILE} | sort | uniq`; do
289162485Sjulian		ldd -f "%p\n" /${libdeplib} >> ${TDEPFILE} ;
290162485Sjulian	done
291162485Sjulian	
292162485Sjulian	for pamdep in `ls -1 /usr/lib/pam*`; do
293162485Sjulian		echo $pamdep >> ${TDEPFILE} ;
294162485Sjulian		ldd -f "%p\n" /${pamdep} >> ${TDEPFILE} ;
295162485Sjulian	done	
296162485Sjulian	
297162485Sjulian	for lib in `cat ${TDEPFILE} | sort | uniq`; do
298162485Sjulian		echo "${TS} Copying "${lib}" to "${WORKDIR}${lib}
299162485Sjulian		cp -fp ${lib} ${WORKDIR}${lib} ;
300162485Sjulian	done
301162485Sjulian
302162485Sjulian	for depsymlink in `cat ${TDEPFILE}`; do
303162485Sjulian		echo "${TS} Checking if ${depsymlink} is a symbolic link"
304162485Sjulian		/bin/ls -l $depsymlink | grep "\->" | awk '{print $11":"$9}' >> ${TDEPFILES}
305162485Sjulian	done
306162485Sjulian
307162485Sjulian	for i in `cat ${TDEPFILES}`; do
308162485Sjulian                SOURCE_FILE=`echo $i | awk -F ":" '{print $1}'`
309162485Sjulian                TARGET_FILE=`echo $i | awk -F ":" '{print $2}'`
310162485Sjulian
311162485Sjulian		echo "${TS} Unlinking ${WORKDIR}${TARGET_FILE}"
312162485Sjulian                chroot ${WORKDIR} /bin/rm -f ${TARGET_FILE}
313162485Sjulian
314162485Sjulian		echo "${TS} Symlinking ${SOURCE_FILE} to ${TARGET_FILE}"
315162485Sjulian                chroot ${WORKDIR} /bin/ln -s ${SOURCE_FILE} ${TARGET_FILE}
316162485Sjulian        done
317162485Sjulian
318162485Sjulian	echo -n "${TS} Unlinking "
319162485Sjulian	rm -fv ${TDEPFILE} ${TDEPFILES}
320162485Sjulian#set +xv
321162485Sjulian}
322162485Sjulian
323162485Sjulian
324162485Sjuliancreate_etc() {
325162485Sjulian	cd /usr/src/etc/sendmail/
326162485Sjulian	make freebsd.cf freebsd.submit.cf
327162485Sjulian
328162485Sjulian	cd /usr/src/etc/
329162485Sjulian	mkdir -p ${WORKDIR}/var/named/etc/namedb
330162485Sjulian	make distribution DESTDIR=${WORKDIR}
331162485Sjulian}
332162485Sjulian
333163017Sjuliancreate_ssh_keys() {
334163017Sjulian	echo "Creating ssh keys..."
335163017Sjulian	ssh-keygen -t rsa1 -b 1024  -f ${WORKDIR}/etc/ssh/ssh_host_key -N ''
336163017Sjulian	ssh-keygen -t dsa -f ${WORKDIR}/etc/ssh/ssh_host_dsa_key -N ''
337163017Sjulian	ssh-keygen -t rsa -f ${WORKDIR}/etc/ssh/ssh_host_rsa_key -N ''
338163017Sjulian}
339163017Sjulian
340162485Sjulianpersonal_directories() {
341162485Sjulian	echo "${TS} Copying your custom configuration on conf/ ..."
342162485Sjulian	for custom in `find ${CURRENTDIR}/conf/${CONF}/ -type d -depth 1`; do
343162485Sjulian		cp -Rp ${custom}/* ${WORKDIR}/${custom#${CURRENTDIR}/conf/${CONF}/}/
344162485Sjulian	done
345162485Sjulian}
346162485Sjulian
347162485Sjuliansymlinks() {
348162485Sjulian#set -xv
349162485Sjulian	for i in `cat tinybsd.basefiles | grep -v "#" | grep ":"`; do
350162485Sjulian		SOURCE_FILE=`echo $i | awk -F ":" {'print $1'}`
351162485Sjulian		TARGET_FILE=`echo $i | awk -F ":" {'print $2'}`
352162485Sjulian		chroot ${WORKDIR} /bin/ln -vs /${SOURCE_FILE} ${TARGET_FILE}
353162485Sjulian	done
354162485Sjulian#set +xv
355162485Sjulian}
356162485Sjulian
357162485Sjulian
358162485Sjuliancreate_image() {
359162485Sjulian	#set -ex
360162485Sjulian
361162485Sjulian	VNODEFILE=`mktemp -t tinybsd`
362162485Sjulian	IMGMNT=`mktemp -d -t tinybsd`
363162485Sjulian
364162485Sjulian	dd if=/dev/zero of=${VNODEFILE} count=${SECTUNIT}
365162485Sjulian
366162485Sjulian	MD=`mdconfig -a -t vnode -f ${VNODEFILE} -x ${SECTRACK} -y ${TRACKCYL}`
367162485Sjulian
368162485Sjulian	diskinfo -v /dev/${MD}
369162485Sjulian
370162485Sjulian	fdisk -I /dev/${MD}
371162485Sjulian	fdisk /dev/${MD}
372162485Sjulian
373162485Sjulian	cp -p /boot/boot0 ${WORKDIR}/boot/boot0
374162485Sjulian	bsdlabel -w -B /dev/${MD}
375162485Sjulian	newfs -O2 -U /dev/${MD}a
376162485Sjulian
377162485Sjulian	mount /dev/${MD}a ${IMGMNT}
378162485Sjulian
379163017Sjulian	if [ ${MFSROOT} = 'yes' ]
380163017Sjulian	then
381163017Sjulian		echo "${TS} Creating MFS root..."
382163017Sjulian		# Update is not done yet
383163017Sjulian		#mkdir -p ${WORKDIR}/usr/local/bin/
384163017Sjulian		#cp -p ${CURRENTDIR}/update/update ${WORKDIR}/usr/local/bin/
385163017Sjulian		rm ${WORKDIR}/etc/fstab
386163017Sjulian		cd ${WORKDIR} && find . -print | sed '/kernel/ d' | cpio -dump ${IMGMNT} || true
387163017Sjulian		umount ${IMGMNT}
388163017Sjulian		dd if=/dev/${MD} of=${CURRENTDIR}/mfsroot.img		
389163017Sjulian		gzip -9 < ${CURRENTDIR}/mfsroot.img > ${CURRENTDIR}/mfsroot.gz
390163017Sjulian		rm ${CURRENTDIR}/mfsroot.img
391163017Sjulian		mount /dev/${MD}a ${IMGMNT}
392163017Sjulian		rm -rf ${IMGMNT}/*
393163017Sjulian		cp -rp ${WORKDIR}/boot ${IMGMNT}
394163017Sjulian		rm ${IMGMNT}/boot/device.hints
395163017Sjulian		( \
396163017Sjulian		echo 'set vfs.root.mountfrom="ufs:/dev/md0a"' ; \
397163017Sjulian		echo 'set bootfile="/boot/kernel/kernel"' ; \
398163017Sjulian		sed -e  '/^#/ d' -e 's/^/set /' < ${WORKDIR}/boot/device.hints ; \
399163017Sjulian		echo 'load /boot/kernel/kernel' ; \
400163017Sjulian		echo 'echo Loading mfsroot' ; \
401163017Sjulian		echo 'load -t mfs_root /mfsroot' ;\
402163017Sjulian		echo 'boot' ; \
403163017Sjulian		) > ${IMGMNT}/boot/loader.rc
404163017Sjulian		mv ${CURRENTDIR}/mfsroot.gz ${IMGMNT}
405163017Sjulian	else
406163017Sjulian		( cd ${WORKDIR} && find . -print | cpio -dump ${IMGMNT} ) || true
407163017Sjulian	fi
408162485Sjulian
409162485Sjulian	df ${IMGMNT}
410163017Sjulian	sleep 1
411162485Sjulian	umount ${IMGMNT}
412162485Sjulian
413162485Sjulian	dd if=/dev/${MD} of=${CURRENTDIR}/${IMG} bs=64k
414162485Sjulian
415162485Sjulian	rm -vf ${VNODEFILE}
416162485Sjulian	rm -rvf ${IMGMNT}
417162485Sjulian	mdconfig -d -u ${MD}
418163017Sjulian	echo ""
419163017Sjulian	echo "${TS} Done!"
420163017Sjulian	echo "${TS} Your configuration options were saved in ${FULLFILENAME}"
421163017Sjulian	echo "${TS} You can see your build log in ${HOME}/tinybsd.log"
422163017Sjulian	echo "${TS} Your final image is in ${CURRENTDIR}/${IMG}"
423163017Sjulian	echo "${TS} Now use dd(1) to write it."
424163017Sjulian
425162485Sjulian}
426162485Sjulian
427162485Sjulian##########################
428162485Sjulian# run things
429163017Sjulian
430163017Sjulian##########################################
431163017Sjulian## The actual program
432163017Sjulian##########################################
433163017Sjuliangetargs $*
434163017Sjuliansetdefaults
435163017Sjulian# Load as many of the configuration options as we can
436163017Sjulianloadconfig
437163017Sjuliansaveconfig
438163017Sjulian
439163017Sjulian# Now start logging.
440163017Sjulian(
441163017Sjulian  # Do the build
442163017Sjulian  prework
443163017Sjulian  check_conf
444163017Sjulian  check_alt_imgname
445163017Sjulian  create_tree
446163017Sjulian  copy_binaries
447163017Sjulian  make_kernel
448163017Sjulian  copy_libraries
449163017Sjulian  symlinks
450163017Sjulian  create_etc
451163017Sjulian  create_ssh_keys
452163017Sjulian  personal_directories
453163017Sjulian  create_image
454162485Sjulian#set +xv
455163017Sjulian) 2>&1 |tee -a  ${HOME}/tinybsd.log
456162485Sjulian
457