3 # Copyright (c) 2015 M. Warner Losh <imp@FreeBSD.org>
4 # Copyright (c) 2010-2011 iXsystems, Inc.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED. IN NO EVENT SHALL iXsystems, Inc OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 # This file is heavily derived from both Sam Leffler's Avilia config,
29 # as well as the BSDRP project's config file. Neither of these have
30 # an explicit copyright/license statement, but are implicitly BSDL. This
31 # example has been taken from the FreeNAS project (an early version) and
32 # simplified to meet the needs of the example.
35 # NB: You want the other file as the command line arg :)
38 # o mkimg setting active partition
39 # o mkimg starting at arbitrary offset (needed for A10, et al)
40 # o mtools still needed because we have no makefs -t msdos
41 # o nanobsd doesn't record changes to WORLDTEMP in customization
42 # scripts yet, so we have kludge to pick up all files
43 # o easy way for pkg to grab files from other repos and put that
45 # o Need to have some way to create / resize the s4 slice to do ping
46 # pong bouncing between s3 and s4 for an arbitrary image. we can resize
48 # o hints in the uboot ports for how to create the image
51 # o documentation for how to run the qemu images
52 # o msdos mtools fallback
53 # o special boot for !x86 !arm platforms
54 # o qemu image for arm
55 # o qemu image for aarch64
56 # o qemu image for armv6/armv7
57 # o easy support for different image / vm formats
58 # o need to promote much of this to nanobsd.sh and friends
59 # o uses old kludge to build image w/o ownership being right
60 # for many files. Should move to mtree-dedup.awk.
61 # o support for EFI images
62 # o support for GPT partitioning
65 # o common tooling for creating images for odd-ball platforms
66 # o support for boot loaders other than uboot in the image
67 # or via special instructions
68 # o no pony support; sadly, you cannot have a pony
71 if [ -z $NANO_NAME ]; then
72 echo "NANO_NAME not defined. Use foo.cfg instead."
75 NANO_SLICE_FAT_SIZE=32m
76 NANO_SLICE_CFG_SIZE=32m
78 NANO_BOOT2CFG="-h -S115200"
81 NANO_RAM_TMPVARSIZE=8192
84 NANO_PMAKE="make -j $(sysctl -n hw.ncpu)"
87 NANO_CFG_BASE=$(realpath ${NANO_CFG_BASE}/..)
88 NANO_SRC=$(realpath ${NANO_CFG_BASE}/../../..)
90 if [ -z ${NANO_CPUTYPE} ]; then
91 NANO_OBJ=${NANO_SRC}/../embedded/obj
93 # Alas, I can't set OBJTREE to ${MACHINE}.${MACHINE_ARCH}.${CPUTYPE}
94 # so this will have to do until I can.
95 NANO_OBJ=${NANO_SRC}/../embedded/obj.${NANO_CPUTYPE}
97 NANO_LOG=${NANO_OBJ}/../${NANO_NAME}
98 NANO_DISKIMGDIR=${NANO_OBJ}/../images
99 NANO_WORLDDIR=${NANO_LOG}/_.w
102 unset MAKEOBJDIRPREFIX
105 NANO_OBJ=$(realpath ${NANO_OBJ})
107 NANO_LOG=$(realpath ${NANO_LOG})
108 mkdir -p ${NANO_WORLDDIR}
109 NANO_WORLDDIR=$(realpath ${NANO_WORLDDIR})
110 mkdir -p ${NANO_DISKIMGDIR}
111 NANO_DISKIMGDIR=$(realpath ${NANO_DISKIMGDIR})
113 NANO_FAT_DIR=${NANO_LOG}/_.fat
115 customize_cmd cust_allow_ssh_root
117 add_etc_make_conf ( ) (
118 touch ${NANO_WORLDDIR}/etc/make.conf
120 customize_cmd add_etc_make_conf
122 cust_install_machine_files ( ) (
123 echo "cd ${NANO_CFG_BASE}/Files"
124 cd ${NANO_CFG_BASE}/Files
125 find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -dumpv ${NANO_WORLDDIR}
127 customize_cmd cust_install_files
128 customize_cmd cust_install_machine_files
130 # NB: leave c++ enabled so devd can be built
132 LOCAL_XTOOL_DIRS=usr.bin/mkimg
136 WITHOUT_BLUETOOTH=true
137 WITHOUT_CALENDAR=true
139 WITHOUT_EXAMPLES=true
142 WITHOUT_IPFILTER=true
143 WITHOUT_LLVM_COV=true
150 WITHOUT_NS_CACHING=true
152 WITHOUT_SENDMAIL=true
153 WITHOUT_SHAREDOCS=true
157 WITHOUT_DEBUG_FILES=t
158 WITHOUT_KERNEL_SYMBOLS=t
160 CONF_INSTALL="$CONF_BUILD
163 NO_INSTALL_MANPAGES=t
165 # The following would help...
166 # WITHOUT_TOOLCHAIN=true can't build ports
167 # WITHOUT_INSTALLLIB=true libgcc.a
171 WITHOUT_TOOLCHAIN=true
172 WITHOUT_INSTALLLIB=true
177 # Creates images for all the formats that use MBR / GPT
178 # split later if the #ifdef soup gets too bad.
179 create_diskimage_gpt ( ) (
180 pprint 2 "build diskimage gpt ${NANO_NAME}"
182 create_diskimage_mbr $*
185 create_diskimage_mbr ( ) (
189 [ -z ${NANO_DISKIMAGE_FORMAT} ] || fmt=".${NANO_DISKIMAGE_FORMAT}"
191 pprint 2 "build diskimage ${NANO_NAME}"
192 pprint 3 "log: ${NANO_LOG}/_.di"
193 pprint 3 "image in: ${NANO_DISKIMGDIR}/_.disk.image.${NANO_NAME}${fmt}"
196 local extra i sz fmt fmtarg bootmbr bootbsd skiparg
198 # Tell mtools not to be too picky
199 export MTOOLS_SKIP_CHECK=1
201 [ -z ${NANO_DISKIMAGE_FORMAT} ] || fmtarg="-f ${NANO_DISKIMAGE_FORMAT}"
202 [ -z ${NANO_DISKIMAGE_FORMAT} ] || fmt=".${NANO_DISKIMAGE_FORMAT}"
203 bootmbr=${NANO_BOOT_MBR:+-b ${NANO_BOOT_MBR}}
204 bootbsd=${NANO_BOOT_BSD:+-b ${NANO_BOOT_BSD}}
205 skiparg=${NANO_MBR_FIRST_SKIP:+-S ${NANO_MBR_FIRST_SKIP}}
207 for i in s1 s2 s3 s4 p1 p2 p3 p4 p5 empty; do
208 rm -fr ${NANO_LOG}/_.${i}*
211 # Populate the FAT partition, if needed
212 if [ -n "${NANO_SLICE_FAT}" ]; then
213 echo Creating MSDOS partition for kernel
214 newfs_msdos -C ${NANO_SLICE_FAT_SIZE} -F 16 -L ${NANO_NAME} \
215 ${NANO_LOG}/_.${NANO_SLICE_FAT}
216 if [ -d ${NANO_FAT_DIR} ]; then
217 # Need to copy files from ${NANO_FATDIR} with mtools, or use
218 # makefs -t msdos once that's supported
219 mcopy -i ${NANO_LOG}/_.${NANO_SLICE_FAT} ${NANO_FAT_DIR}/* ::
223 # Populate the Powerpc boot image, if needed
224 if [ "${NANO_LAYOUT}" = powerpc64-ibm ]; then
225 dd if=${NANO_WORLDDIR}/boot/boot1.elf of=${NANO_LOG}/_.s1 bs=800k count=1 conv=sync
228 # Populate the / partition, and place it into a slice with a
230 [ -z ${NANO_NOPRIV_BUILD} ] || extra="-F ${NANO_METALOG}"
231 sz=${NANO_SLICE_ROOT_SIZE:+-s ${NANO_SLICE_ROOT_SIZE}}
232 eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_LOG}/_.${NANO_ROOT}" \
234 case ${NANO_DISK_SCHEME} in
236 mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_LOG}/_.${NANO_ROOT} \
237 -o ${NANO_LOG}/_.${NANO_SLICE_ROOT}
238 eval $NANO_SLICE_CFG=freebsd
239 eval $NANO_SLICE_ROOT=freebsd
242 eval $NANO_SLICE_CFG=freebsd-ufs
243 eval $NANO_SLICE_ROOT=freebsd-ufs
247 # Populate the /cfg partition, empty if none given
248 if [ -z "${NANO_CFGDIR}" ]; then
249 echo "Faking cfg dir, it's empty"
250 NANO_CFGDIR=${NANO_LOG}/_.empty
251 mkdir -p ${NANO_CFGDIR}
254 eval "${NANO_MAKEFS_UFS}" -s ${NANO_SLICE_CFG_SIZE} \
255 "${NANO_LOG}/_.${NANO_SLICE_CFG}" "${NANO_CFGDIR}"
257 # data slice not supported since we need the part for FAT for
260 # Now shuffle all the slices together into the proper layout
261 if [ -n "$NANO_SLICE_FAT" ]; then
262 eval $NANO_SLICE_FAT=fat16b
265 out=${NANO_DISKIMGDIR}/_.disk.image.${NANO_NAME}${fmt}
266 # below depends on https://reviews.freebsd.org/D4403 not yet in the tree
267 # but there's problems: it marks all partitions as active, so you have to
268 # boot off partition 3 or 2 by hand if you're playing around with this WIP
269 case ${NANO_LAYOUT} in
271 mkimg -a 3 ${skiparg} ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_LOG}/_.s1 \
272 -p ${s2}:=${NANO_LOG}/_.s2 \
273 -p ${s3}:=${NANO_LOG}/_.s3 \
277 # s3 is cfg, s1 is /, s2 is other / (s2 is created in first boot script)
278 mkimg -a 1 ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_LOG}/_.s1 \
280 -p ${s3}:=${NANO_LOG}/_.s3 \
286 # s1 is boot, s2 is cfg, s3 is /, not sure how to make that
287 # boot (marked as active) with mkimg yet
288 mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr \
289 -p efi:=${NANO_WORLDDIR}/boot/efiboot.img \
290 -p ${s2}:=${NANO_LOG}/_.s2 \
291 -p ${s3}:=${NANO_LOG}/_.s3 \
295 # p1 is boot for uefi, p2 is boot for gpt, p3 is cfg, p4 is /
296 # and p5 is alt-root (after resize)
297 mkimg -a 2 ${fmtarg} ${bootmbr} -s gpt \
298 -p efi:=${NANO_WORLDDIR}/boot/efiboot.img \
299 -p freebsd-boot:=${NANO_WORLDDIR}/boot/gptboot \
300 -p ${p3}:=${NANO_LOG}/_.p3 \
301 -p ${p4}:=${NANO_LOG}/_.p4 \
305 # A lie to make the boot loader work, it boots the first BSD partition
306 # it finds, regardless of the active flag.
308 # boot image is on a special partition, ala std-embedded, but that
309 # partition isn't FAT with special files, but a copy of the boot
311 mkimg -a 1 ${fmtarg} -s mbr -p prepboot:=${NANO_LOG}/_.s1 \
312 -p ${s2}:=${NANO_LOG}/_.s2 \
313 -p ${s3}:=${NANO_LOG}/_.s3a \
319 ) > ${NANO_LOG}/_.di 2>&1
327 # Automatically include the packaging port here so it is always first so it
328 # builds the port and adds the package so we can add other packages.
329 #XXX Doesn't work for cross build, so punting until I can integreate qemu-static
330 #XXX or poudriere, both of which require priv'd execution. Or qemu-system,
331 #XXX which is super, super slow.
332 #add_port ports-mgmt/pkg
333 #add_port security/sudo
336 rp=$(realpath ${NANO_OBJ}/)
337 __a=`mount | grep ${rp} | awk '{print length($3), $3;}' | sort -rn | awk '{$1=""; print;}'`
338 if [ -n "$__a" ]; then
339 echo "unmounting $__a"
343 if [ "$DEBUG" = 1 ]; then
353 CONF_INSTALL="$CONF_BUILD
356 CONF_INSTALL="$CONF_INSTALL
360 if [ "${NANO_PACKAGE_ONLY}" -eq 1 ]; then
361 CONF_INSTALL="${CONF_INSTALL}
362 ${PKG_ONLY_MAKE_CONF}
364 echo "Automatically building a thin image with packages"
366 echo "Automatically building a * * F A T * * image so we can build ports"
369 VARS="MASTER_SITE_BACKUP MASTER_SITE_OVERRIDE PACKAGEROOT PACKAGESITE"
372 val=$(eval echo "\$$var")
373 if [ -n "$val" ]; then
374 CONF_INSTALL="${CONF_INSTALL}
379 typical_embedded ( ) (
380 # Need to create rc.conf before we copy over /etc to /conf/base/etc
381 # so now's a good time.
383 local rc=${NANO_WORLDDIR}/etc/rc.conf
385 echo "hostname=nanobsd-${NANO_NAME}" > $rc
386 echo "growfs_enable=YES" >> $rc
387 echo "growfs_type=nanobsd-pingpong" >> $rc
388 echo "ntpdate_enable=YES" >> $rc
389 echo "ifconfig_DEFAULT=DHCP" >> $rc
390 echo "ntpdate_hosts='0.freebsd.pool.ntp.org 1.freebsd.pool.ntp.org'" >> $rc
391 # Make sure that firstboot scripts run so growfs works.
392 # Note: still some issues remvoing this XXX
393 touch ${NANO_WORLDDIR}/firstboot
395 customize_cmd typical_embedded
398 chdir ${NANO_WORLDDIR}
402 mkdir -p pkg/tmp # Needed for pkg bootstrap
403 mkdir -p usr/local/etc # Will get moved to local/etc
405 echo 'PKG_DBDIR = "/pkg/db"'
406 echo 'PKG_CACHEDIR = "/pkg/cache"'
407 echo 'DEFAULT_ALWAYS_YES = "yes"'
408 echo 'ASSUME_ALWAYS_YES = "yes"'
409 ) >> usr/local/etc/pkg.conf
410 [ -z ${NANO_NOPRIV_BUILD} ] || (
411 echo "./pkg type=dir uname=root gname=wheel mode=0755"
412 echo "./pkg/cache type=dir uname=root gname=wheel mode=0755"
413 echo "./pkg/db type=dir uname=root gname=wheel mode=0755"
414 echo "./pkg/tmp type=dir uname=root gname=wheel mode=0755"
417 customize_cmd fix_pkg
420 VERSION_FILE=${NANO_WORLDDIR}/etc/version
421 if [ "${SVNREVISION}" = "${REVISION}" ]; then
422 echo "${NANO_NAME}" > "${VERSION_FILE}"
424 echo "${NANO_NAME} (${SVNREVISION})" > "${VERSION_FILE}"
427 customize_cmd save_build
429 shrink_md_fbsize ( ) (
430 # We have a lot of little files on our memory disks. Let's decrease
431 # the block and frag size to fit more little files on them (this
432 # halves our space requirement by ~50% on /etc and /var on 8.x --
433 # and gives us more back on 9.x as the default block and frag size
434 # are 4 times larger).
435 sed -i '' -e 's,-S -i 4096,-S -i 4096 -b 4096 -f 512,' \
436 ${NANO_WORLDDIR}/etc/rc.initdiskless
438 customize_cmd shrink_md_fbsize
440 customize_cmd cust_comconsole
443 local d=/usr/local/share/u-boot/${NANO_BOOT_PKG}
444 local f=${NANO_FAT_DIR}
446 # For now, just copy all the files. However, for iMX6 and Allwinner,
447 # we'll need to put a special boot block at a fixed location
448 # on the disk as well.
454 # Also copy ubldr. u-boot will load it and it will load the kernel
455 # from the ufs partition
456 cp ${NANO_WORLDDIR}/boot/ubldr .
457 cp ${NANO_WORLDDIR}/boot/ubldr.bin .
459 # We have to touch the saveenv file
462 # Now we need to copy over dtb files from the build.
463 cp ${NANO_WORLDDIR}/boot/dtb/*.dtb .
466 if [ -n "$NANO_BOOT_PKG" ]; then
467 d=/usr/local/share/u-boot/${NANO_BOOT_PKG}
468 if [ ! -d ${d} ]; then
469 echo ${NANO_BOOT_PKG} not installed. Sadly, it must be.
472 if [ ! -x /usr/local/bin/mcopy ]; then
473 echo mtools not installed. Sadly, we gotta have it.
476 customize_cmd dos_boot_part
480 # not quite ready to tweak these in nopriv build
481 if [ -z ${NANO_NOPRIV_BUILD} ]; then
482 # Last second tweaks -- generally not needed
483 chown -R root:wheel ${NANO_WORLDDIR}/root
484 chmod 0755 ${NANO_WORLDDIR}/root/*
485 chmod 0755 ${NANO_WORLDDIR}/*
486 chown -R root:wheel ${NANO_WORLDDIR}/etc
487 chown -R root:wheel ${NANO_WORLDDIR}/boot
488 chown root:wheel ${NANO_WORLDDIR}/
489 chown root:wheel ${NANO_WORLDDIR}/usr
492 late_customize_cmd product_custom
495 # Convenience routines to bring up many settings for standard environments
499 # For each architecture, we have a standard set of settings to the extent
500 # it makes sense. For architectures that don't have a standard environment
501 # cfg files need to either define a lot of settings, provide their own disk
502 # imaging, or set which of the variants we support. No subshells, since we
503 # set global variables
523 # Default values, if not overridden in .cfg file
524 : ${NANO_KERNEL:=GENERIC}
525 : ${NANO_DRIVE:=ada0}
526 : ${NANO_LAYOUT:=std-x86}
527 : ${NANO_BOOT_MBR:=${NANO_WORLDDIR}/boot/boot0sio}
528 : ${NANO_BOOT_BSD:=${NANO_WORLDDIR}/boot/boot}
550 NANO_LAYOUT=powerpc64-ibm
559 # QEMU settings for the standard environments
563 NANO_DISKIMAGE_FORMAT=qcow2
566 # other standard environments will go here
568 eval std_${NANO_ARCH}
570 # Slice 1: FAT for ROM loading bootstrap
571 # Slice 2: Config partition
572 # Slice 3: FreeBSD partition (sized exactly)
573 # Slice 4: FreeBSD partition (empty)
574 # on first boot, we resize slice 3 & 4 to be 1/2 of what's
575 # left over on the SD card after slice 1 and 2 are taken
576 # off the top. We also resize the 'a' partition on first boot
577 # to the size of the partition for the ping/pong upgrade.
578 # This feature needs support in the rc.d bootup script.
580 # Ideally, we'd not put BSD labels on the MBR disks.
581 # However, we can't boot off raw MBR disks. First,
582 # boot2 defaults to 'a' partition, and freaks out
583 # unless you tell it to use 'c'. But even if we
584 # hack that, then /boot/loader wants to load off
585 # of 'c' partition. If you fix that, then we'll
586 # try to mount root, but sanity checks prevent
587 # slices from working.
590 : ${NANO_ENDIAN:=little} # make -V something to figure it out?
591 : ${NANO_LAYOUT:=std-embedded}
592 : ${NANO_MAKEFS_UFS:=makefs -t ffs -B ${NANO_ENDIAN}}
593 : ${NANO_DISK_SCHEME:=mbr} # No others really supported ATM (well, gpt)
594 case ${NANO_LAYOUT} in
599 NANO_SLICE_ALTROOT=s4
600 NANO_ROOT=${NANO_SLICE_ROOT}a
601 NANO_ALTROOT=${NANO_SLICE_ALTROOT}a
606 NANO_SLICE_ALTROOT=s2
607 NANO_ROOT=${NANO_SLICE_ROOT}a
608 NANO_ALTROOT=${NANO_SLICE_ALTROOT}a
611 NANO_SLICE_PPCBOOT=s1
614 NANO_SLICE_ALTROOT=s4
615 NANO_ROOT=${NANO_SLICE_ROOT}a
616 NANO_ALTROOT=${NANO_SLICE_ALTROOT}a
626 NANO_SLICE_ALTROOT=s4
627 NANO_ROOT=${NANO_SLICE_ROOT}
628 NANO_ALTROOT=${NANO_SLICE_ALTROOT}
636 NANO_SLICE_ALTROOT=p5
637 NANO_ROOT=${NANO_SLICE_ROOT}
638 NANO_ALTROOT=${NANO_SLICE_ALTROOT}
641 echo Unknown Layout ${NANO_LAYOUT}
647 NANO_SLICE_DATA= # Not included
649 # Each major disk scheme has its own routine. Generally
650 # this is for mbr, gpt, etc. These are generally are widely
651 # shared, but some specialized formats won't be shared.
652 create_diskimage ( ) (
653 eval create_diskimage_${NANO_DISK_SCHEME}
656 # Set the path to the same path we use for buldworld to use latest mkimg
657 NANO_TARGET=$(cd ${NANO_SRC}; ${NANO_MAKE} TARGET_ARCH=${NANO_ARCH} -V _TARGET)
658 NANO_TMPPATH=$(cd ${NANO_SRC}; ${NANO_MAKE} MK_AUTO_OBJ=no TARGET=${NANO_TARGET} TARGET_ARCH=${NANO_ARCH} -f Makefile.inc1 buildenv -V TMPPATH)
659 export PATH="${NANO_TMPPATH}:${PATH}"