Tag Archives: loader

Upgrade FreeBSD with ZFS Boot Environments

I am known as a strong ZFS Boot Environment supporter … and not without a reason. I have stated the reasons ‘why’ many times but most (or all) of them are condensed here – https://is.gd/BECTL – in my presentation about it.

The upcoming FreeBSD 13.0-RELEASE looks very promising. In many tests it is almost TWICE as fast as the 12.2-RELEASE. Ouch!

The detailed tests are available on the phoronix.com site.

Having 12.2-RELEASE installed I wanted to check 13.0-BETA* to check if things that are important for me – like working suspend/resume for example – work as advertised on the newer version. It is the perfect task that can be achieved by using ZFS Boot Environments.

In the example below we will create entire new ZFS Boot Environment with clone of our current 12.2-RELEASE system and upgrade it there (in BE) to the 13.0-BETA3 version … and there will only be required on reboot – not three as in typical freebsd-update(8) upgrade procedure.

I assume that you have FreeBSD 12.2-RELEASE installed with ZFS (default ZFS FreeBSD install) and its installed in UEFI or UEFI+BIOS mode.

Here are the steps that will be needed.

(host) # beadm create 13                        # create new '13' ZFS Boot Environment
       Created successfully
(host) # beadm mount 13 /var/tmp/BE-13          # mount new '13' BE somewhere
       Mounted successfully on '/var/tmp/BE-13'
(host) # chroot /var/tmp/BE-13                  # make chroot(8) into that place
  (BE) # mount -t devfs devfs /dev              # mount the devfs(8) in that BE
  (BE) # rm -rf /var/db/freebsd-update          # remove any old patches
  (BE) # mkdir /var/db/freebsd-update           # create fresh dir for patches
  (BE) # freebsd-update upgrade -r 13.0-BETA3   # fetch the patches needed for upgrade
  (BE) # freebsd-update install                 # install kernel and kernel modules
  (BE) # freebsd-update install                 # install userspace/binaries/libraries
  (BE) # pkg upgrade                            # upgrade all packages with pkg(8)
  (BE) # freebsd-update install                 # remove old libraries and files
Β  (BE) # exit                                   # leave chroot(8) environment
(host) # umount /var/tmp/BE-13/dev              # umount the devfs(8) in that BE
(host) # beadm activate 13                      # activate new '13' BE
       Activated successfully

I am using mine sysutils/beadm for the process but you as well may use the bectl(8)Β from FreeBSD base system.

We will also need new FreeBSD loader(8) which will be updated this way – thanks to @JeffSipek for pointing that out.

On my system FreeBSD is installed on ada1 device.

(host) # gpart show -p ada1 | grep efi                # find UEFI msdosfs(5) partition
               40     409600  ada1p1  efi  (200M)     # <-- this one
(host) # mount_msdosfs /dev/ada1p1 /mnt               # mount it under /mnt
(host) # find /mnt                                    # display its contents
       /mnt
       /mnt/efi
       /mnt/efi/boot
       /mnt/efi/boot/bootx64.efi                      # update bootx64.efi file
(host) # cp /boot/boot1.efi /mnt/efi/boot/bootx64.efi # copy from /boot/boot1.efi file
(host) # umount /mnt                                  # unmount /mnt filesystem

There is small chance that you will not be able to mount the efi partition. Even fsck(8) is not able to help here.

Typical errors that some users faced look like that:

(host) # mount_msdosfs /dev/ada1p1 /mnt # error when trying to mount efi partition
       mount_msdosfs: /dev/ada1p1: Invalid argument

(host) # fsck_msdosfs -y /dev/ada1p1    # error when trying to fsck(8) that partition
       ** /dev/ada1p1
       Invalid signature in boot block: 0b6a

If you hit that problem then first backup your current efi partition to for example /BACKUP.ada1p1 file.

(host) # dd < /dev/ada1p1 > /BACKUP.ada1p1 bs=1m

Now we will create fresh efi partition from scratch.

(host) # newfs_msdos -F 32 -c 1 /dev/ada0p1            # create new FAT32 partition
(host) # mount_msdosfs /dev/ada0p1 /mnt                # mount it under /mnt
(host) # mkdir -p /mnt/efi/boot                        # create needed directories
(host) # cp /boot/loader.efi /mnt/efi/boot/bootx64.efi # copy from /boot/loader.efi file
(host) # umount /mnt                                   # unmount /mnt filesystem

Now you should have new ‘working’ efi partition.

The last step is to reboot(8) into the new 13.0-BETA3 system.

(host) # reboot

If you find any problems with new bootloader not being able to load your new FreeBSD then you may alternatively copy the /boot/boot1.efi instead of /boot/loader.efi into the /mnt/efi/boot/bootx64.efi place.

Keep in mind that if you boot from geli(8)encrypted system then /boot/loader.efi is mandatory and you will not be able to boot if you would use /boot/boot1.efi file instead.

Done.

You should now see the new FreeBSD loader(8) in all its glory πŸ™‚

You may now enjoy latest FreeBSD 13.0-BETA3 installation.

Same steps will be required to update to soon to be available FreeBSD 13.0-RC* (RC1/RC2/RC3) version and finally FreeBSD 13.0-RELEASE hopefully somewhere in March 2021.

UPDATE 1 – What if Everything Went Fine

You now have most up to date FreeBSD system that should work faster then 12.2-RELEASE and you still has your older 12.2-RELEASE Boot Environment that you can go back to if you find any problems with 13.0 version.

On my system it looks like that:

(host) # beadm list
       BE   Active Mountpoint Space Created
       12.2 -      -           6.5G 2021-02-12 10:15
       13   NR     /          18.8G 2021-02-13 11:32

The Space column is little misleading as it takes into account snapshots space used for example. To get exact information each Boot Environment takes use -D option. This way you will get information about each Boot Environment space separately.

(host) # beadm list -D
       BE   Active Mountpoint  Space Created
       12.2 -      -            9.8G 2021-02-12 10:15
       13   NR     /            9.6G 2021-02-13 11:32

I will be keeping the 12.2-RELEASE Boot Environment for a while – maybe I will delete it a month or so after 13.0-RELEASE is available but if you tested all your needs and feel that 13.0 fulfills all your needs the same way or better then 12.2-RELEASE then you may delete that older Boot Environment with below command.

(host) # beadm destroy 12.2

UPDATE 2 – What if Something Goes Wrong

Generally if the new BE named ‘13‘ does not boot (or hangs at boot) then just select your earlier Boot Environment that you used before the upgrade – the one that has 12.2-RELEASE inside it.

You now have the system that worked for you before we proceed to the upgrade process.

If that fails (or bootloader is broken) then grab the FreeBSD-13.0-BETA3-amd64-memstick.img image and write it on some pendrive with dd(8) command.

# dd if=FreeBSD-13.0-BETA3-amd64-memstick.img of=/dev/da0 bs=1M status=progress

As you now have the pendrive with FreeBSD 13.0-BETA3 then you may boot from it and fix your installation. Pick LiveCD after its loaded. Then type root at login: prompt and hit [ENTER] for empty password.

The list of tasks that can be done now depends on what is broken and I can not guess every possible error and fix scenario so if you hit any problems during that upgrade process then just contact me with your preferred way and we will figure something out.

EOF

FreeBSD Desktop – Part 1 – Simplified Boot

This is the first post in the FreeBSD Desktop series.

You may want to check other articles in the FreeBSD Desktop series on the FreeBSD Desktop – Global Page where you will find links to all episodes of the series along with table of contents for each episode’s contents.

The default FreeBSD boot process is quite verbose with a lot of debugging information along with kernel messages. We may divide that boot process into several β€˜screens’ or stages. First thing You see is the β€˜BIOS’ screen of the computer manufacturer. SecondΒ  thing is the FreeBSD BTX Loader. The third one is the FreeBSD Boot Menu with eventual ZFS Boot Environments if You use ZFS for root filesystem and other options to select like Single User Mode for example. The 4th one is the system boot along with kernel messages in non-native resolution. In the middle of that stage screen switches to native resolution and continues to display kernel messages and services leading to the text prompt with login: at the end. There comes optional fifth screen which may be graphically started (x11) login manager like slim or gdm.

This verbose information is usually useful for servers but not that much for laptops and/or desktop/workstation systems. The UNIX philosophy is to not β€˜say’ anything to stdout if everything is OK, so stdout/stderr should only be used when something is wrong … like on AMIGA, if anything is wrong then I want to see big red sign like [GURU MEDITAION] but if everything is ok, shut the … slience is golden πŸ™‚

guru-meditation

I really like Sun Solaris 10 approach here, that it boots with minimal information like its version and hostname into the login: prompt in less then 10 lines. The image below is from the first Sun Solaris 10 boot, so it includes additional OpenSSH server key generation information.

sun-solaris-10-boot-first

Unfortunately – despite what Oracle says – Oracle Solaris is dying, I gathered most of the information here – Oracle just killed Solaris/SPARC/ZFS teams – https://forums.freebsd.org/threads/62320/ – on FreeBSD Forums. The recent Oracle Solaris 11.4 release process along with public beta will not change that. Oracle Solaris will be kept in maintenance mode for the rest of its life, which is set by Oracle to 2034 currently. Pity because even BSD bits recently found its way into it Solaris, for example the OpenBSD PF firewall, there are some differences – Comparing PF in Oracle Solaris to IP Filter and to OpenBSD Packet Filter – https://docs.oracle.com/cd/E37838_01/html/E60993/pfovw-comparall.html – but there are differences between OpenBSD PF and FreeBSD PF too.

Back to FreeBSD – according to the project website – https://freebsd.org/ – β€œFreeBSD is an operating system used to power modern servers, desktops, and embedded platforms” so why not tune the boot process to be more appealing on laptops/desktops? Below are the stages of the default FreeBSD boot process up to the login: prompt.

stage0-BIOS.jpg

stage1-BTX-Loader.jpg

stage2-Boot-Menu.jpg

stage3-NOMOD-Non-Native-Boot.jpg

stage4a-NOMOD-Native-Boot-A.jpg.jpg

stage4b-NOMOD-Native-Boot-B.jpg

Not very lean to my standards. But with one parameter in /boot/loader.conf and 5 slightly silenced startup scripts its whole a lot better. Here are the modifications needed.

First add the boot_mute=YES option to the /boot/loader.conf file.

As we are here, You may as well add autoboot_delay=2 parameter to the /boot/loader.conf file to speed up boot process by 8 seconds. Default delay is 10 seconds.

% grep boot_mute /boot/loader.conf
boot_mute=YES
%

Next we will need to modify these startup scripts.

  • /etc/rc.d/ldconfig
  • /etc/rc.d/netif
  • /etc/rc.d/nfsclient
  • /etc/rc.d/random
  • /etc/rc.d/routing

Here is the summary of the changes. In most cases its just adding 1> /dev/null or 1> /dev/null 2> /dev/null to not display unneeded information at boot process.

% grep -n -E '(1|2)> /dev/null' /etc/rc.d/* | grep -E 'routing|netif|ldconfig'
/etc/rc.d/ldconfig:40: check_startmsgs && echo 'ELF ldconfig path:' ${_LDC} 1> /dev/null
/etc/rc.d/ldconfig:60: echo '32-bit compatibility ldconfig path:' ${_LDC} 1> /dev/null
/etc/rc.d/netif:260: /sbin/ifconfig ${ifn} 1> /dev/null 2> /dev/null
/etc/rc.d/routing:70: eval static_${_a} delete $_if 1> /dev/null 2> /dev/null
/etc/rc.d/routing:97: static_$2 add $3 1> /dev/null 2> /dev/null
/etc/rc.d/routing:104: static_$2 add $3 add $3 1> /dev/null 2> /dev/null

The only exception is the /etc/rc.d/random which requires little more love.

% grep -n -A 8 'random_start()' /etc/rc.d/random
45:random_start()
46-{
47-
48-   # if [ ${harvest_mask} -gt 0 ]; then
49-   #       echo -n 'Setting up harvesting: '
50-   #       ${SYSCTL} kern.random.harvest.mask=${harvest_mask} > /dev/null
51-   #       ${SYSCTL_N} kern.random.harvest.mask_symbolic
52-   # fi
53-

Here are diff(1) patches if that way will be easier for you.

% diff -rq ~/CLEAN-FreeBSD-11.1-RELEASE/etc/rc.d /etc/rc.d | column -t
Files  ~/CLEAN-FreeBSD-11.1-RELEASE/etc/rc.d/ldconfig   and  /etc/rc.d/ldconfig   differ
Files  ~/CLEAN-FreeBSD-11.1-RELEASE/etc/rc.d/netif      and  /etc/rc.d/netif      differ
Files  ~/CLEAN-FreeBSD-11.1-RELEASE/etc/rc.d/nfsclient  and  /etc/rc.d/nfsclient  differ
Files  ~/CLEAN-FreeBSD-11.1-RELEASE/etc/rc.d/random     and  /etc/rc.d/random     differ
Files  ~/CLEAN-FreeBSD-11.1-RELEASE/etc/rc.d/routing    and  /etc/rc.d/routing    differ
% diff -u ./rc.d/ldconfig /etc/rc.d/ldconfig
--- ./rc.d/ldconfig     2017-07-21 04:11:06.000000000 +0200
+++ /etc/rc.d/ldconfig  2017-12-18 09:12:18.190074000 +0100
@@ -37,7 +37,7 @@
                                _LDC="${_LDC} ${i}"
                        fi
                done
-               check_startmsgs && echo 'ELF ldconfig path:' ${_LDC}
+               check_startmsgs && echo 'ELF ldconfig path:' ${_LDC} 1> /dev/null
                ${ldconfig} -elf ${_ins} ${_LDC}
 
                case `sysctl -n hw.machine_arch` in
@@ -57,7 +57,7 @@
                                fi
                        done
                        check_startmsgs &&
-                           echo '32-bit compatibility ldconfig path:' ${_LDC}
+                           echo '32-bit compatibility ldconfig path:' ${_LDC} 1> /dev/null
                        ${ldconfig} -32 -m ${_ins} ${_LDC}
                        ;;
                esac

% diff -u ./rc.d/netif /etc/rc.d/netif
--- ./rc.d/netif        2017-07-21 04:11:06.000000000 +0200
+++ /etc/rc.d/netif     2017-11-30 17:32:11.394251000 +0100
@@ -257,7 +257,7 @@
                esac
                if check_startmsgs; then
                        for ifn in ${_ok}; do
-                               /sbin/ifconfig ${ifn}
+                               /sbin/ifconfig ${ifn} 1> /dev/null 2> /dev/null
                        done
                fi
        fi
% diff -u ./rc.d/nfsclient /etc/rc.d/nfsclient
--- ./rc.d/nfsclient    2017-07-21 04:11:06.000000000 +0200
+++ /etc/rc.d/nfsclient 2017-12-18 09:15:38.200376000 +0100
@@ -44,7 +44,7 @@
        # successfully notified about a previous client shutdown.
        # If there is no /var/db/mounttab, we do nothing.
        if [ -f /var/db/mounttab ]; then
-               rpc.umntall -k
+               rpc.umntall -k 2> /dev/null
        fi
 }
 load_rc_config $name
% diff -u ./rc.d/random /etc/rc.d/random
--- ./rc.d/random       2017-07-21 04:11:06.000000000 +0200
+++ /etc/rc.d/random    2018-01-09 13:32:18.439347000 +0100
@@ -45,13 +45,13 @@
 random_start()
 {
 
-       if [ ${harvest_mask} -gt 0 ]; then
-               echo -n 'Setting up harvesting: '
-               ${SYSCTL} kern.random.harvest.mask=${harvest_mask} > /dev/null
-               ${SYSCTL_N} kern.random.harvest.mask_symbolic
-       fi
+       # if [ ${harvest_mask} -gt 0 ]; then
+       #       echo -n 'Setting up harvesting: '
+       #       ${SYSCTL} kern.random.harvest.mask=${harvest_mask} > /dev/null
+       #       ${SYSCTL_N} kern.random.harvest.mask_symbolic
+       # fi
 
-       echo -n 'Feeding entropy: '
+       echo -n 'Feeding entropy:'
 
        if [ ! -w /dev/random ] ; then
                warn "/dev/random is not writeable"

% diff -u ./rc.d/routing /etc/rc.d/routing
--- ./rc.d/routing      2017-07-21 04:11:06.000000000 +0200
+++ /etc/rc.d/routing   2017-12-18 09:22:16.604428000 +0100
@@ -67,7 +67,7 @@
        ""|[Aa][Ll][Ll]|[Aa][Nn][Yy])
                for _a in inet inet6 atm; do
                        afexists $_a || continue
-                       eval static_${_a} delete $_if
+                       eval static_${_a} delete $_if 1> /dev/null 2> /dev/null
                        # When $_if is specified, do not flush routes.
                        if ! [ -n "$_if" ]; then
                                eval routing_stop_${_a}
@@ -94,14 +94,14 @@
        _ret=0
        case $1 in
        static)
-               static_$2 add $3
+               static_$2 add $3 1> /dev/null 2> /dev/null
                _ret=$?
                ;;
        options)
                options_$2
                ;;
        doall)
-               static_$2 add $3
+               static_$2 add $3 add $3 1> /dev/null 2> /dev/null
                _ret=$?
                options_$2
                ;;

Now lets see how FreeBSD boots now after the modifications.

stage0-BIOS.jpg

stage1-BTX-Loader.jpg

stage2-Boot-Menu.jpg

stage3-MOD-Non-Native-Boot.jpg.jpg

stage4a-MOD-Native-Boot-A.jpg.jpg

stage4b-MOD-Native-Boot-B.jpg

Its definitely not perfect, but a lot better in my taste.

Now lets login to desktop πŸ™‚

I prefer not to use a login manager so I have an alias named x to xinit command. This way after I login I type x press [ENTER] and x11 desktop is started.

% which x
x: aliased to xinit ~/.xinitrc -- -dpi 75 -nolisten tcp 1> /dev/null 2> /dev/null

stage4c-MOD-Native-Boot-C.jpg

stage5-X11.jpg

UPDATE 1 – FreeBSD 12.x

I recently tried FreeBSD 12.0-RC* versions and there is one ‘talkative’ script that also could be ‘silenced’ a little.

Its the /etc/rc.d/devmatch scrtipt.

Here is the needed patch to make it great again nice and clean again.

% diff -u /home/vermaden/rc-devmatch devmatch 
--- /home/vermaden/rc-devmatch        2018-11-27 17:49:53.573514000 +0100
+++ devmatch    2018-11-27 17:50:11.955342000 +0100
@@ -65,7 +65,7 @@
                case "#${x}#" in
                *"#${m}#"*) continue ;;
                esac
-               echo "Autoloading module: ${m}"
+               # echo "Autoloading module: ${m}"
                kldload -n ${m}
        done
        devctl thaw

UPDATE 2 – The drm-kmod Silencing

Recently to get support for newer GPUs the drm-kmod meta port/package is needed. The thing is that if you add the /boot/modules/i915kms.ko (for Intel GPUs) to the kld_list parameter it will display following error message from the kernel even with boot_mute=YES in the /boot/loader.conf file.

Loading kernel modules:
Dec 16 11:08:03 t420s kernel: Failed to add WC MTRR for [0xe0000000-0xefffffff]: -28; performance may suffer

The syslogd is guilty here with its default configuration in the /etc/syslog.conf file. To make it silent (not print pointless messages) make this change in the /etc/syslog.conf file.

% diff -u /root/syslog.conf /etc/syslog.conf
--- /root/syslog.conf   2018-12-18 11:49:48.204878000 +0100
+++ /etc/syslog.conf    2018-12-18 11:49:55.681504000 +0100
@@ -5,7 +5,7 @@
 #      separators. If you are sharing this file between systems, you
 #      may want to use only tabs as field separators here.
 #      Consult the syslog.conf(5) manpage.
-*.err;kern.warning;auth.notice;mail.crit                       /dev/console
+# *.err;kern.warning;auth.notice;mail.crit                       /dev/console
 *.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err  /var/log/messages
 security.*                                                     /var/log/security
 auth.info;authpriv.info                                        /var/log/auth.log

Now it will not print these pointless messages.

This applies both to 11.2-RELEASE and 12.0-RELEASE versions.

UPDATE 3 – Silence the Services Starting Messages

Thanks to the vmisev suggestion we can silence the FreeBSD boot process even more.

Just add rc_startmsgs=NO to your /etc/rc.conf file and reboot to see effects.

Here is already silenced boot process by my earlier settings.

rc_startmsgs_YES.jpg

After adding rc_startmsgs=NO to the /etc/rc.conf file the boot messages are cut in half.

rc_startmsgs_NO.jpg

Now its very close to Solaris/Illumos provides πŸ™‚

EOF