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