{"id":247,"date":"2017-02-08T00:01:02","date_gmt":"2017-02-08T00:01:02","guid":{"rendered":"http:\/\/blog.ignoranthack.me\/?p=247"},"modified":"2017-02-08T00:01:02","modified_gmt":"2017-02-08T00:01:02","slug":"one-pxeboot-to-find-them-and-in-the-darkness-bind-them","status":"publish","type":"post","link":"http:\/\/blog.ignoranthack.me\/?p=247","title":{"rendered":"One pxeboot to find them and in the darkness bind them"},"content":{"rendered":"<p>Irritatingly, I couldn&#8217;t find a decent cut-n-paste how to on the Internet for using a much loved and mostly overlooked FreeBSD installation and boot up process using a fully cooked diskless image fetched via TFTP instead of the really well documented and <a href=\"https:\/\/www.freebsd.org\/doc\/handbook\/network-diskless.html\">fantastic howto on NFS booting<\/a>.<\/p>\n<p>Primarily, I wanted to switch off of NFS booting as it tends to be really troublesome if one is doing development or debugging of the FreeBSD network stack or Ethernet drivers. I couldn&#8217;t reliably screw around with the network interfaces without disturbing the NFS root mount and inflicting relatively long timeouts on my tests. I decided to try and switch to MFS root based testing so that I didn&#8217;t run into these types of problems, however I didn&#8217;t realize that the boot loader had gone through some overhauls recently and the documentation that *is* floating around on the Internet, is a bit out of date. So, here is the beginning of what I hope will be the inception of a new FreeBSD handbook entry before version 12 is released.<\/p>\n<p>I want to cover the actual construction of the entire process, so I will not be hand copying binaries from a release and all files will be constructed from source where possible.\u00a0 This means that I can fully automate a build and regression from source to ensure that this document stays relatively up to date.\u00a0 I&#8217;m an active FreeBSD contributor, so I have many checkouts of FreeBSD lying around.\u00a0 If you&#8217;re a sysadmin, you probably use \/usr\/src for most of the projects like this, which is fine for our purposes.<\/p>\n<p>Assuming that you have a fresh checkout of FreeBSD somewhere, lets start by crafting a &#8220;src.conf&#8221; and a &#8220;make.conf&#8221; to minimize a bit of build time and a bit of space.<\/p>\n<p>I turn a lot of stuff off in the build here.\u00a0 Since I&#8217;m running the same major revision of FreeBSD that I&#8217;ll be building, I can get away with some shenanigans regarding not building toolchains.\u00a0 If you are trying to build 12-CURRENT on 11-STABLE, you may have to play around with the knobs a bit in src.conf:<\/p>\n<p>WITHOUT_BLUETOOTH=&#8221;YES&#8221;<br \/>\nWITHOUT_BSNMP=&#8221;YES&#8221;<br \/>\nWITHOUT_CAPSICUM=&#8221;YES&#8221;<br \/>\nWITHOUT_CDDL=&#8221;YES&#8221;<br \/>\nWITHOUT_COMPAT32=&#8221;YES&#8221;<br \/>\nWITHOUT_CTM=&#8221;YES&#8221;<br \/>\nWITHOUT_DEBUG_FILES=&#8221;YES&#8221;<br \/>\nWITHOUT_EXAMPLES=&#8221;YES<br \/>\nWITHOUT_FLOPPY=&#8221;YES&#8221;<br \/>\nWITHOUT_FREEBSD_UPDATE=&#8221;YES&#8221;<br \/>\nWITHOUT_GAMES=&#8221;YES&#8221;<br \/>\nWITHOUT_ICONV=&#8221;YES&#8221;<br \/>\nWITHOUT_JAIL=&#8221;YES&#8221;<br \/>\nWITHOUT_LIB32=&#8221;YES&#8221;<br \/>\nWITHOUT_LOCALES=&#8221;YES&#8221;<br \/>\nWITHOUT_LPR=&#8221;YES&#8221;<br \/>\nWITHOUT_MAKE=&#8221;YES&#8221;<br \/>\nWITHOUT_MAN=&#8221;YES&#8221;<br \/>\nWITHOUT_PORTSNAP=&#8221;YES&#8221;<br \/>\nWITHOUT_TESTS=&#8221;YES&#8221;<br \/>\nWITHOUT_PC_SYSINSTALL=&#8221;YES&#8221;<br \/>\nWITHOUT_RESCUE=&#8221;YES&#8221;<br \/>\nWITHOUT_SVNLITE=&#8221;YES&#8221;<br \/>\nWITHOUT_TEXTPROC=&#8221;YES&#8221;<br \/>\nWITHOUT_TOOLCHAIN=&#8221;YES&#8221;<br \/>\nWITHOUT_WIRELESS=&#8221;YES&#8221;<br \/>\nWITHOUT_KERBEROS=&#8221;YES&#8221;<br \/>\nWITHOUT_MAIL=&#8221;YES&#8221;<br \/>\nWTTHOUT_EFI=&#8221;YES&#8221;<br \/>\nWITHOUT_NTP=&#8221;YES&#8221;<\/p>\n<p>My make.conf is much shorter, and only set&#8217;s a few things to make life easier:<\/p>\n<p>BOOT_PXELDR_ALWAYS_SERIAL=y<br \/>\nNO_MODULES=y<br \/>\nMALLOC_PRODUCTION=y<\/p>\n<p>Set\/export a couple of variables to your local shell to use these:<\/p>\n<p>setenv SRCCONF \/path\/to\/src.conf<br \/>\nsetenv __MAKE_CONF \/path\/to\/make.conf<\/p>\n<p>Since I&#8217;m not building as root here, I set one more variable:<\/p>\n<p>setenv MAKEOBJDIRPREFIX \/var\/tmp\/mfsroot<\/p>\n<p>Execute a buildworld and turn some electrons into heat for a while.\u00a0 You&#8217;ll probably note a big difference in build times here.\u00a0 Also note that you&#8217;re building a much smaller FreeBSD system with a lot of missing pieces.\u00a0 No local mail agent, no ntp services, no compilers\/debuggers, no wireless bits &#8230; etc.\u00a0 Your mileage may vary here, but I needed a small world as I&#8217;m debugging\/testing kernel\/network drivers, not userland.<\/p>\n<p>You can make a choice here of kernels to build.\u00a0 Most folks will want GENERIC-NODEBUG, but if you want, you can base a customized kernel configuration from MINIMAL that will do the trick.\u00a0 You&#8217;ll need to include drivers specific to your systems and this will void all your warantees if you were given one.\u00a0 Here is an example that I&#8217;m using to build and test various bits and things.\u00a0 Note that I&#8217;ve added em(4) to my configuration as that&#8217;s the network interface I&#8217;m using.<\/p>\n<p>include MINIMAL<br \/>\nident MFS_NETBOOT<\/p>\n<p>nomakeoptions DEBUG # Build kernel with gdb(1) debug symbols<br \/>\nnomakeoptions WITH_CTF # Run ctfconvert(1) for DTrace support<\/p>\n<p>nooptions COMPAT_FREEBSD32<br \/>\nnooptions COMPAT_FREEBSD4<br \/>\nnooptions COMPAT_FREEBSD5<br \/>\nnooptions COMPAT_FREEBSD6<br \/>\nnooptions COMPAT_FREEBSD7<br \/>\nnooptions COMPAT_FREEBSD9<br \/>\nnooptions COMPAT_FREEBSD10<br \/>\nnooptions COMPAT_FREEBSD11<br \/>\nnooptions KTRACE<br \/>\nnooptions AUDIT<br \/>\nnooptions CAPABILITY_MODE<br \/>\nnooptions CAPABILITIES<br \/>\nnooptions MAC<br \/>\nnooptions KDTRACE_FRAME<br \/>\nnooptions KDTRACE_HOOKS<br \/>\nnooptions DDB_CTF<\/p>\n<p># Debugging support. Always need this:<br \/>\nnooptions KDB<br \/>\nnooptions KDB_TRACE<br \/>\n# For full debugger support use (turn off in stable branch):<br \/>\nnooptions DDB<br \/>\nnooptions GDB<br \/>\nnooptions DEADLKRES<br \/>\nnooptions INVARIANTS<br \/>\nnooptions INVARIANT_SUPPORT<br \/>\nnooptions WITNESS<br \/>\nnooptions WITNESS_SKIPSPIN<br \/>\n# Xen HVM Guest Optimizations<br \/>\n# NOTE: XENHVM depends on xenpci. They must be added or removed together.<br \/>\nnooptions XENHVM # Xen HVM kernel infrastructure<br \/>\nnodevice xenpci # Xen HVM Hypervisor services driver<\/p>\n<p>options GEOM_PART_GPT<br \/>\noptions GEOM_RAID<br \/>\noptions GEOM_LABEL<br \/>\noptions GEOM_UZIP<\/p>\n<p>options IFLIB<br \/>\ndevice em<\/p>\n<p># Serial (COM) ports<br \/>\ndevice uart # Generic UART driver<\/p>\n<p># Needed to actually boot from an MFS root<br \/>\ndevice md # Memory &#8220;disks&#8221;<\/p>\n<p>This will do the bare minimum and give you a functioning system, at least it does for me on my 2core Atom box.\u00a0 There&#8217;s little to no debugging enabled here, so if you chose to go this route remember that all of the facilities to debug are deactivated.<\/p>\n<p>Allow me a short digression here.\u00a0 One should NEVER create their own kernel configs from scratch and not derive them from one of the base kernel configs (GENERIC for example).\u00a0 When you hand craft a kernel config, you allow yourself to get into situations where new options and devices can be added or removed.\u00a0 This can lead to scenarios where your systems can be unusable and cost you many hours of hair pulling and gnashing of teeth.\u00a0 It is far simpler to include a base configuration and unset the devices and options you don&#8217;t want.\u00a0 Judicious use of noptions, nodevice and nomakeoptions can be used to remove things that you don&#8217;t want.\u00a0 Use them, please.<\/p>\n<p>Anywho, back to the task at hand.<\/p>\n<p>FreeBSD has shipped a directory to disk image creation tool for quite some time.\u00a0 makefs(8) does a great job of turning a directory tree into a disk image without all the the magical hand waving of creating a file backed md(4) device.\u00a0 Its a shortcut and you should use it.\u00a0 Embedded folks have been using it to boot up their MIPS and ARM devices for a while now.<\/p>\n<p>We&#8217;ll need to install the build somewhere that we can then access with makefs.\u00a0 I tend to just put it in a throw-away directory in \/var\/tmp, e.g. \/var\/tmp\/netboot_mfs<\/p>\n<p>So, something like &#8216;make installworld DESTDIR=\/var\/tmp\/netboot_mfs&#8217; should do the trick here.\u00a0 At this point, we can modify this installed directory with whatever configuration changes needed for your system boot up.\u00a0 At a minimum, I modify \/boot\/loader.conf and \/boot.config.\u00a0 These may not be needed for your environment, but I make the following changes:<\/p>\n<p>loader.conf:<br \/>\nconsole=&#8221;comconsole&#8221;<\/p>\n<p>boot.config:<br \/>\n-D<\/p>\n<p>You can now build your disk image:<br \/>\nmakefs -M 192m \/var\/tmp\/mfs_root.img \/var\/tmp\/netboot_mfs<br \/>\nCalculated size of `mfs_root.img&#8217;: 201326592 bytes, 3800 inodes<br \/>\nExtent size set to 8192<br \/>\nmfs_root.img: 192.0MB (393216 sectors) block size 8192, fragment size 1024<br \/>\nusing 4 cylinder groups of 54.38MB, 6960 blks, 1152 inodes.<br \/>\nsuper-block backups (for fsck -b #) at:<br \/>\n32, 111392, 222752, 334112,<br \/>\nPopulating `mfs_root.img&#8217;<br \/>\nImage `mfs_root.img&#8217; complete<\/p>\n<p>I add the &#8220;-M 192m&#8221; to the command line here to give my image a bit of space to do stuff and things on the running system without running out of space.\u00a0 makefs(8) will create an image big enough to fit the files regardless of the command line arguments, but the -M will &#8220;pad&#8221; the image to 192MB if its smaller.<\/p>\n<p>Go ahead and compress your diskimage with either bzip2 or gzip. I won&#8217;t judge.<\/p>\n<p>-rw-r&#8211;r&#8211; 1 root sbruno 35235255 Feb 7 16:14 mfs_root.img.bz2<br \/>\n-rw-r&#8211;r&#8211; 1 root sbruno 39516593 Feb 7 16:17 mfs_root.img.gz<br \/>\n(use bzip2).<\/p>\n<p>Don&#8217;t think that I haven&#8217;t forgotten about the kernel either.\u00a0 We&#8217;ll compress that beastie directly.\u00a0 One does not install it however, one does not need it, one does not simply install a kernel into Mordor.\u00a0 Recall that we set a MAKEOBJDIRPREFIX when doing out kernel and world builds.<\/p>\n<p>\/var\/tmp\/sbruno % find . -name kernel<br \/>\n.\/home\/sbruno\/bsd\/fbsd_head\/sys\/GENERIC-NODEBUG\/kernel<br \/>\n.\/home\/sbruno\/bsd\/fbsd_head\/sys\/NETBOOT\/kernel<\/p>\n<p>In this example, I&#8217;ve built both so you kind of have an idea of what you&#8217;re looking for, it can be a bit strange to *not* install a kernel, but as we are fond of saying these days, <a href=\"https:\/\/www.youtube.com\/watch?v=C7sE0agEVNg\">EVERYTHING IS FINE.\u00a0 <\/a><\/p>\n<p>You&#8217;re also going to need the pxeboot binary.\u00a0 On 12-CURRENT nowadays you don&#8217;t have to recompile it for TFTP installations as it&#8217;ll do the right thing depending on DHCP options.<\/p>\n<p>\/var\/tmp\/sbruno % find . -name pxeboot<br \/>\n.\/home\/sbruno\/bsd\/fbsd_head\/sys\/boot\/i386\/pxeldr\/pxeboot<\/p>\n<p>Speaking of DHCP and TFTP, we should probably set those up now.\u00a0 Remember when I linked you to <a href=\"https:\/\/www.freebsd.org\/doc\/handbook\/network-diskless.html\">The Outstanding FreeBSD Handbook<\/a>?\u00a0 It has the correct setting for the setup of inetd(8) and tftp(8) on your sever.\u00a0 Ignore all the NFS bits, those don&#8217;t apply.<\/p>\n<p>Install your dhcp server, you can use the same one from <a href=\"https:\/\/www.freebsd.org\/doc\/handbook\/network-diskless.html\">The Outstanding FreeBSD Handbook<\/a> as I did.<\/p>\n<p>The dhcpd.conf settings are a little different here.\u00a0 We don&#8217;t need to pass in a root-path option, but need a custom dhcp option code 150:<\/p>\n<p>option tftp-server code 150 = { ip-address };<\/p>\n<p>subnet 192.168.100.0 netmask 255.255.255.0 {<br \/>\noption routers 192.168.100.1;<br \/>\noption domain-name-servers 192.168.0.1;<br \/>\nhost router {<br \/>\nhardware ethernet xx:xx:xx:xx:xx:xx;<br \/>\nfixed-address 192.168.100.52;<br \/>\noption tftp-server 192.168.100.1;<br \/>\nnext-server 192.168.100.1;<br \/>\nfilename &#8220;\/boot\/pxeboot&#8221;;<br \/>\n}<\/p>\n<p>Now we can populate \/tftpboot with the files we&#8217;ve created and add *one* last configuration file, this time with FORTH to ensure we&#8217;ve done the right thing.<\/p>\n<p>\/tftpboot\/boot # ls -l \/tftpboot\/boot<br \/>\ntotal 34844<br \/>\ndrwxr-xr-x 2 root wheel 3 Feb 7 16:45 kernel<br \/>\n-rw-r&#8211;r&#8211; 1 root wheel 21 Feb 7 12:45 loader.conf<br \/>\n-r&#8211;r&#8211;r&#8211; 1 root wheel 174 Feb 7 09:47 loader.rc<br \/>\n-rw-r&#8211;r&#8211; 1 root wheel 35234122 Feb 7 12:04 netboot.img.bz2<br \/>\n-r&#8211;r&#8211;r&#8211; 1 root wheel 337920 Feb 7 08:34 pxeboot<\/p>\n<p>\/tftpboot\/boot # ls -l \/tftpboot\/boot\/kernel<br \/>\ntotal 2564<br \/>\n-rwxr-xr-x 1 root wheel 2565979 Feb 7 15:36 kernel.bz2<\/p>\n<p>loader.rc:<br \/>\necho Loading kernel<br \/>\nload \/boot\/kernel\/kernel<br \/>\necho Loading md_image &#8230;<br \/>\nload -t md_image \/boot\/netboot.img<br \/>\nset vfs.root.mountfrom=&#8221;ufs:\/dev\/md0&#8243;<br \/>\nset console=&#8221;comconsole&#8221;<br \/>\nboot<\/p>\n<p>Here dear readers, is where I leave you.\u00a0 If you&#8217;ve done all the right things &#8230; you should end up booting up into your newly built MFS root.\u00a0 If you haven&#8217;t done all the right things or I&#8217;ve omitted something, then the Nazgul will find you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Irritatingly, I couldn&#8217;t find a decent cut-n-paste how to on the Internet for using a much loved and mostly overlooked FreeBSD installation and boot up process using a fully cooked diskless image fetched via TFTP instead of the really well documented and fantastic howto on NFS booting. Primarily, I wanted to switch off of NFS [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"_share_on_mastodon":"0"},"categories":[1],"tags":[],"share_on_mastodon":{"url":"","error":""},"_links":{"self":[{"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=\/wp\/v2\/posts\/247"}],"collection":[{"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=247"}],"version-history":[{"count":2,"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=\/wp\/v2\/posts\/247\/revisions"}],"predecessor-version":[{"id":251,"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=\/wp\/v2\/posts\/247\/revisions\/251"}],"wp:attachment":[{"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=247"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=247"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.ignoranthack.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}