]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - tools/tools/tinybsd/tinybsd
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / tools / tools / tinybsd / tinybsd
1 #!/bin/sh -
2 # Copyright (c) 2006 Jean Milanez Melo <jmelo@freebsdbrasil.com.br>
3 #                                      <jmelo@FreeBSD.org>
4 #                    Patrick Tracanelli <eksffa@freebsdbrasil.com.br>
5 #
6 # $FreeBSD$
7 #set -xv
8 CURRENTDIR=/usr/src/tools/tools/tinybsd
9 if [ ! -d $CURRENTDIR ]
10 then
11   CURRENTDIR=`pwd`
12 else
13   cd $CURRENTDIR
14 fi
15
16 WORKDIR=/usr/obj/tinybsdbuild
17 KERNCONF=TINYBSD
18 BASEFILE="tinybsd.basefiles"
19 PORTSFILE="tinybsd.ports"
20 PORTSDIR=/usr/ports
21 DEFINSTARGS="-o 0 -g 0 -m 555"
22 TS="=====>"
23
24 splitarg1 () {
25    local IFS
26    IFS='='
27    set $1
28    echo $1
29 }
30
31 splitarg2 () {
32    local IFS
33    IFS='='
34    set $1
35    echo $2
36 }
37
38 getargs () {
39  ARGS="$*"
40  for arg in $* 
41  do
42    ARG=`splitarg1 $arg`
43    VAL=`splitarg2 $arg`
44    case $ARG in
45      sectors)
46         SECTUNIT=$VAL
47         ;;
48      heads)
49         TRACKCYL=$VAL 
50         ;;
51      spt)
52         SECTRACK=$VAL
53         ;;
54      conf)
55         CONF=$VAL
56         ;;
57      mfsroot)
58         MFSROOT=$VAL
59         ;;
60      image)
61         IMG=$VAL
62         ;;
63      batch)
64         NO_PROMPTS="YES"
65         ;;
66      new)
67         NO_READ="YES"
68         ;;
69      *)
70          usage
71          ;;
72     esac
73  done
74 }
75
76 usage () {
77     echo "Woops
78     Usage: $0 sectors=<size of media> [80000]
79               heads=<heads according to firmware>  [4]
80               spt=<sectors per track according to firmware> [32]
81               conf=<configuration name> (see conf/name) [default]
82               mfsroot[=<yes|no>] [no]
83               image=<tinybsd image name> [tinybsd.bin]
84               batch[=<anything>]  (do not ask interactively)
85               new[=<anything>]  (do not read previous values)
86
87      Examples:
88     $0 sectors=65536 heads=8 spt=16 conf=wireless mfsroot=yes image=myimage.img batch
89
90      Default values are set in the program.
91      Environment values override defaults.
92      Previous values override environment values but can be disabled.
93      Command arguments override previous values.
94      Interactive values override command arguments but can be disabled. 
95
96      Run diskinfo(8) -v against your CF device to get correct information
97      about your disk. USB keys do not need any specific geometry"
98     exit 1
99 }
100
101 ########
102 # Load variables from stdin (could be a file)
103 # Look for lines that match foo=bar
104 # do not run the file.. that is asking for trouble
105 ########
106 loadvars () {
107   while :
108   do
109     OIFS=$IFS
110     IFS="="
111     if read PART1 PART2
112     then
113       IFS="$OIFS"
114       case "$PART1" in
115       \#*)
116         ;;
117       "")
118         ;;
119       *)
120         set "${PART1}"
121         if [ $# = "1" ]
122         then
123           eval "${PART1}='${PART2}'"
124         fi
125         ;;
126       esac
127     else
128       IFS="$OIFS"
129       return 0
130     fi
131   done
132 }
133
134 ########
135 # get values from the user
136 ########
137 confirm_action(){
138     local ANSWER
139     local MESSAGE
140     ANSWER=$1
141     MESSAGE=$2
142     if [ "$NO_PROMPTS" != "YES" ]
143     then
144         echo -n "$MESSAGE [$ANSWER] " > /dev/tty
145         read result
146         [ "$result" != "" ] && ANSWER=$result
147     fi
148
149     ANSWER=`eval "echo $ANSWER"`
150     echo $ANSWER
151 }
152
153 ########
154 # These are only used the VERY first time you run the program (on this machine)
155 ########
156 setdefaults () {
157   NO_PROMPTS=${NO_PROMPTS:-NO}
158   NO_READ=${NO_READ:-NO}
159   SECTUNIT=${SECTUNIT:-80000}; export SECTUNIT
160   TRACKCYL=${TRACKCYL:-4}; export TRACKCYL
161   SECTRACK=${SECTRACK:-32}; export SECTRACK
162   CONF=${CONF:-default}; export CONF
163   MFSROOT=${MFSROOT:-NO}; export MFSROOT
164   IMG=${IMG:-tinybsd.bin}; export IMG
165
166 }
167
168 #######
169 # get ourselves set up.
170 # Partly by reading config files and partly from asking questions.
171 #######
172 loadconfig () {
173   if [ "${NO_READ}" = "YES" ]
174   then
175     return
176   fi
177
178   HOSTNAME=`hostname`
179   HOSTPART=${HOSTNAME%%.*}
180   FILENAME=".tinybsd.${HOSTPART}.${USER}"
181   FULLFILENAME=$HOME/$FILENAME
182
183   if [ -f ${FULLFILENAME} ]
184   then
185     loadvars <${FULLFILENAME}
186   fi
187
188   SECTUNIT=`confirm_action "$SECTUNIT" "512 byte sectors per unit?"`
189   TRACKCYL=`confirm_action "$TRACKCYL" "Tracks per cylinder?"`
190   SECTRACK=`confirm_action "$SECTRACK" "Sectors per track?"`
191   while :
192   do
193     echo "The following configurations exist:"
194     ls -l conf|awk '/^d/{print "    ",$9}'|grep -v CVS
195     CONF=`confirm_action "$CONF" "Configuration name?"`
196     if [ ! -d "${CURRENTDIR}/conf/$CONF" ]
197     then
198       echo "${TS} Error: Could not find config (${CONF})"
199       if [ "$NO_PROMPTS" = "YES" ]
200       then
201         exit 1
202       fi
203     else
204       break
205     fi
206   done
207   MFSROOT=`confirm_action "$MFSROOT" "Use an MFSROOT? (YES/NO)"`
208   IMG=`confirm_action "$IMG" "Image file to generate?"`
209
210 # example of formatted value (NNN in this case)
211 #  #condition and format the number
212 #  if [ -z "${BUILDNUM}" ]
213 #  then
214 #    echo "Starting with build 001"
215 #    BUILDNUM="001"
216 #  else
217 #    BUILDNUM=`printf "%03d\n" $(($BUILDNUM))`
218 #  fi
219
220
221 }
222
223 saveconfig () {
224   HOSTNAME=`hostname`
225   HOSTPART=${HOSTNAME%%.*}
226   FILENAME=".tinybsd.${HOSTPART}.${USER}"
227   FULLFILENAME=$HOME/$FILENAME
228   (
229     echo "# written by tinybsd" `date` 
230     echo "SECTUNIT=${SECTUNIT}"
231     echo "TRACKCYL=${TRACKCYL}"
232     echo "SECTRACK=${SECTRACK}"
233     echo "CONF=${CONF}"
234     echo "MFSROOT=${MFSROOT:-NO}"
235     echo "IMG=${IMG}"
236   ) >${FULLFILENAME}
237 }
238
239 check_alt_imgname() {
240         if [ ${IMG} = 'tinybsd.bin' ]
241         then
242                 echo "${TS} Alternative image name not set; defaulting to 'tinybsd.bin'"
243         fi
244 }
245
246 rotate_buidlog() {
247         mv -f ${HOME}/tinybsd.log ${HOME}/tinybsd.log.old
248 }
249
250 remove_workdir() {
251         # Before removing check if there is not a mount under $WORKDIR anymore
252         MOUNT_CHECK=`mount|egrep "on ${WORKDIR}"`
253
254         if [ ! -z "${MOUNT_CHECK}" ]; then
255                 echo "There are mounts under the workdir (${WORKDIR}). Please umount them before running this script"
256                 exit 1
257         else
258                 chflags -R noschg ${WORKDIR}
259                 echo "${TS} Removing "${WORKDIR}
260                 rm -rf ${WORKDIR}
261                 echo "${TS} Removing Build Kernel Directory"
262                 rm -rf /usr/obj/usr/src/sys/${KERNCONF}
263                 echo "${TS}  done."
264         fi
265 }
266
267
268 prework() {
269         remove_workdir
270         mkdir -p ${WORKDIR}
271 }
272
273
274 create_tree() {
275         echo "${TS} Creating directory hierarchy... "
276         mtree -deU -f /etc/mtree/BSD.root.dist -p ${WORKDIR}
277         mtree -deU -f /etc/mtree/BIND.chroot.dist -p ${WORKDIR}
278         mtree -deU -f /etc/mtree/BSD.usr.dist -p ${WORKDIR}/usr
279         mtree -deU -f /etc/mtree/BSD.local.dist -p ${WORKDIR}/usr/local
280         mtree -deU -f /etc/mtree/BSD.var.dist -p ${WORKDIR}/var
281 }
282
283 copy_binaries() {
284         cd ${CURRENTDIR}/conf/${CONF}
285
286         for file in `cat ${CURRENTDIR}/conf/${CONF}/${BASEFILE} | grep -v "#" | \
287                 cut -f1 -d":" | sort | uniq` ; do
288                 echo "${TS} Copying "/${file}" to "${WORKDIR}/${file} 
289                 cp -fp /${file} ${WORKDIR}/${file} ;
290         done
291 }
292
293 install_ports() {
294         for portname in `cat ${CURRENTDIR}/conf/${CONF}/${PORTSFILE} | grep -v '#'` ; do
295                 if [ ! -d "${WORKDIR}/usr/ports" ]; then
296                         mkdir -p "${WORKDIR}/usr/ports"
297                 fi
298
299                 PNAME=`/usr/bin/basename "${portname}"`
300                 PORT_OPTION_FILE="/var/db/ports/${PNAME}/options"
301
302                 if [ -f "${PORT_OPTION_FILE}" ]; then
303                         mkdir -p "${WORKDIR}/var/db/ports/${PNAME}"
304                         cp "${PORT_OPTION_FILE}" "${WORKDIR}/var/db/ports/${PNAME}/"
305                 fi
306
307                 mount_nullfs /lib "${WORKDIR}/lib"
308                 mount_nullfs /usr/bin "${WORKDIR}/usr/bin"
309                 mount_nullfs /usr/sbin "${WORKDIR}/usr/sbin"
310                 mount_nullfs /usr/ports "${WORKDIR}/usr/ports"
311                 mount_nullfs /usr/share "${WORKDIR}/usr/share"
312                 mount_nullfs /usr/libexec "${WORKDIR}/usr/libexec"
313                 mount_nullfs /usr/lib "${WORKDIR}/usr/lib"
314                 mount_nullfs /usr/include "${WORKDIR}/usr/include"
315
316                 cd ${PORTSDIR}/${portname}
317                 make fetch-recursive
318                 make DESTDIR_ENV_LIST=PATH DESTDIR="${WORKDIR}" install
319                 make clean
320
321                 umount "${WORKDIR}/lib"
322                 umount "${WORKDIR}/usr/ports"
323                 umount "${WORKDIR}/usr/bin"
324                 umount "${WORKDIR}/usr/sbin"
325                 umount "${WORKDIR}/usr/share"
326                 umount "${WORKDIR}/usr/libexec"
327                 umount "${WORKDIR}/usr/lib"
328                 umount "${WORKDIR}/usr/include"
329         done
330 }
331
332 make_kernel() {
333         echo "${TS} Building customized tiny beastie kernel... "
334         cp -p ${CURRENTDIR}/conf/${CONF}/${KERNCONF} /usr/src/sys/i386/conf
335         cd /usr/src
336         make buildkernel KERNCONF=${KERNCONF} || exit 1
337         gzip -9 /usr/obj/usr/src/sys/${KERNCONF}/kernel
338         install ${DEFINSTARGS} /usr/obj/usr/src/sys/${KERNCONF}/kernel.gz ${WORKDIR}/boot/kernel/
339         install ${DEFINSTARGS} \
340           /usr/obj/usr/src/sys/${KERNCONF}/modules/usr/src/sys/modules/acpi/acpi/acpi.ko \
341             ${WORKDIR}/boot/kernel
342         install -o 0 -g 0 -m 444 /sys/i386/conf/GENERIC.hints ${WORKDIR}/boot/device.hints
343 }
344
345 copy_libraries() {
346         TDEPFILE="`mktemp -t deps`"
347         TDEPFILES="`mktemp -t depsymlnk`"
348
349         find "${WORKDIR}" -type f |while read file; do
350                 ldd -f "%p\n" ${file} >> ${TDEPFILE} ; # don't worry on progs been "not dynamic"
351         done
352
353         for libdeplib in `cat ${TDEPFILE} | sort | uniq`; do
354                 ldd -f "%p\n" /${libdeplib} >> ${TDEPFILE} ;
355         done
356
357         for pamdep in `ls -1 /usr/lib/pam*`; do
358                 echo $pamdep >> ${TDEPFILE} ;
359                 ldd -f "%p\n" /${pamdep} >> ${TDEPFILE} ;
360         done    
361
362         for lib in `cat ${TDEPFILE} | sort | uniq`; do
363                 echo "${TS} Copying "${lib}" to "${WORKDIR}${lib}
364                 cp -fp ${lib} ${WORKDIR}${lib} ;
365         done
366
367         for depsymlink in `cat ${TDEPFILE}`; do
368                 echo "${TS} Checking if ${depsymlink} is a symbolic link"
369                 /bin/ls -l $depsymlink | grep "\->" | awk '{print $11":"$9}' >> ${TDEPFILES}
370         done
371
372         for i in `cat ${TDEPFILES}`; do
373                 SOURCE_FILE=`echo $i | awk -F ":" '{print $1}'`
374                 TARGET_FILE=`echo $i | awk -F ":" '{print $2}'`
375
376                 echo "${TS} Unlinking ${WORKDIR}${TARGET_FILE}"
377                 chroot ${WORKDIR} /bin/chflags 0 ${TARGET_FILE}
378                 chroot ${WORKDIR} /bin/rm -f ${TARGET_FILE}
379
380                 echo "${TS} Symlinking ${SOURCE_FILE} to ${TARGET_FILE}"
381                 chroot ${WORKDIR} /bin/ln -s ${SOURCE_FILE} ${TARGET_FILE}
382         done
383
384         echo -n "${TS} Unlinking "
385         rm -fv ${TDEPFILE} ${TDEPFILES}
386 }
387
388 create_etc() {
389         cd /usr/src/etc/sendmail/
390         make freebsd.cf freebsd.submit.cf
391
392         cd /usr/src/etc/
393         mkdir -p ${WORKDIR}/var/named/etc/namedb
394         make distribution DESTDIR=${WORKDIR}
395 }
396
397 create_ssh_keys() {
398         echo "Creating ssh keys..."
399         ssh-keygen -t rsa1 -b 1024  -f ${WORKDIR}/etc/ssh/ssh_host_key -N ''
400         ssh-keygen -t dsa -f ${WORKDIR}/etc/ssh/ssh_host_dsa_key -N ''
401         ssh-keygen -t rsa -f ${WORKDIR}/etc/ssh/ssh_host_rsa_key -N ''
402 }
403
404 personal_conf() {
405         echo "${TS} Copying your custom configuration on conf/ ..."
406         for custom in `find ${CURRENTDIR}/conf/${CONF}/ -type d -depth 1 \! -name CVS`; do
407                 cp -Rp ${custom}/* ${WORKDIR}/${custom#${CURRENTDIR}/conf/${CONF}/}/
408         done
409
410         if [ -f ${CURRENTDIR}/conf/${CONF}/boot.config ]; then
411                 cp ${CURRENTDIR}/conf/${CONF}/boot.config ${WORKDIR}/boot.config
412         fi
413 }
414
415 symlinks() {
416 #set -xv
417         for i in `cat ${CURRENTDIR}/conf/${CONF}/${BASEFILE}| grep -v "#" | grep ":"`; do
418                 SOURCE_FILE=`echo $i | awk -F ":" {'print $1'}`
419                 TARGET_FILE=`echo $i | awk -F ":" {'print $2'}`
420                 chroot ${WORKDIR} /bin/ln -vs /${SOURCE_FILE} ${TARGET_FILE}
421         done
422 #set +xv
423 }
424
425
426 create_image() {
427         VNODEFILE=`mktemp -t tinybsd`
428         IMGMNT=`mktemp -d -t tinybsd`
429
430         dd if=/dev/zero of=${VNODEFILE} count=${SECTUNIT}
431
432         MD=`mdconfig -a -t vnode -f ${VNODEFILE} -x ${SECTRACK} -y ${TRACKCYL}`
433
434         diskinfo -v /dev/${MD}
435
436         fdisk -I /dev/${MD}
437         fdisk /dev/${MD}
438
439         cp -p /boot/boot0 ${WORKDIR}/boot/boot0
440         bsdlabel -w -B /dev/${MD}
441         newfs -O2 -U /dev/${MD}a
442
443         mount /dev/${MD}a ${IMGMNT}
444
445         if [ ${MFSROOT} = 'yes' ]
446         then
447                 echo "${TS} Creating MFS root..."
448                 # Update is not done yet
449                 #mkdir -p ${WORKDIR}/usr/local/bin/
450                 #cp -p ${CURRENTDIR}/update/update ${WORKDIR}/usr/local/bin/
451                 rm ${WORKDIR}/etc/fstab
452                 cd ${WORKDIR} && find . -print | sed '/kernel/ d' | cpio -dump ${IMGMNT} || true
453                 umount ${IMGMNT}
454                 dd if=/dev/${MD} of=${CURRENTDIR}/mfsroot.img           
455                 gzip -9 < ${CURRENTDIR}/mfsroot.img > ${CURRENTDIR}/mfsroot.gz
456                 rm ${CURRENTDIR}/mfsroot.img
457                 mount /dev/${MD}a ${IMGMNT}
458                 rm -rf ${IMGMNT}/*
459                 cp -rp ${WORKDIR}/boot ${IMGMNT}
460                 rm ${IMGMNT}/boot/device.hints
461                 ( \
462                 echo 'set vfs.root.mountfrom="ufs:/dev/md0a"' ; \
463                 echo 'set bootfile="/boot/kernel/kernel"' ; \
464                 sed -e  '/^#/ d' -e 's/^/set /' < ${WORKDIR}/boot/device.hints ; \
465                 echo 'load /boot/kernel/kernel' ; \
466                 echo 'echo Loading mfsroot' ; \
467                 echo 'load -t mfs_root /mfsroot' ;\
468                 echo 'boot' ; \
469                 ) > ${IMGMNT}/boot/loader.rc
470                 mv ${CURRENTDIR}/mfsroot.gz ${IMGMNT}
471         else
472                 ( cd ${WORKDIR} && find . -print | cpio -dump ${IMGMNT} ) || true
473         fi
474
475         df ${IMGMNT}
476         sleep 1
477         umount ${IMGMNT}
478
479         dd if=/dev/${MD} of=${CURRENTDIR}/${IMG} bs=64k
480
481         rm -vf ${VNODEFILE}
482         rm -rvf ${IMGMNT}
483         mdconfig -d -u ${MD}
484         echo ""
485         echo "${TS} Done!"
486         echo "${TS} Your configuration options were saved in ${FULLFILENAME}"
487         echo "${TS} You can see your build log in ${HOME}/tinybsd.log"
488         echo "${TS} Your final image is in ${CURRENTDIR}/${IMG}"
489         echo "${TS} Now use dd(1) to write it."
490 }
491
492 ##########################
493 # run things
494
495 ##########################################
496 ## The actual program
497 ##########################################
498 getargs $*
499 setdefaults
500 # Load as many of the configuration options as we can
501 loadconfig
502 saveconfig
503
504 # Rotate build log
505 rotate_buidlog
506
507 # Now start logging.
508 (
509   # Do the build
510   prework
511   check_alt_imgname
512   create_tree
513   copy_binaries
514   create_etc
515   install_ports
516   make_kernel
517   copy_libraries
518   symlinks
519   create_ssh_keys
520   personal_conf
521   create_image
522 #set +xv
523 ) 2>&1 |tee -a  ${HOME}/tinybsd.log
524