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