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