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