#!/bin/sh - # # $FreeBSD$ # This file requires sysutils/makefs to run # # The PicoBSD build script. Invoked as # # picobsd [options] image_type [site_name] # # CWARNFLAGS can be used to pass -Wall or similar options # # Where image_type is a directory with the picobsd config info, # and ${image_type}/floppy.tree.${site_name} contains # optional site-specific configuration. # # For Options, see the bottom of the file where the processing is # done. The picobsd(8) manpage might be of some help, but code and docs # tend to lose sync over time. # # This script depends on the following files: # # in ${PICO_TREE} : # Makefile.conf Makefile used to build the kernel # config shell variables, sourced here. # mfs.mtree mtree config file # floppy.tree/ files which go on the floppy # mfs_tree/ files which go onto the mfs # # in ${MY_TREE} : # PICOBSD kernel config file # config shell variables, sourced here. # crunch.conf crunchgen configuration # mfs.mtree overrides ${PICO_TREE}/mfs.mtree # floppy.tree.exclude files from floppy.tree/ which we do not need here. # floppy.tree/ local additions to ${PICO_TREE}/mfs_free # floppy.tree.${site}/ same as above, site specific. # mfs_tree/ local additions to the mfs_free # buildtree.mk optional Makefile to build an extension for floppy tree # (generated in buildtree/ ) # #--- The main entry point is at the end. # # There are two initialization functions: # # + set_defaults # is run on entry to the script, and is used to set default values # for all variables that do not depend on image type and source tree. # # + set_build_parameters # is run after command line parsing # # VARIABLE NAMES: # + variables that control operation (e.g. verbosity) and are generally # set from the command line have o_ ("option") as a name prefix # # + variables that contain pathnames and values that should not change # have c_ ("constant") as a name prefix # # + variables exported to Makefiles and subshells are CAPITAL # # + variables local to the script are lowercase, possibly with # an l_ ("local") prefix. # # There are unfortunately exceptions: # name, l_usrtree, l_objtree # SRC points to your FreeBSD source tree. # l_usrtree points to the /usr subdir for the source tree. # Normally /usr or ${SRC}/../usr # l_objtree points to the obj tree. Normally ${l_usrtree}/obj-pico-${o_arch} # c_label is either bsdlabel or disklabel # PICO_TREE is where standard picobsd stuff resides. # Normally ${SRC}/release/picobsd # You can set SRC with --src # It is not recommended to override the other variables. # MY_TREE (set later) is where this floppy type resides. # BUILDDIR is the build directory # log something on stdout if verbose. o_verbose=0 # this needs to be here! log() { # message local foo [ ${o_verbose} -gt 0 ] && printf "\n*** %s\n" "$*" [ ${o_verbose} -gt 1 ] && read -p "=== Press enter to continue" foo return 0 } # unconditionally log and wait for input logverbose() { # message local foo printf "\n*** %s\n" "$*" read -p "=== Press enter to continue" foo return 0 } # set some default values for variables. # needs to be done as the first thing in the script. set_defaults() { # no arguments # EDITOR is the editor you use # fd_size floppy size in KB (default to 1440). You can use 1480, # 1720, 2880, etc. but beware that only 1440 and 1480 will boot # from 1.44M floppy drives (1480 will not work on vmware). EDITOR=${EDITOR:-vi} fd_size=${fd_size:-1440} o_all_in_mfs="yes" # put all files in mfs so you can boot # and run the image via diskless boot. o_clean="" # set if you want to clean prev.builds. o_interactive="" # default is interactive o_verbose=0 # verbose level, 0 is silent o_tarv="" # tar verbose flag, "" or "v" o_init_src="" # set to build libs and includes. o_makeopts=${MAKEOPTS:--s} # make options, be silent by default o_no_devfs= # default is use devfs. # You should only set it when building 4.x images o_do_modules="" # do not build modules o_arch=`uname -m` # default to amd64 or i386 ... SRC="/usr/src" # default location for sources c_startdir=`pwd` # directory where we start # used to lookup config and create BUILDDIR # XXX 6.x/7.x have a single /boot/boot block, which is the concatenation # of the old two. For the time being, we keep these, but this should # be fixed at some point. # blocks c_boot1=/boot/boot1 # boot blocks (in case you want custom ones) c_boot2=/boot/boot2 c_reply=${c_reply:-`mktemp "/tmp/reply.XXXXXXXXXX"`} # file where User replies will be put c_mnt=`mktemp -d "/tmp/picobsd.XXXXXXXXXX"` # mountpoint used to build memory filesystems c_fs=fs.PICOBSD # filename used for the memory filesystem c_img=picobsd.bin # filename used for the picobsd image c_iso=picobsd.iso # filename used for the ISO image generate_iso="NO" # don't generate the iso image # select the right disklabel program case `uname -r` in 4.*) c_label="disklabel" ;; *) c_label="bsdlabel" ;; esac set -e trap fail 2 #trap fail 3 #trap fail 6 trap fail 15 } # use the new build infrastructure to create libraries # and also to build a specific target create_includes_and_libraries2() { # opt_dir opt_target local no log "create_includes_and_libraries2() for ${SRC} $1" if [ ${OSVERSION} -ge 600000 ] ; then no="-DNO_CLEAN -DNO_PROFILE -DNO_GAMES -DNO_LIBC_R" # WITHOUT_CDDL=1" no="$no -DWITHOUT_CLANG -DMALLOC_PRODUCTION" else no="-DNOCLEAN -DNOPROFILE -DNOGAMES -DNOLIBC_R" fi ( cd ${SRC}; # make -DNOCLEAN -DNOPROFILE -DNOGAMES -DNOLIBC_R -DPICOBSD buildworld if [ -d "$1" ] ; then cd $1 ; ${BINMAKE} ${o_par} $2 # specific target, e.g. ld-elf.so else MAKEOBJDIRPREFIX=${l_objtree} export MAKEOBJDIRPREFIX # export WITH_RESCUE=yes # build crunchide # ${BINMAKE} ${o_par} _+_= $no toolchain _includes _libraries ( # eval export `cd ${SRC}; ${BINMAKE} -f Makefile.inc1 -V BMAKEENV` eval "export XMAKE=\"`cd ${SRC}; make -f Makefile -V XMAKE`\"" ${BINMAKE} ${o_par} _+_= $no toolchain ) eval export `cd ${SRC}; ${BINMAKE} -f Makefile.inc1 -V WMAKEENV` ${BINMAKE} ${o_par} _+_= $no _includes _libraries [ ${o_arch} != `uname -m` ] && \ (cd ${l_objtree}; ln -s . ${o_arch}.${o_arch} || true ) fi ) } # entry for 4.x and earlier trees create_includes_and_libraries() { local e i log "create_includes_and_libraries() for ${SRC}" # Optionally creates include directory and libraries. mkdir -p ${l_usrtree}/include # the include directory... mkdir -p ${l_usrtree}/share/misc # a few things go here mkdir -p ${l_usrtree}/lib # libraries mkdir -p ${l_usrtree}/sbin # some binaries # override variables for ownershiip and destinations # BINOWN:BINGRP are also used for include files (cd ${SRC}; \ BINOWN=`id -un` BINGRP=`id -gn` \ DESTDIR=${l_usrtree}/.. \ make -m ${SRC}/share/mk includes ) || fail $? includes # Pick up the correct headers for libraries. CFLAGS="-nostdinc -I${l_usrtree}/include" ; export CFLAGS (cd ${SRC} # $e is the invocation of make with correct environment # XXX check the NO* options below, maybe system dependent. e="MAKEOBJDIRPREFIX=${l_objtree}/picobsd/libraries \ BINOWN=`id -un` BINGRP=`id -gn` \ DESTDIR=${l_usrtree}/.. \ make -m ${SRC}/share/mk \ -DNOHTML -DNOINFO -DNOMAN -DNOSHARE -DNOFSCHG " log "do a 'make obj' in a few places." # This is very version-specific... The following works for 5.0 for i in lib secure/lib gnu/lib \ gnu/usr.bin/perl usr.bin/lex usr.sbin/config ; do (cd ${i}; eval $e obj) done log "now make the static libraries" eval $e -DNOPROFILE -DNOPIC libraries (cd ${SRC}/usr.sbin/config eval $e # build binary eval $e install # install it ) ) || fail $? "libraries" log "Libraries done" } # set_type [the_site] looks in user or system directories # for the directory named as the first argument, reads the configuration # files and sets variables according to the config. # Also sets MY_TREE and BUILDDIR and SITE set_type() { # the_type the_site local a i log "set_type() : Type '$1' site '$2'" THETYPE=$1 SITE=$2 a=$1 name="" # clear in case of errors for i in ${c_startdir}/${a} ${PICO_TREE}/${a} ; do log "set_type: checking $i" [ -d $i -a -f $i/crunch.conf ] || continue # look for a kernel config file, privilege arch-specific l_kernconf=$i/PICOBSD.${o_arch} [ -f $l_kernconf ] || l_kernconf=$i/PICOBSD [ -f $l_kernconf ] || continue set -- `cat $l_kernconf | \ awk '/^#PicoBSD/ {print $2, $3, $4, $5, $6}'` [ x"$1" != "x" ] || continue MFS_SIZE=$1 name=`(cd $i ; pwd) ` name=`basename $name` MY_TREE=$i BUILDDIR=${c_startdir}/build_dir-${name}-${o_arch} log "Matching file $name in $i" return ; done logverbose "Type $a NOT FOUND" } clean_tree() { log "clean_tree()" if [ -z "${name}" ] ; then echo "---> Wrong floppy type" exit 3 fi rm -rf ${BUILDDIR} } # prepare a message to be printed in the dialog menus. set_msgs() { # OK log "set_msgs()" MSG1="Type: ${THETYPE} name $name" MSG="PicoBSD build -- Current parameters:\n\n\t1. ${MSG1}\n\ \t2. MFS size: ${MFS_SIZE} kB\n\ \t3. Site-info: ${SITE}\n\t4. Full-path: ${MY_TREE}\n" } # Main build procedure. Builds both the disk image and the ISO build_image() { log "build_image() <${name}>" [ -n "${name}" ] || fail $? bad_type clear set_msgs printf "${MSG}---> We'll use the sources living in ${SRC}\n\n" # read config variables from a global and then a type-specific file # basically STAND_LINKS and MY_DEVS, but can also override other # variables. # . ${PICO_TREE}/build/config [ -f "${MY_TREE}/config" ] && . ${MY_TREE}/config [ -f "${o_additional_config}" ] && . ${o_additional_config} # location of the object directory PICO_OBJ=${l_objtree}/picobsd/${THETYPE} log "PICO_OBJ is ${PICO_OBJ}" # create build directory and subtree mkdir -p ${BUILDDIR}/crunch # remove any old stuff rm -f ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs} # invoke commands to build a kernel do_kernel # fill a subdirectory with things that go into the floppy # (mostly /etc and similar stuff) populate_floppy_fs # populate it and produce a file with the MFS image populate_mfs_tree # things which go into mfs # create, mount and fill a filesystem with floppy image fill_floppy_image # copies everything into the floppy } # Set build parameters interactively main_dialog() { local ans i l log "main_dialog()" while true ; do set_msgs rm ${c_reply} dialog --menu "PicoBSD build menu -- (29 sep 2001)" 19 70 12 \ N "--> READY, build it <---" \ T "${MSG1}" \ K "edit Kernel config file" \ E "Edit crunch.conf file" \ S "MFS Size: ${MFS_SIZE}kB" \ F "Floppy size: ${fd_size}kB" \ $ "Site-info: ${SITE}" \ Q "Quit" \ 2> ${c_reply} ans=`cat ${c_reply}` rm ${c_reply} case ${ans} in T) l="" for i in ${c_startdir} ${c_startdir}/* ${PICO_TREE}/* ; do if [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ]; then l="$l `basename $i` `basename $i`" fi done log $l { dialog --menu "Setup the type of configuration" 12 70 5 $l \ 2> ${c_reply} && set_type "`cat ${c_reply}`" ${SITE} ; } || true ;; K) ${EDITOR} ${MY_TREE}/PICOBSD ;; E) ${EDITOR} ${MY_TREE}/crunch.conf ;; S) { dialog --title "MFS Size setup" --inputbox \ "MFS size depends on what you need to put on the MFS image. Typically \ ranges between 820kB (for very small bridge/router images) to \ as much as 2500kB kB for a densely packed image. \ Keep in mind that this memory is \ totally lost to other programs. Usually you want to keep \ this as small as possible. " 10 70 2> ${c_reply} \ && MFS_SIZE=`cat ${c_reply}` ; } || true ;; \$) { dialog --title "Site info setup" --inputbox \ "Please enter the full path to the directory \ containing site-specific setup. \ This directory tree must contain files that replace \ standard ones in floppy.tree/ and mfs.tree/ . " \ 10 70 2> ${c_reply} && SITE=`cat ${c_reply}` ; } || true ;; F) { dialog --menu "Set floppy size" 15 70 4 \ 1440 "1.44MB" 1720 "1.72MB" 2880 "2.88MB" 4096 "4MB" \ 2> ${c_reply} && fd_size=`cat ${c_reply}` ; } || true ;; N) break 2 ;; Q) exit 0 ;; *) echo "Unknown option \"${ans}\". Try again." sleep 2 clear ;; esac done } # Call the build procedure # Install image do_install() { log "do_install()" if [ "${o_interactive}" = "NO" ] ; then echo "+++ Build completed +++" cat .build.reply || true return fi dialog --title "Build ${THETYPE} completed" --inputbox \ "\nThe build process was completed successfuly.\n\ `cat .build.reply` \n\n\ Now we are going to install the image on the floppy.\n\ Please insert a blank floppy in /dev/fd0.\\n WARNING: the contents of the floppy will be permanently erased!\n\ \n\ Your options:\n\ * ^C or [Cancel] to abort,\n\ * Enter to install ${c_img},\n\ " 20 80 2> ${c_reply} if [ "$?" = "0" ]; then echo "Writing ${c_img}..." dd if=${BUILDDIR}/${c_img} of=/dev/fd0.${fd_size} else echo "Ok, the image is in ${c_img}" fi echo "Done." } #------------------------------------------------------------------- # invoke the picobsd Makefile to compile the kernel. # if MODULES is set (value is irrelevant) the makefile will build modules. do_kernel() { # OK log "do_kernel() Preparing kernel \"$name\" in $MY_TREE" (cd $MY_TREE; export name SRC BUILDDIR # used in this makefile ; # export CONFIG export WARNS CWARNFLAGS [ "${o_do_modules}" = "yes" ] && export MODULES="" ${BINMAKE} ${o_par} KERNCONF=${l_kernconf} \ -v -f ${PICO_TREE}/build/Makefile.conf ) || \ fail $? missing_kernel } # Populate the variable part of the floppy filesystem. Must be done before # the MFS because its content might need to be copied there as well. # # This involves fetching files from three subtrees, in this order: # # 1. a standard one, from which type-specific files are excluded; # 2. a type-specific one; # 3. a site-specific one. # # Files are first copied to a local tree and then compressed. populate_floppy_fs() { # OK local dst excl srcdir log "populate_floppy_fs()" dst=${BUILDDIR}/floppy.tree log "pwd=`pwd` Populating floppy filesystem..." rm -rf ${dst} || true # clean relics from old compilations. mkdir ${dst} # create a clean tree # compute exclude list for generic tree excl=${MY_TREE}/floppy.tree.exclude if [ -f ${excl} ] ; then log "Files excluded from generic tree: `echo;cat ${excl}`" excl="--exclude-from ${excl}" else excl="" fi # copy from the floppy trees into the destination for FLOPPY_TREE in ${PICO_TREE}/floppy.tree ${MY_TREE}/floppy.tree \ ${MY_TREE}/floppy.tree.${SITE} ; do if [ -d ${FLOPPY_TREE} ] ; then (cd ${FLOPPY_TREE} ; tar -cf - --exclude CVS \ --exclude .svn ${excl} . ) | \ (cd ${dst} ; tar x${o_tarv}f - ) log "Copied from ${FLOPPY_TREE}" fi excl="" # reset the exclude list. done # add local manipulation if [ -f ${MY_TREE}/buildtree.mk ] ; then log "building local floppy tree" ${BINMAKE} -C ${dst} -f ${MY_TREE}/buildtree.mk floppy.tree fi # compress the files in etc/, just in case # XXX this should be done in the makefile. # gzip returns an error if it fails to compress some file (cd $dst ; gzip -9 etc/* log "Compressed files in etc/ `echo; ls -l etc`" ) || true } # Copy the specified files to the destination filesystem. # Each file is specified as a pair "src dst", dst is assumed to be # a directory (and created with mkdir -p) if it has a trailing / # Be careful to escape metacharacters. # You can use ${CROSS} to point to the root of the cross build # (remember that it might be incomplete) do_copyfiles() { # rootdir varname log Copy files to $1 local root=$1 local srcs dst local CROSS=${_SHLIBDIRPREFIX} eval set "\${${2}}" srcs="" for dst in $* ; do [ -z "$srcs" ] && srcs=$dst && continue eval srcs="$srcs" # expand wildcard and vars case x"$dst" in */ ) mkdir -p ${root}/${dst} ;; # * ) mkdir -p `dirname ${root}/${dst}` ;; esac cp -p ${srcs} ${root}/${dst} || true srcs="" done } # do_links is a helper function to create links between programs # in stand/ # This is done reading the names and destination from variable # links in a config file, in the format # : dst names do_links() { # rootdir varname local root=$1 local l i dst eval l="\${${2}}" dst="" log "Create links for ${l}" (cd ${root}/stand for i in $l ; do if [ "$dst" = ":" -o "$i" = ":" ] ; then dst=$i elif [ -n "${dst}" ] ; then ln -s ${dst} ${i} fi done ) } # find_progs is a helper function to locate the named programs # or libraries in ${o_objdir} or ${_SHLIBDIRPREFIX}, # and return the full pathnames. # Called as "find_progs [[-L libpath] [-P binpath]] prog1 prog2 ... " # On return it sets ${u_progs} to the list of programs, and ${u_libs} # to the list of shared libraries used. # # '-L path' can be used to specify a search path for libraries # (which searches in $path/lib:$path/usr/lib:$path/usr/local/lib # '-P binpath' can be used to specify a search path for programs # (which searches in a lot of places in the subtree) # -L must be the first, followed by -P # # You can use it e.g. in a local confign file by writing # # do_copyfiles_user() { # local dst=$1 # find_progs nvi sed less grep # cp -p ${u_progs} ${dst}/bin # cp -p ${u_libs} ${dst}/lib # mkdir -p ${dst}/libexec # find_progs ld-elf.so.1 # cp -p ${u_progs} ${dst}/libexec # ignore errors # } find_progs() { # programs local pass i old_libs="" tmp o="" if [ x"$1" = "x-L" -a -d "$2" ] ; then # set lib search path o="-P $2"; shift; shift fi # Result returned in global variables u_libs="" ; u_progs="`find_progs_helper $*`" [ -z "${u_progs}" ] && return 1 # not found, error # use objdump to find libraries. Iterate to fetch recursive # dependencies. tmp="${u_progs}" ; pass=1 while [ $pass -lt 10 ] ; do pass=$(($pass + 1)) i="`objdump -x ${tmp} | \ awk '$1 == "NEEDED" { print $2 }' | sort | uniq`" if [ "$old_libs" = "$i" ] ; then log "libraries for: $my_progs ($u_progs) are ($i) $u_libs" log "--- done find_progs ---" return 0 else # logverbose "old--- $old_libs --- new +++ $i +++" fi u_libs="`find_progs_helper $o $i`" old_libs="$i" tmp="$tmp $u_libs" done log "WARNING: Too many passes, giving up" } find_progs_helper() { # programs local dir=${o_objdir:-${_SHLIBDIRPREFIX}/..} local ldir="" if [ x"$1" = "x-P" -a -d "$2" ] ; then # set path ldir=$2; shift; shift fi local progs="$*" local subdirs=". local/bin local/sbin local/lib local/libexec \ bin sbin usr.bin usr.sbin libexec lib \ gnu/usr.bin gnu/lib \ secure/usr.bin secure/usr.sbin secure/libexec secure/lib" local names="" # files to search local o="" local i for i in $progs ; do # full pathnames are just listed [ -f "$i" ] && echo $i && continue names="${names} ${o} -name $i" o="-o" done [ -z "${names}" ] && return 0 local places="" # places to search for i in $subdirs ; do [ -d "${dir}/${i}" ] && places="${places} ${dir}/${i}" done if [ -n "${ldir}" ] ; then for i in $subdirs ; do [ -d "${ldir}/${i}" ] && places="${places} ${ldir}/${i}" done fi for i in $progs ; do # full pathnames are just listed [ -f "$i" ] && echo $i && continue find ${places} -maxdepth 3 -type f -name ${i} | head -1 done # use maxdepth 3 because some libs are way down } # Populate the memory filesystem with binaries and non-variable # configuration files. # First do an mtree pass, then create directory links and device entries, # then run crunchgen etc. to build the binary and create links. # Then copy the specific/generic mfs_tree. # Finally, if required, make a copy of the floppy.tree onto /fd populate_mfs_tree() { local i j a dst MFS_TREE log "populate_mfs_tree()" dst=${BUILDDIR}/mfs.tree rm -rf ${dst} || true # clean relics from old compilations. mkdir ${dst} # create a fresh tree log "pwd=`pwd`, Populating MFS tree..." # use type-specific mfs.mtree, default to generic one. a=${MY_TREE}/mfs.mtree [ -f ${a} ] || a=${PICO_TREE}/build/mfs.mtree log "Running mtree using $a..." mtree -deU -f $a -p ${dst} > /dev/null || fail $? mtree # Create symlinks using relative pathnames, so it is possible # to follow them also when building the image. # Note that names in STAND_LINKS should not have a leading / for i in ${STAND_LINKS}; do j=`echo $i | sed -E 's:^[^/]+::;s:/[^/]+:../:g'` ln -s ${j}stand ${dst}/$i done ln -s ../../dev/null ${dst}/var/run/log ln -s ../../../etc/termcap ${dst}/usr/share/misc/termcap ### now build the crunched binaries ### ( cd ${BUILDDIR}/crunch log "Making and installing crunch1 from `pwd` src ${SRC}..." a=${BUILDDIR}/crunch1.conf ( export BUILDDIR SRC MY_TREE PICO_OBJ ; ${BINMAKE} \ -v -f ${PICO_TREE}/build/Makefile.conf ${BUILDDIR}/crunch.mk ) log "Libs are ${LIBS} " export SRC # used by crunch.mk # export LIBS CFLAGS log "Now make -f crunch.mk" ${BINMAKE} ${o_makeopts} -f ${BUILDDIR}/crunch.mk strip --remove-section=.note --remove-section=.comment crunch1 mv crunch1 ${dst}/stand/crunch chmod 555 ${dst}/stand/crunch log "Making links for binaries..." for i in `crunchgen -l $a` ; do ln ${dst}/stand/crunch ${dst}/stand/${i}; done # rm $a # do not remove! ) || fail $? crunch if [ -f ${dst}/stand/sshd ] ; then log "Setting up host key for sshd:" if [ -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key.gz ] ; then log "Using existing host key" else log "Generating new host key" ssh-keygen -t rsa1 -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key \ -N "" -C "root@picobsd" gzip -9 ${BUILDDIR}/floppy.tree/etc/ssh_host_key* || true fi fi log "Copy generic and site-specific MFS tree..." for MFS_TREE in ${PICO_TREE}/mfs_tree ${MY_TREE}/mfs_tree ; do if [ -d ${MFS_TREE} ] ; then log "Copy ${MFS_TREE} ..." (cd ${MFS_TREE} ; tar -cf - --exclude CVS --exclude .svn . ) | \ (cd ${dst} ; tar x${o_tarv}f - ) fi done if [ -f ${MY_TREE}/buildtree.mk ] ; then log "building local floppy tree" ${BINMAKE} -C ${dst} -f ${MY_TREE}/buildtree.mk mfs.tree fi if [ "${o_all_in_mfs}" = "yes" ]; then log "Copy generic floppy_tree into MFS..." # ignore failure in case the floppy is empty cp -Rp ${BUILDDIR}/floppy.tree/* ${dst}/fd || true fi # 4.x compatibility - create device nodes if [ -n "${o_no_devfs}" ] ; then # create device entries using MAKEDEV (cd ${dst}/dev ln -s ${SRC}/etc/MAKEDEV ; chmod 555 MAKEDEV # log `pwd` sh ./MAKEDEV ${MY_DEVS} rm MAKEDEV ) fi if [ "`id -u`" = "0" ] ; then log "Fixing permissions" (cd ${dst}; chown -R root . ) fi log "for a shared 'crunch' take libraries and dynamic loader as well" find_progs ${dst}/stand/crunch if [ -n "${u_libs}" ] ; then mkdir -p ${dst}/lib && cp -p ${u_libs} ${dst}/lib mkdir -p ${dst}/libexec create_includes_and_libraries2 libexec/rtld-elf find_progs ld-elf.so.1 && cp -p ${u_progs} ${dst}/libexec fi [ -n "${copy_files}" ] && do_copyfiles ${dst} copy_files do_copyfiles_user ${dst} || true [ -n "${links}" ] && do_links ${dst} links strip ${dst}/libexec/* ${dst}/lib/* ${dst}/stand/* 2> /dev/null || true # The 'import_files' mechanism is deprecated, as it requires # root permissions to follow the symlinks, and also does # not let you rename the entries. if [ -n "${import_files}" ] ; then log "importing ${import_files} into mfs" # We do it in a chroot environment on the target so # symlinks are followed correctly. # Make sure we have a statically linked tar there. mkdir -p ${dst}/rescue cp /rescue/tar ${dst}/rescue (cd ${l_usrtree}/.. ; tar cf - ${import_files} ) | \ (chroot ${dst} /rescue/tar xPf - ) rm -rf ${dst}/rescue fi # final step -- build the mfs image (cd ${BUILDDIR} # override the owner echo "/set uid=0 gid=0" > mtree.out mtree -ic -p ${dst} -k "" >> mtree.out log "mtre.out at ${BUILDDIR}/mtree.out" makefs -t ffs -o bsize=4096 -o fsize=512 \ -s ${MFS_SIZE}k -f 1000 -F mtree.out ${c_fs} ${dst} ls -l ${c_fs} ) log "done mfs image" } final_cleanup() { log "final_cleanup()" rm -rf ${c_mnt} ${c_reply} 2> /dev/null || true } # fail errno errcode # This function is used to trap errors and print msgs # fail() { local errno errocode where errno=$1 errcode=$2 where=$3 echo "---> fail: Error <${errno}> error code <${errcode}> in <${where}>" case ${errcode} in mtree) echo "Error while making hierarchy in ${c_mnt}" ;; crunch) echo "Error while building ${name}." ;; missing_kernel) echo "Error: you must build PICOBSD${suffix} kernel first" ;; includes) echo "Error: failed while making includes" ;; libraries) echo "Error: failed while making libraries" ;; bad_type) echo "Error: unknown floppy type ${name}" ;; no_space) echo "Error: no space left on device (${where})" ;; no_mfs) echo "Error: while writing MFS into the kernel." ;; "") echo "User break" errcode="userbreak" ;; *) echo "unknown error, maybe user break: $errno $errcode" ;; esac echo "---> Aborting $0" # try to cleanup the vnode. final_cleanup exit 2 } fill_floppy_image() { local blocks dst mfs_start mfs_end mfs_size img_size log "fill_floppy_image()" dst=${c_mnt} # where to create the image log "Preparing ${fd_size}kB floppy filesystem..." # correct blocks according to size. blocks=${fd_size}; if [ "${blocks}" = "1720" ]; then blocks=1722 elif [ "${blocks}" = "1480" ]; then blocks=1476 fi log "Labeling floppy image" dst=${BUILDDIR}/image.tree rm -rf ${dst} mkdir -p ${dst} ( cd ${BUILDDIR} set 0 0 # reset variables # $1 takes the offset of the MFS filesystem set `strings -at d kernel | grep "MFS Filesystem goes here"` mfs_start=$1 set 0 0 # reset variables set `strings -at d kernel | grep "MFS Filesystem had better"` mfs_end=$1 mfs_size="$((${mfs_end} - ${mfs_start}))" set -- `ls -l ${c_fs}`; imgsize="$5" if [ ${mfs_start} -gt 0 -a ${mfs_size} -ge ${imgsize} ] ; then mfs_ofs=$((${mfs_start} + 8192)) log "Preload kernel with file ${c_fs} at ${mfs_ofs}" log "`ls -l ${c_fs}` to fit in ${mfs_size}" dd if=${c_fs} ibs=8192 iseek=1 of=kernel obs=${mfs_ofs} \ oseek=1 conv=notrunc # 2> /dev/null else log "not loading mfs, size ${mfs_size} img ${imgsize}" fi log "Compress with kgzip and copy to floppy image" mkdir -p ${dst}/boot/kernel # XXX loader.conf does not work unless we also load the .4th files echo "hint.acpi.0.disabled=\"1\"" > ${dst}/boot/loader.conf echo "console=\"comconsole\"" >> ${dst}/boot/loader.conf cp -p /boot/loader ${dst}/boot/loader || fail $? no_space "copying bootloader" gzip -c kernel > ${dst}/boot/kernel/kernel.gz || fail $? no_space "copying kernel" # now transfer the floppy tree. If it is already in mfs, dont bother. if [ "${o_all_in_mfs}" != "yes" ] ; then log "Now transfer floppy tree if not already in MFS image" cp -Rp floppy.tree/* ${dst} || \ fail $? no_space "copying floppy tree" fi ) # add local manipulation to the image if [ -f ${MY_TREE}/buildtree.mk ] ; then ${BINMAKE} -C ${dst} -f ${MY_TREE}/buildtree.mk image.tree fi log "image used `du -s ${dst}` of ${blocks}k" if [ "${generate_iso}" = "YES" ]; then logverbose "generate_iso ${generate_iso}" # build_iso_image # XXX not implemented yet (cd ${BUILDDIR} cp -p /boot/cdboot ${dst}/boot || fail $? no_space "copying cdboot" mkisofs -b boot/cdboot -no-emul-boot -J -r -ldots -l -L \ -o ${c_iso} ${dst} ) fi (cd ${BUILDDIR} makefs -t ffs -o bsize=4096 -o fsize=512 \ -s ${blocks}k -f 50 ${c_img} ${dst} ${c_label} -w -f `pwd`/${c_img} auto # write in a label # copy partition c: into a: with some sed magic ${c_label} -f `pwd`/${c_img} | sed -e '/ c:/{p;s/c:/a:/;}' | \ ${c_label} -R -f `pwd`/${c_img} /dev/stdin ${c_label} -f `pwd`/${c_img} ls -l ${c_img} ${c_label} -f `pwd`/${c_img} log "after disklabel" ) echo "BUILDDIR ${BUILDDIR}" # dump the primary and secondary boot # XXX primary is 512 bytes dd if=${c_boot1} of=${BUILDDIR}/${c_img} conv=notrunc 2>/dev/null # XXX secondary starts after the 0x114 = dec 276 bytes of the label # so we skip 276 from the source, and 276+512=788 from dst # the old style blocks used 512 and 1024 respectively dd if=${c_boot2} iseek=1 ibs=276 2> /dev/null | \ dd of=${BUILDDIR}/${c_img} oseek=1 obs=788 conv=notrunc 2>/dev/null log "done disk image" # XXX (log "Fixing permissions"; cd ${dst}; chown -R root *) # leave build stuff if verbose [ ${o_verbose} -gt 0 ] && return rm -rf ${BUILDDIR}/floppy.tree || true # cleanup # df -ik ${dst} | colrm 70 > .build.reply rm -rf ${dst} rm ${BUILDDIR}/${c_fs} # rm ${BUILDDIR}/kernel.gz } # This function creates variables which depend on the source tree in use: # SRC, l_usrtree, l_objtree # Optionally creates libraries, includes and the like (for cross compiles, # needs to be done once). set_build_parameters() { if [ "${SRC}" = "/usr/src" ] ; then l_usrtree=${USR:-/usr} else l_usrtree=${USR:-${SRC}/../usr} fi l_objtree=${l_usrtree}/obj-pico-${o_arch} PICO_TREE=${PICO_TREE:-${SRC}/release/picobsd} set `grep "#define[\t ]__FreeBSD_version" ${SRC}/sys/sys/param.h` OSVERSION=$3 log "OSVERSION is ${OSVERSION}" if [ ${OSVERSION} -ge 500035 ] ; then export MAKEOBJDIRPREFIX=${l_objtree} export TARGET_ARCH=${o_arch} TARGET=${o_arch} # XXX why change machine_arch ? #-- export MACHINE_ARCH=`uname -m` MACHINE=`uname -m` # export CWARNFLAGS="-Wextra -Wno-sign-compare -Wno-missing-field-initializers" eval "export BINMAKE=\"`cd ${SRC}; make -f Makefile -V BINMAKE`\"" fi if [ "${o_init_src}" != "" ] ; then if [ ${OSVERSION} -lt 500035 ] ; then create_includes_and_libraries else create_includes_and_libraries2 fi else eval export `cd ${SRC}; ${BINMAKE} -f Makefile.inc1 -V WMAKEENV` fi if [ ${OSVERSION} -lt 500035 ] ; then # Create the right LIBS and CFLAGS for further builds. # and build the config program LIBS="-L${l_usrtree}/lib" CFLAGS="-nostdinc -I${l_usrtree}/include" export LIBS CFLAGS CONFIG=${l_usrtree}/sbin/config export CONFIG fi # if we have o_objdir, find where bin/ is if [ ! -z "${o_objdir}" ] ; then if [ -d ${o_objdir}/bin ] ; then # fine elif [ -d "${o_objdir}${SRC}/bin" ] ; then o_objdir="${o_objdir}${SRC}" log "Changing objdir to ${o_objdir}" else log "Cannot find objdir in ${o_objdir}, sorry" o_objdir="" fi fi } #------------------------------------------------------------------- # Main entry of the script. Initialize variables, parse command line # arguments. # o_par="-j 8" # parallel make and other make options set_defaults while [ true ]; do log "Parsing $1" case $1 in --par) o_par="-j 8" ;; --src) # set the source path instead of /usr/src SRC=`realpath $2` shift ;; --init) # run a partial buildworld on the source tree o_init_src="YES" ;; --arch) # override the target architecture o_arch=$2 shift ;; --floppy_size) # image size fd_size=$2 shift ;; --all_in_mfs) o_all_in_mfs="yes" ;; --no_all_in_mfs) o_all_in_mfs="no" ;; --modules) # also build kernel modules o_do_modules="yes" ;; -n) o_interactive="NO" ;; -clear|-clean|-c) # clean o_clean="YES" o_interactive="NO" ;; -v) # need -v -v to wait for user input o_verbose=$((${o_verbose}+1)) # verbose level o_tarv="v" # tar verbose flag o_makeopts="-d l" # be verbose ;; --iso) # generate iso image generate_iso="YES" ;; --cfg) # read additional config from this file o_additional_config=`realpath $2` shift ;; --objdir) # Place with results of a previous buildworld # useful if you want to copy shared binaries and libs o_objdir=`realpath $2` shift ;; *) break ;; esac shift done set_build_parameters # things that depend on ${SRC} set_type $1 $2 # type and site, respectively [ "${o_interactive}" != "NO" ] && main_dialog if [ "${o_clean}" = "YES" ] ; then clean_tree else build_image do_install fi final_cleanup exit 0