]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - release/picobsd/build/picobsd
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / release / picobsd / build / picobsd
1 #!/bin/sh -
2 #
3 # $FreeBSD$
4 # This file requires sysutils/makefs to run
5 #
6 # The PicoBSD build script. Invoked as
7 #
8 #       picobsd [options] image_type [site_name]
9 #
10 # Where image_type is a directory with the picobsd config info,
11 # and ${image_type}/floppy.tree.${site_name} contains
12 # optional site-specific configuration.
13 #
14 # For Options, see the bottom of the file where the processing is
15 # done. The picobsd(8) manpage might be of some help, but code and docs
16 # tend to lose sync over time.
17 #
18 # This script depends on the following files:
19 #
20 # in ${PICO_TREE} :
21 #   Makefile.conf       Makefile used to build the kernel
22 #   config              shell variables, sourced here.
23 #   mfs.mtree           mtree config file
24 #   floppy.tree/        files which go on the floppy
25 #   mfs_tree/           files which go onto the mfs
26 #
27 # in ${MY_TREE} :
28 #   PICOBSD             kernel config file
29 #   config              shell variables, sourced here.
30 #   crunch.conf         crunchgen configuration
31 #   mfs.mtree           overrides ${PICO_TREE}/mfs.mtree
32 #   floppy.tree.exclude files from floppy.tree/ which we do not need here.
33 #   floppy.tree/        local additions to ${PICO_TREE}/mfs_free
34 #   floppy.tree.${site}/ same as above, site specific.
35 #   mfs_tree/           local additions to the mfs_free
36 #   buildtree.mk        optional Makefile to build an extension for floppy tree
37 #                       (generated in buildtree/ )
38
39 #
40 #--- The main entry point is at the end.
41 #
42
43 # There are two initialization functions:
44 #
45 # + set_defaults
46 #   is run on entry to the script, and is used to set default values
47 #   for all variables that do not depend on image type and source tree.
48 #
49 # + set_build_parameters
50 #   is run after command line parsing
51 #
52 # VARIABLE NAMES:
53 # + variables that control operation (e.g. verbosity) and are generally
54 #   set from the command line have o_ ("option") as a name prefix
55 #
56 # + variables that contain pathnames and values that should not change
57 #   have c_ ("constant") as a name prefix
58 #
59 # + variables exported to Makefiles and subshells are CAPITAL
60 #
61 # + variables local to the script are lowercase, possibly with
62 #   an l_ ("local") prefix.
63 #
64 # There are unfortunately exceptions:
65 # name, l_usrtree, l_objtree
66
67 # SRC points to your FreeBSD source tree.
68 # l_usrtree points to the /usr subdir for the source tree.
69 #     Normally /usr or ${SRC}/../usr
70 # l_objtree points to the obj tree. Normally ${l_usrtree}/obj-pico
71 # c_label is either bsdlabel or disklabel
72 # PICO_TREE is where standard picobsd stuff resides.
73 #     Normally ${SRC}/release/picobsd
74 # You can set SRC with --src <directory>
75 # It is not recommended to override the other variables.
76
77 # MY_TREE (set later) is where this floppy type resides.
78 # BUILDDIR is the build directory
79
80 # log something on stdout if verbose.
81 o_verbose=0     # this needs to be here!
82 log() { #       message
83     local foo
84     [ ${o_verbose} -gt 0 ] && printf "\n*** %s\n" "$*"
85     [ ${o_verbose}  -gt 1 ] && read -p "=== Press enter to continue" foo
86     return 0
87 }
88
89 # unconditionally log and wait for input
90 logverbose() {  # message
91     local foo
92     printf "\n*** %s\n" "$*"
93     read -p "=== Press enter to continue" foo
94     return 0
95 }
96
97 # set some default values for variables.
98 # needs to be done as the first thing in the script.
99
100 set_defaults() {        # no arguments
101     # EDITOR is the editor you use
102     # fd_size  floppy size in KB (default to 1440). You can use 1480,
103     #   1720, 2880, etc. but beware that only 1440 and 1480 will boot
104     #   from 1.44M floppy drives (1480 will not work on vmware).
105     EDITOR=${EDITOR:-vi}
106     fd_size=${fd_size:-1440}
107
108     o_use_loader="yes"          # use /boot/loader
109         # You should not change it unless you are really short
110         # of space, and your kernel is small enough that the
111         # bootblocks manage to load it.
112
113     o_all_in_mfs="yes"          # put all files in mfs so you can boot
114                                 # and run the image via diskless boot.
115     o_clean=""                  # set if you want to clean prev.builds.
116     o_interactive=""            # default is interactive
117     o_verbose=0                 # verbose level, 0 is silent
118     o_tarv=""                   # tar verbose flag, "" or "v"
119     o_init_src=""               # set to build libs and includes.
120     o_makeopts=${MAKEOPTS:--s}  # make options, be silent by default
121     o_no_devfs=                 # default is use devfs.
122         # You should only set it when building 4.x images
123     o_do_modules=""             # do not build modules
124
125     SRC="/usr/src"              # default location for sources
126     c_startdir=`pwd`            # directory where we start
127                                 # used to lookup config and create BUILDDIR
128
129     # XXX 6.x/7.x have a single /boot/boot block, which is the concatenation
130     # of the old two. For the time being, we keep these, but this should
131     # be fixed at some point.
132
133     # blocks
134     c_boot1=/boot/boot1         # boot blocks (in case you want custom ones)
135     c_boot2=/boot/boot2
136
137     c_reply=${c_reply:-`mktemp "/tmp/reply.XXXXXXXXXX"`}
138                                 # file where User replies will be put
139     c_mnt=`mktemp -d "/tmp/picobsd.XXXXXXXXXX"`
140                                 # mountpoint used to build memory filesystems
141     c_fs=fs.PICOBSD             # filename used for the memory filesystem
142     c_img=picobsd.bin           # filename used for the picobsd image
143     generate_iso="NO"           # don't generate the iso image
144
145     # select the right disklabel program
146     case `uname -r` in
147         4.*)
148             c_label="disklabel"
149             ;;
150         *)
151             c_label="bsdlabel"
152             ;;
153     esac
154
155     set -e
156
157     trap fail 2
158     #trap fail 3
159     #trap fail 6
160     trap fail 15
161 }
162
163 # use the new build infrastructure to create libraries
164 # and also to build a specific target
165 create_includes_and_libraries2() { # opt_dir opt_target
166     local no
167     log "create_includes_and_libraries2() for ${SRC}"
168     if [ ${OSVERSION} -ge 600000 ] ; then
169         no="-DNO_CLEAN -DNO_PROFILE -DNO_GAMES -DNO_LIBC_R"
170     else
171         no="-DNOCLEAN -DNOPROFILE -DNOGAMES -DNOLIBC_R"
172     fi
173     MAKEOBJDIRPREFIX=${l_objtree}
174     export MAKEOBJDIRPREFIX
175     ( cd ${SRC};
176     # make -DNOCLEAN -DNOPROFILE -DNOGAMES -DNOLIBC_R -DPICOBSD buildworld
177     if [ -d "$1" ] ; then
178         cd $1 ; make $2 # specific target, e.g. ld-elf.so
179     else
180         make _+_= $no toolchain _includes _libraries
181     fi
182     )
183 }
184
185 # entry for 4.x and earlier trees
186 create_includes_and_libraries() {
187     local e i
188
189     log "create_includes_and_libraries() for ${SRC}"
190     # Optionally creates include directory and libraries.
191     mkdir -p ${l_usrtree}/include       # the include directory...
192     mkdir -p ${l_usrtree}/share/misc    # a few things go here
193     mkdir -p ${l_usrtree}/lib           # libraries
194     mkdir -p ${l_usrtree}/sbin          # some binaries
195     # override variables for ownershiip and destinations
196     # BINOWN:BINGRP are also used for include files
197     (cd ${SRC}; \
198         BINOWN=`id -un` BINGRP=`id -gn` \
199         DESTDIR=${l_usrtree}/.. \
200         make -m ${SRC}/share/mk includes ) || fail $? includes
201     # Pick up the correct headers for libraries.
202     CFLAGS="-nostdinc -I${l_usrtree}/include" ; export CFLAGS
203
204     (cd ${SRC}
205         # $e is the invocation of make with correct environment
206         # XXX check the NO* options below, maybe system dependent.
207         e="MAKEOBJDIRPREFIX=${l_objtree}/picobsd/libraries \
208             BINOWN=`id -un` BINGRP=`id -gn` \
209             DESTDIR=${l_usrtree}/.. \
210             make -m ${SRC}/share/mk \
211                 -DNOHTML -DNOINFO -DNOMAN -DNOSHARE -DNOFSCHG "
212         log "do a 'make obj' in a few places."
213         # This is very version-specific... The following works for 5.0
214         for i in lib secure/lib gnu/lib \
215                 gnu/usr.bin/perl usr.bin/lex usr.sbin/config ; do
216             (cd ${i}; eval $e obj)
217         done
218         log "now make the static libraries"
219         eval $e -DNOPROFILE -DNOPIC libraries
220         (cd ${SRC}/usr.sbin/config
221         eval $e         # build binary
222         eval $e install # install it
223         )
224     ) || fail $? "libraries"
225     log "Libraries done"
226 }
227
228 # set_type <the_type> [the_site] looks in user or system directories
229 # for the directory named as the first argument, reads the configuration
230 # files and sets variables according to the config.
231 # Also sets MY_TREE and BUILDDIR and SITE
232
233 set_type() {    # the_type the_site
234     local a i
235
236     log "set_type() : Type '$1' site '$2'"
237     THETYPE=$1
238     SITE=$2
239     a=$1
240     name=""     # clear in case of errors
241     for i in ${c_startdir}/${a} ${PICO_TREE}/${a} ; do
242         log "set_type: checking $i"
243         [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ] || continue
244         set -- `cat $i/PICOBSD | \
245             awk '/^#PicoBSD/ {print $2, $3, $4, $5, $6}'`
246         [ x"$1" != "x" ] || continue
247         MFS_SIZE=$1 ; init_name=$2
248         mfs_inodes=$3 ; fd_inodes=$4
249         name=`(cd $i ; pwd) `
250         name=`basename $name`
251         MY_TREE=$i
252         BUILDDIR=${c_startdir}/build_dir-${name}
253         log "Matching file $name in $i"
254         return ;
255     done
256     logverbose "Type $a NOT FOUND"
257 }
258
259 clean_tree() {
260     log "clean_tree()"
261     if [ -z "${name}" ] ; then
262         echo "---> Wrong floppy type"
263         exit 3
264     fi
265     rm -rf ${BUILDDIR}
266 }
267
268 # prepare a message to be printed in the dialog menus.
269 set_msgs() {            # OK
270     log "set_msgs()"
271
272     MSG1="Type: ${THETYPE} name $name"
273
274     MSG="PicoBSD build -- Current parameters:\n\n\t1.  ${MSG1}\n\
275 \t2.  MFS size: ${MFS_SIZE} kB\n\
276 \t3.  Site-info: ${SITE}\n\t4.  Full-path: ${MY_TREE}\n"
277 }
278
279 # build the iso image
280 build_iso_image() {
281     log "build_iso_image()"
282     clear
283     set_msgs
284     printf "${MSG}---> Build the iso image not ready yet\n\n"
285 }
286
287 # Main build procedure.
288 build_image() {
289     log "build_image() <${name}>"
290     [ -n "${name}" ] || fail $? bad_type
291     clear
292     set_msgs
293     printf "${MSG}---> We'll use the sources living in ${SRC}\n\n"
294
295     # read config variables from a global and then a type-specific file
296     # basically STAND_LINKS and MY_DEVS, but can also override other
297     # variables.
298     # 
299     . ${PICO_TREE}/build/config
300     [ -f "${MY_TREE}/config" ]          && . ${MY_TREE}/config
301     [ -f "${o_additional_config}" ]     && . ${o_additional_config}
302
303     # location of the object directory
304     PICO_OBJ=${l_objtree}/picobsd/${THETYPE}
305     log "PICO_OBJ is ${PICO_OBJ}"
306
307     if [ ${OSVERSION} -ge 500035 ] ; then
308         export MAKEOBJDIRPREFIX=${l_objtree}
309         eval "export BINMAKE=\"`cd ${SRC}; make -f Makefile -V BINMAKE`\""
310         eval export `cd ${SRC}; ${BINMAKE} -f Makefile.inc1 -V WMAKEENV`
311     fi
312     # create build directory and subtree
313     mkdir -p ${BUILDDIR}/crunch
314     # remove any old stuff
315     rm -f ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs}
316     # invoke commands to build a kernel
317     do_kernel
318     # fill a subdirectory with things that go into the floppy
319     # (mostly /etc and similar stuff)
320     populate_floppy_fs
321     # populate it and produce a file with the MFS image
322     populate_mfs_tree           # things which go into mfs
323     # create, mount and fill a filesystem with floppy image
324     fill_floppy_image # copies everything into the floppy
325 }
326
327 # Set build parameters interactively
328
329 main_dialog() {
330   local ans i l
331
332   log "main_dialog()"
333   while true ; do
334     set_msgs
335     rm ${c_reply}
336     dialog --menu "PicoBSD build menu -- (29 sep 2001)" 19 70 12 \
337         N "--> READY, build it <---" \
338         T "${MSG1}" \
339         K "edit Kernel config file" \
340         E "Edit crunch.conf file" \
341         S "MFS Size: ${MFS_SIZE}kB" \
342         I "Init type: ${init_name}" \
343         F "Floppy size: ${fd_size}kB" \
344         M "MFS bytes per inode: ${mfs_inodes}" \
345         U "UFS bytes per inode: ${fd_inodes}" \
346         $ "Site-info: ${SITE}" \
347         Q "Quit" \
348         2> ${c_reply}
349     ans=`cat ${c_reply}`
350     rm ${c_reply}
351     case ${ans} in
352     T)
353         l=""
354         for i in ${c_startdir} ${c_startdir}/* ${PICO_TREE}/* ; do
355             if [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ]; then
356                 l="$l `basename $i` `basename $i`"
357             fi
358         done
359         log $l
360         { dialog --menu "Setup the type of configuration" 12 70 5 $l \
361                 2> ${c_reply} && set_type "`cat ${c_reply}`" ${SITE} ; } || true
362         ;;
363     I)
364         { dialog --menu "Choose your init(8) program" \
365         10 70 2 init "Standard init (requires getty)" \
366         oinit "small init from TinyWare" 2> ${c_reply} \
367                 && init_name=`cat ${c_reply}` ; } || true
368         ;;
369
370     K) ${EDITOR} ${MY_TREE}/PICOBSD ;;
371
372     E) ${EDITOR} ${MY_TREE}/crunch.conf ;;
373
374     S)
375         { dialog --title "MFS Size setup" --inputbox \
376 "MFS size depends on what you need to put on the MFS image. Typically \
377 ranges between 820kB (for very small bridge/router images) to \
378 as much as 2500kB kB for a densely packed image. \
379 Keep in mind that this memory is \
380 totally lost to other programs. Usually you want to keep \
381 this as small as possible. " 10 70 2> ${c_reply} \
382         && MFS_SIZE=`cat ${c_reply}` ; } || true
383         ;;
384
385     \$)
386         { dialog --title "Site info setup" --inputbox \
387         "Please enter the full path to the directory \
388         containing site-specific setup. \
389         This directory tree must contain files that replace \
390         standard ones in floppy.tree/ and mfs.tree/ . " \
391         10 70 2> ${c_reply} && SITE=`cat ${c_reply}` ; } || true
392         ;;
393
394     F)
395         { dialog --menu "Set floppy size" 15 70 4 \
396             1440 "1.44MB" 1720 "1.72MB" 2880 "2.88MB" 4096 "4MB" \
397                  2> ${c_reply} && fd_size=`cat ${c_reply}` ; } || true
398         ;;
399
400     M)
401         { dialog --title "MFS bytes per inode:" --inputbox \
402         "Enter MFS bytes per inode (typically 4096..65536). \
403         A larger value means fewer inodes but more space on MFS" \
404         10 70 2> ${c_reply} && mfs_inodes=`cat ${c_reply}`  ; } || true
405         ;;
406
407     U)
408         { dialog --title "Floppy bytes per inode:" --inputbox \
409         "Enter floppy bytes per inode (typically 3072..65536). \
410         A larger value means fewer inodes but more space on the floppy." \
411         10 70 2> ${c_reply} && fd_inodes=`cat ${c_reply}` ; } || true
412         ;;
413
414     N) break 2
415         ;;
416
417     Q) exit 0 ;;
418
419     *) echo "\aUnknown option \"${ans}\". Try again."
420         sleep 2
421         clear
422         ;;
423     esac
424   done
425 }
426
427 # Call the build procedure
428 # Install image
429 do_install() {
430     log "do_install()"
431
432     if [ "${o_interactive}" = "NO" ] ; then
433         echo "+++ Build completed +++"
434         cat .build.reply || true
435         return
436     fi
437     dialog --title "Build ${THETYPE} completed" --inputbox \
438 "\nThe build process was completed successfuly.\n\
439 `cat .build.reply` \n\n\
440 Now we are going to install the image on the floppy.\n\
441 Please insert a blank floppy in /dev/fd0.\\n
442 WARNING: the contents of the floppy will be permanently erased!\n\
443 \n\
444 Your options:\n\
445         * ^C or [Cancel] to abort,\n\
446         * Enter to install ${c_img},\n\
447 " 20 80 2> ${c_reply}
448     if [ "$?" = "0" ]; then
449         echo "Writing ${c_img}..."
450         dd if=${BUILDDIR}/${c_img} of=/dev/fd0.${fd_size}
451     else
452         echo "Ok, the image is in ${c_img}"
453     fi
454     echo "Done."
455 }
456
457
458 #-------------------------------------------------------------------
459
460 # invoke the picobsd Makefile to compile the kernel.
461 # if MODULES is set (value is irrelevant) the makefile will build modules.
462 do_kernel() {           # OK
463     log "do_kernel() Preparing kernel \"$name\" in $MY_TREE"
464     (cd $MY_TREE; export name SRC BUILDDIR # used in this makefile ;
465         # export CONFIG
466         [ "${o_do_modules}" = "yes" ] && export MODULES=""
467         ${BINMAKE} -v -f ${PICO_TREE}/build/Makefile.conf ) || \
468         fail $? missing_kernel
469 }
470
471 # Populate the variable part of the floppy filesystem. Must be done before
472 # the MFS because its content might need to be copied there as well.
473 #
474 # This involves fetching files from three subtrees, in this order:
475 #
476 #  1. a standard one, from which type-specific files are excluded;
477 #  2. a type-specific one;
478 #  3. a site-specific one.
479 #
480 # Files are first copied to a local tree and then compressed.
481
482 populate_floppy_fs() {          # OK
483     local dst excl srcdir
484
485     log "populate_floppy_fs()"
486     dst=${BUILDDIR}/floppy.tree
487     log "pwd=`pwd` Populating floppy filesystem..."
488
489     rm -rf ${dst} || true       # clean relics from old compilations.
490     mkdir ${dst}                # create a clean tree
491
492     # compute exclude list for generic tree
493     excl=${MY_TREE}/floppy.tree.exclude
494     if [ -f ${excl} ] ; then
495         log "Files excluded from generic tree: `echo;cat ${excl}`"
496         excl="--exclude-from ${excl}"
497     else
498         excl=""
499     fi
500     # copy from the floppy trees into the destination
501     for FLOPPY_TREE in ${PICO_TREE}/floppy.tree ${MY_TREE}/floppy.tree \
502                 ${MY_TREE}/floppy.tree.${SITE} ; do
503         if [ -d ${FLOPPY_TREE} ] ; then
504             (cd ${FLOPPY_TREE} ; tar -cf - --exclude CVS \
505                     --exclude .svn ${excl} . ) | \
506                 (cd ${dst} ; tar x${o_tarv}f - )
507             log "Copied from ${FLOPPY_TREE}"
508         fi
509         excl="" # reset the exclude list.
510     done
511
512     # add local manipulation
513     if [ -f ${MY_TREE}/buildtree.mk ] ; then
514         log "building local floppy tree"
515         ${BINMAKE} -C ${dst} -f ${MY_TREE}/buildtree.mk floppy.tree
516     fi
517  
518     # compress the files in etc/, just in case
519     # XXX this should be done in the makefile.
520     # gzip returns an error if it fails to compress some file
521     (cd $dst ; gzip -9 etc/*
522             log "Compressed files in etc/ `echo; ls -l etc`"
523     ) || true
524 }
525
526 # Copy the specified files to the destination filesystem.
527 # Each file is specified as a pair "src dst", dst is assumed to be
528 # a directory (and created with mkdir -p) if it has a trailing /
529 # Be careful to escape metacharacters.
530 # You can use ${CROSS} to point to the root of the cross build
531 # (remember that it might be incomplete)
532
533 do_copyfiles() {        # rootdir varname
534         log Copy files to $1
535         local root=$1
536         local srcs dst
537         local CROSS=${_SHLIBDIRPREFIX}
538         eval set "\${${2}}"
539         srcs=""
540         for dst in $* ; do
541                 [ -z "$srcs" ] && srcs=$dst && continue
542                 eval srcs="$srcs"       # expand wildcard and vars
543                 case x"$dst" in
544                 */ )    mkdir -p ${root}/${dst} ;;
545                 # * )   mkdir -p `dirname ${root}/${dst}` ;;
546                 esac
547                 cp -p ${srcs} ${root}/${dst} || true
548                 srcs=""
549         done
550 }
551
552 # do_links is a helper function to create links between programs
553 # in stand/
554 # This is done reading the names and destination from variable
555 # links in a config file, in the format
556 #       : dst names
557
558 do_links() {    # rootdir varname
559         local root=$1
560         local l i dst
561         eval l="\${${2}}"
562         dst=""
563         log "Create links for ${l}"
564         (cd ${root}/stand
565         for i in $l ; do
566             if [ "$dst" = ":" -o "$i" = ":" ] ; then
567                 dst=$i
568             elif [ -n "${dst}" ] ; then
569                 ln -s ${dst} ${i}
570             fi
571         done
572         )
573 }
574
575 # find_progs is a helper function to locate the named programs
576 # or libraries in ${o_objdir} or ${_SHLIBDIRPREFIX},
577 # and return the full pathnames.
578 # Sets ${u_progs} to the list of programs, and ${u_libs}
579 # to the list of shared libraries used.
580 #
581 # You can use it e.g. in a local configuration file by writing
582 #
583 #  do_copyfiles_user() {
584 #       local dst=$1
585 #       find_progs nvi sed less grep
586 #       cp -p ${u_progs} ${dst}/bin
587 #       cp -p ${u_libs} ${dst}/lib
588 #       mkdir -p ${dst}/libexec
589 #       find_progs ld-elf.so.1
590 #       cp -p ${u_progs} ${dst}/libexec
591 #  }
592
593 find_progs() {  # programs
594         local i
595         u_progs="`find_progs_helper $*`"
596         local o=${o_objdir:-${_SHLIBDIRPREFIX}}
597         [ -z "${u_progs}" ] && return 1 # not found, error
598         i="`ldd ${u_progs} | grep -v '^/' | awk '{print $1}' | sort | uniq`"
599         u_libs="`find_progs_helper $i`"
600         return 0
601 }
602
603 find_progs_helper() {   # programs
604         local progs="$*"
605         local i o places names
606         local subdirs="bin sbin usr.bin usr.sbin libexec lib \
607                 gnu/usr.bin gnu/lib \
608                 secure/usr.bin secure/usr.sbin secure/libexec secure/lib"
609         names=""        # files to search
610         o=""
611         for i in $progs ; do
612                 # plain programs come out verbatim
613                 [ -f "$i" ] && echo $i && continue
614                 names="${names} ${o} -name $i"
615                 o="-o"
616         done
617         [ -z "${names}" ] && return 0
618         places=""                               # places to search
619         o=${o_objdir:-${_SHLIBDIRPREFIX}/..}
620         for i in $subdirs ; do
621                 [ -d "${o}/${i}" ] && places="${places} ${o}/${i}"
622         done
623         find ${places} -type f \( ${names} \)
624 }
625
626 # Populate the memory filesystem with binaries and non-variable
627 # configuration files.
628 # First do an mtree pass, then create directory links and device entries,
629 # then run crunchgen etc. to build the binary and create links.
630 # Then copy the specific/generic mfs_tree.
631 # Finally, if required, make a copy of the floppy.tree onto /fd
632
633 populate_mfs_tree() {
634     local i j a dst MFS_TREE
635
636     log "populate_mfs_tree()"
637     dst=${BUILDDIR}/mfs.tree
638     rm -rf ${dst} || true       # clean relics from old compilations.
639     mkdir ${dst}                # create a fresh tree
640
641     log "pwd=`pwd`, Populating MFS tree..."
642
643     # use type-specific mfs.mtree, default to generic one.
644     a=${MY_TREE}/mfs.mtree
645     [ -f ${a} ] || a=${PICO_TREE}/build/mfs.mtree
646     log "Running mtree using $a..."
647     mtree -deU -f $a -p ${dst} > /dev/null || fail $? mtree
648
649     # Create symlinks using relative pathnames, so it is possible
650     # to follow them also when building the image.
651     # Note that names in STAND_LINKS should not have a leading /
652     for i in ${STAND_LINKS}; do
653         j=`echo $i | sed -E 's:^[^/]+::;s:/[^/]+:../:g'`
654         ln -s ${j}stand ${dst}/$i
655     done
656     ln -s ../../dev/null ${dst}/var/run/log
657     ln -s ../../../etc/termcap ${dst}/usr/share/misc/termcap
658
659     ### now build the crunched binaries ###
660     (
661     cd ${BUILDDIR}/crunch
662     log "Making and installing crunch1 from `pwd` src ${SRC}..."
663     a=${BUILDDIR}/crunch1.conf
664     ( export BUILDDIR SRC MY_TREE PICO_OBJ ;
665         ${BINMAKE} \
666                 -v -f ${PICO_TREE}/build/Makefile.conf ${BUILDDIR}/crunch.mk )
667     log "Libs are ${LIBS} "
668     export SRC # used by crunch.mk
669     # export LIBS CFLAGS
670     log "Now make -f crunch.mk"
671     ${BINMAKE} ${o_makeopts} -f ${BUILDDIR}/crunch.mk
672     strip --remove-section=.note --remove-section=.comment crunch1
673     mv crunch1 ${dst}/stand/crunch
674     chmod 555 ${dst}/stand/crunch
675     log "Making links for binaries..."
676     for i in `crunchgen -l $a` ; do
677         ln ${dst}/stand/crunch ${dst}/stand/${i};
678     done
679     # rm $a # do not remove!
680     ) || fail $? crunch
681
682     if [ -f ${dst}/stand/sshd ] ; then
683         log "Setting up host key for sshd:"
684         if [ -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key.gz ] ; then
685             log "Using existing host key"
686         else
687             log "Generating new host key" 
688             ssh-keygen -t rsa1 -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key \
689                  -N "" -C "root@picobsd"
690             gzip -9 ${BUILDDIR}/floppy.tree/etc/ssh_host_key* || true
691         fi
692     fi
693
694     log "Copy generic and site-specific MFS tree..."
695     for MFS_TREE in ${PICO_TREE}/mfs_tree ${MY_TREE}/mfs_tree ; do
696         if [ -d ${MFS_TREE} ] ; then
697             log "Copy ${MFS_TREE} ..."
698             (cd ${MFS_TREE} ; tar -cf - --exclude CVS --exclude .svn . ) | \
699                     (cd ${dst} ; tar x${o_tarv}f - )
700         fi
701     done
702
703     if [ -f ${MY_TREE}/buildtree.mk ] ; then
704         log "building local floppy tree"
705         ${BINMAKE} -C ${dst} -f ${MY_TREE}/buildtree.mk mfs.tree
706     fi
707
708     if [ "${o_all_in_mfs}" = "yes" ]; then
709         log "Copy generic floppy_tree into MFS..."
710         # ignore failure in case the floppy is empty
711         cp -Rp ${BUILDDIR}/floppy.tree/* ${dst}/fd || true
712     fi
713
714     # 4.x compatibility - create device nodes
715     if [ -n "${o_no_devfs}" ] ; then
716         # create device entries using MAKEDEV
717         (cd ${dst}/dev
718         ln -s ${SRC}/etc/MAKEDEV ; chmod 555 MAKEDEV
719         # log `pwd`
720         sh ./MAKEDEV ${MY_DEVS}
721         rm MAKEDEV
722         )
723     fi
724     if [ "`id -u`" = "0" ] ; then
725         log "Fixing permissions"
726         (cd ${dst}; chown -R root . )
727     fi
728
729     # If we are building a shared 'crunch', take the libraries
730     # and the dynamic loader as well
731     find_progs ${dst}/stand/crunch
732     if [ -n "${u_libs}" ] ; then
733         mkdir -p ${dst}/lib && cp -p ${u_libs} ${dst}/lib
734         mkdir -p ${dst}/libexec
735         create_includes_and_libraries2 libexec/rtld-elf
736         find_progs ld-elf.so.1 && cp -p ${u_progs} ${dst}/libexec
737     fi
738
739     [ -n "${copy_files}" ] && do_copyfiles ${dst} copy_files
740     do_copyfiles_user ${dst} || true
741     [ -n "${links}" ] && do_links ${dst} links
742     strip ${dst}/libexec/* ${dst}/lib/* ${dst}/stand/* 2> /dev/null || true
743
744     # The 'import_files' mechanism is deprecated, as it requires
745     # root permissions to follow the symlinks, and also does
746     # not let you rename the entries.
747     if [ -n "${import_files}" ] ; then
748         log "importing ${import_files} into mfs"
749         # We do it in a chroot environment on the target so
750         # symlinks are followed correctly.
751         # Make sure we have a statically linked tar there.
752         mkdir -p ${dst}/rescue
753         cp /rescue/tar ${dst}/rescue
754         (cd ${l_usrtree}/.. ; tar cf - ${import_files} ) | \
755             (chroot ${dst} /rescue/tar xPf - )
756         rm -rf ${dst}/rescue
757     fi
758
759     # final step -- build the mfs image
760     (cd ${BUILDDIR}
761         # override the owner
762         echo "/set uid=0 gid=0" > mtree.out
763         mtree -ic -p ${dst} -k "" >> mtree.out
764         log "mtre.out at ${BUILDDIR}/mtree.out"
765         makefs -t ffs -o bsize=4096 -o fsize=512 \
766                 -s ${MFS_SIZE}k -f 1000 -F mtree.out ${c_fs} ${dst}
767         ls -l ${c_fs} )
768     log "done mfs image"
769 }
770
771 final_cleanup() {
772     log "final_cleanup()"
773     rm -rf ${c_mnt} ${c_reply} 2> /dev/null || true
774     rm -f ${c_reply}
775 }
776
777 # fail errno errcode
778 # This function is used to trap errors and print msgs
779 #
780 fail() {
781     local errno errocode where
782
783     errno=$1
784     errcode=$2
785     where=$3
786     echo "---> fail: Error <${errno}> error code <${errcode}> in <${where}>"
787     case ${errcode} in
788     mtree)
789         echo "Error while making hierarchy in ${c_mnt}"
790         ;;
791     crunch)
792         echo "Error while building ${name}."
793         ;;
794     missing_kernel)
795         echo "Error: you must build PICOBSD${suffix} kernel first"
796         ;;
797     includes)
798         echo "Error: failed while making includes"
799         ;;
800     libraries)
801         echo "Error: failed while making libraries"
802         ;;
803     bad_type)
804         echo "Error: unknown floppy type ${name}"
805         ;;
806     no_space)
807         echo "Error: no space left on device (${where})"
808         ;;
809     no_mfs)
810         echo "Error: while writing MFS into the kernel."
811         ;;
812     "")
813         echo "User break"
814         errcode="userbreak"
815         ;;
816     *)
817         echo "unknown error, maybe user break: $errno $errcode"
818         ;;
819     esac
820     echo "---> Aborting $0"
821     # try to cleanup the vnode.
822     final_cleanup
823     exit 2
824 }
825
826 fill_floppy_image() {
827     local blocks dst mfs_start mfs_end mfs_size img_size
828
829     log "fill_floppy_image()"
830     dst=${c_mnt}        # where to create the image
831
832     log "Preparing ${fd_size}kB floppy filesystem..."
833
834     # correct blocks according to size.
835     blocks=${fd_size};
836     if [ "${blocks}" = "1720" ]; then
837         blocks=1722
838     elif [ "${blocks}" = "1480" ]; then
839         blocks=1476
840     fi
841
842     log "Labeling floppy image"
843     b2=${BUILDDIR}/boot2 # modified boot2
844     cp -f ${c_boot2} ${b2}
845     chmod 0644 ${b2}
846
847     if [ ${o_use_loader} = "no" ] ; then
848         log "patch ${c_boot2} to boot /kernel right away"
849         set `strings -at d ${b2} | grep "/boot/loader"`
850         echo -e "/kernel\0\0\0\0\0" | \
851             dd of=${b2} obs=$1 oseek=1 conv=notrunc 2>/dev/null
852     fi
853     chmod 0444 ${b2}
854
855     dst=${BUILDDIR}/image.tree
856     rm -rf ${dst}
857     mkdir -p ${dst}
858     (
859     cd ${BUILDDIR}
860     set 0 0 # reset variables
861     # $1 takes the offset of the MFS filesystem
862     set `strings -at d kernel | grep "MFS Filesystem goes here"`
863     mfs_start=$1
864     set 0 0 # reset variables
865     set `strings -at d kernel | grep "MFS Filesystem had better"`
866     mfs_end=$1
867     mfs_size="$((${mfs_end} - ${mfs_start}))"
868     set -- `ls -l ${c_fs}`; imgsize="$5"
869     if [ ${mfs_start} -gt 0 -a ${mfs_size} -ge ${imgsize} ] ; then
870         mfs_ofs=$((${mfs_start} + 8192))
871         log "Preload kernel with file ${c_fs} at ${mfs_ofs}"
872         logverbose "`ls -l ${c_fs}` to fit in ${mfs_size}"
873         dd if=${c_fs} ibs=8192 iseek=1 of=kernel obs=${mfs_ofs} \
874             oseek=1 conv=notrunc # 2> /dev/null
875     else
876         log "not loading mfs, size ${mfs_size} img ${imgsize}"
877     fi
878     log "Compress with kgzip and copy to floppy image"
879     if [ ${o_use_loader} = "no" ] ; then
880         kgzip -o kernel.gz kernel
881         cp -p kernel.gz ${dst}/kernel || fail $? no_space "copying kernel"
882     else
883         gzip kernel
884         mkdir -p  ${dst}/boot/kernel
885         echo "hint.acpi.0.disabled=\"1\"" > ${dst}/boot/loader.conf
886         echo "console=\"comconsole\"" >> ${dst}/boot/loader.conf
887         cp -p /boot/loader ${dst}/boot/loader || fail $? no_space "copying bootloader"
888         cp -p kernel.gz ${dst}/boot/kernel/kernel.gz || fail $? no_space "copying kernel"
889     fi
890
891     # now transfer the floppy tree. If it is already in mfs, dont bother.
892     if [ "${o_all_in_mfs}" != "yes" ] ; then
893         log "Now transfer floppy tree if not already in MFS image"
894         cp -Rp floppy.tree/* ${dst} || \
895                 fail $? no_space "copying floppy tree"
896     fi
897     )
898
899     # add local manipulation to the image
900     if [ -f ${MY_TREE}/buildtree.mk ] ; then
901         ${BINMAKE} -C ${dst} -f ${MY_TREE}/buildtree.mk image.tree
902     fi
903
904     log "image used `du -s ${dst}` of ${blocks}k"
905     (cd ${BUILDDIR}
906     makefs -t ffs -o bsize=4096 -o fsize=512 \
907         -s ${blocks}k -f 50 ${c_img} ${dst}
908
909     ${c_label} -w -f `pwd`/${c_img} auto # write in a label
910     # copy partition c: into a: with some sed magic
911     ${c_label} -f `pwd`/${c_img} | sed -e '/  c:/{p;s/c:/a:/;}' | \
912         ${c_label} -R -f `pwd`/${c_img} /dev/stdin
913     ${c_label} -f `pwd`/${c_img}
914
915     ls -l ${c_img}
916     ${c_label} -f `pwd`/${c_img}
917     logverbose "after disklabel"
918     )
919
920     echo "BUILDDIR ${BUILDDIR}"
921     if [ "${generate_iso}" = "YES" ]; then
922         echo "generate_iso ${generate_iso}"
923         # build_iso_image       # XXX not implemented yet
924         exit 1
925     fi
926
927     # dump the primary and secondary boot
928     # XXX primary is 512 bytes
929     dd if=${c_boot1} of=${BUILDDIR}/${c_img} conv=notrunc 2>/dev/null
930     # XXX secondary starts after the 0x114 = dec 276 bytes of the label
931     # so we skip 276 from the source, and 276+512=788 from dst
932     # the old style blocks used 512 and 1024 respectively
933
934     dd if=${b2} iseek=1 ibs=276 2> /dev/null | \
935         dd of=${BUILDDIR}/${c_img} oseek=1 obs=788 conv=notrunc 2>/dev/null
936     logverbose "done floppy image"
937     # XXX (log "Fixing permissions"; cd ${dst}; chown -R root *)
938     rm -rf ${BUILDDIR}/floppy.tree || true # cleanup
939     # df -ik ${dst} | colrm 70 > .build.reply
940     rm -rf ${dst}
941     rm ${BUILDDIR}/${c_fs}
942     # rm ${BUILDDIR}/kernel.gz
943 }
944
945 # This function creates variables which depend on the source tree in use:
946 # SRC, l_usrtree, l_objtree
947 # Optionally creates libraries, includes and the like (for cross compiles,
948 # needs to be done once).
949
950 set_build_parameters() {
951     if [ "${SRC}" = "/usr/src" ] ; then
952         l_usrtree=${USR:-/usr}
953     else
954         l_usrtree=${USR:-${SRC}/../usr}
955     fi
956     l_objtree=${l_usrtree}/obj-pico
957     PICO_TREE=${PICO_TREE:-${SRC}/release/picobsd}
958     set `grep "#define[\t ]__FreeBSD_version" ${SRC}/sys/sys/param.h`
959     OSVERSION=$3
960     log "OSVERSION is ${OSVERSION}"
961     if [ "${o_init_src}" != "" ] ; then
962         if [ ${OSVERSION} -lt 500035 ] ; then
963             create_includes_and_libraries
964         else
965             create_includes_and_libraries2
966         fi
967     fi
968     if [ ${OSVERSION} -lt 500035 ] ; then
969         # Create the right LIBS and CFLAGS for further builds.
970         # and build the config program
971         LIBS="-L${l_usrtree}/lib"
972         CFLAGS="-nostdinc -I${l_usrtree}/include"
973         export LIBS CFLAGS
974         CONFIG=${l_usrtree}/sbin/config
975         export CONFIG
976     fi
977
978     # if we have o_objdir, find where bin/ is
979     if [ ! -z "${o_objdir}" ] ; then
980         if [ -d ${o_objdir}/bin ] ; then
981             # fine
982         elif [ -d "${o_objdir}${SRC}/bin" ] ; then
983             o_objdir="${o_objdir}${SRC}"
984             log "Changing objdir to ${o_objdir}"
985         else
986             log "Cannot find objdir in ${o_objdir}, sorry"
987             o_objdir=""
988         fi
989     fi
990 }
991
992 #-------------------------------------------------------------------
993 # Main entry of the script. Initialize variables, parse command line
994 # arguments.
995
996 set_defaults
997 while [ true ]; do
998     log "Parsing $1"
999     case $1 in
1000     --src)      # set the source path instead of /usr/src
1001         SRC=`realpath $2`
1002         shift
1003         ;;
1004     --init)
1005         o_init_src="YES"
1006         ;;
1007
1008     --floppy_size)
1009         fd_size=$2
1010         shift
1011         ;;
1012
1013     --no_loader)        # omit /boot/loader, just rely on boot2
1014                         # (it may have problems with kernels > 4MB)
1015         o_use_loader="no"
1016         ;;
1017
1018     --all_in_mfs)
1019         o_all_in_mfs="yes"
1020         ;;
1021
1022     --no_all_in_mfs)
1023         o_all_in_mfs="no"
1024         ;;
1025
1026     --modules)  # also build kernel modules
1027         o_do_modules="yes"
1028         ;;
1029     -n)
1030         o_interactive="NO"
1031         ;;
1032
1033     -clear|-clean|-c) # clean
1034         o_clean="YES"
1035         o_interactive="NO"
1036         ;;
1037
1038     -v) # need -v -v to wait for user input
1039         o_verbose=$((${o_verbose}+1))   # verbose level
1040         o_tarv="v"                      # tar verbose flag
1041         o_makeopts="-d l" # be verbose
1042         ;;
1043
1044     --iso) # generate iso image
1045         generate_iso="YES"
1046         ;;
1047
1048     --cfg) # read additional config from this file
1049         o_additional_config=`realpath $2`
1050         shift
1051         ;;
1052
1053     --objdir)   # Place with results of a previous buildworld
1054                 # useful if you want to copy shared binaries and libs
1055         o_objdir=`realpath $2`
1056         shift
1057         ;;
1058
1059     *)
1060         break
1061         ;;
1062
1063     esac
1064     shift
1065 done
1066
1067 set_build_parameters    # things that depend on ${SRC}
1068 set_type $1 $2          # type and site, respectively
1069
1070 [ "${o_interactive}" != "NO" ] && main_dialog
1071
1072 if [ "${o_clean}" = "YES" ] ; then
1073     clean_tree
1074 else
1075     build_image
1076     do_install
1077 fi
1078 final_cleanup
1079 exit 0