Dual boot UEFI Linux/FreeBSD

There a lot of tutorials out there explaining how to dual boot Linux and FreeBSD on legacy BIOS but not so much for UEFI only systems. So I will share my experience installing Debian 10.2 and FreeBSD 12.1 on my ThinkPad X250 in UEFI only mode. It should be easy to adapt this to other Linux distributions and other systems than FreeBSD.

This post will be soon followed by another post explaining how FreeBSD and Linux can get along with each other after being installed. But now for the installation.

First ensure in your UEFI/BIOS settings that boot is set to UEFI only and CSM disabled. You don’t want to boot the installer in legacy mode by accident.

We will use a GTP partition table and the create the following partitions:

  1. EFI System Partition (ESP): To store the UEFI bootloaders
  2. SWAP + ext4: For Linux
  3. SWAP + UFS: For FreeBSD

Note that we could technically use the same SWAP for both FreeBSD and Linux. Still I prefer to use 2 SWAP partitions and use both of them in each OS. It’s a matter of preference I guess.

Install Linux and FreeBSD

Install Linux

We start installing Debian so that Linux stays in charge of GRUB. We do so because it’s frequent on Linux to have multiple kernel variants, for instance a more recent version of the kernel, custom or a RT patched kernel. So we let Linux’s package manager handle all of that.

At the partitioning step, select “Manual partitioning” and create a GPT partition table. For UEFI to function properly, we need a EFI System Partition (ESP), 500MB should be more than enough for this. Then a Linux swap partition and a Linux ext4 partition for the data. Leave some space unallocated for FreeBSD.

It is possible to use Linux’s swap partition in FreeBSD. More about that later. For now we will let each OS have its own swap partition.

Complete the Debian installation. It should install grub bootloader in the EFI partition. Check that Debian boots properly. Then start the FreeBSD install.

Install FreeBSD

There used to be a separate installation image for FreeBSD UEFI. This is not the case anymore, so you can use the AMD64 memstick image for 12.1-RELEASE on the FreeBSD download page.

Boot the installer and go ahead up to the partitioning step. Use the space you left unallocated for the freebsd-swap and freebsd-ufs partitions. The installer will complain that an EFI partition is required for the system to work properly and propose to create it. Ignore this as the partition was already created under Linux. It is weird though that the FreeBSD installer does not detect this, but there is a FreeBSD forum post about this issue.

Proceed and complete the FreeBSD installation. Then reboot into Debian to configure the dual boot.

GRUB dual boot

It is now time to tell Linux’s GRUB about our newly installed FreeBSD system.

We created the swap partitions before the data partitions for each OS, so to resume our partition table we now have:

  1. EFI System Partition
  2. Linux SWAP
  3. Linux ext4
  4. FreeBSD SWAP
  5. FreeBSD UFS

So our FreeBSD partition is (hd0, gpt5) in GRUB parlance. You may need to adapt this to your own partition scheme though. Once in Debian as root edit /etc/grub.d/40_custom and after the comment add:

menuentry 'FreeBSD' {
insmod ufs2
set root='(hd0,gpt5)'
chainloader /boot/loader.efi
}

If you want, you can also configure FreeBSD as the default entry by editing /etc/default/grub and change DEFAULT=0 to DEFAULT=FreeBSD.

Then update grub with update-grub2, finally reboot and select FreeBSD in the GRUB menu. You can now boot both Linux and FreeBSD.

FreeBSD aware UEFI

It is now possible to boot both Debian and FreeBSD from GRUB. However it is not yet possible to boot FreeBSD directly from UEFI. To do so we need to copy the FreeBSD UEFI loader in to EFI partition and register it. Debian already mounts the EFI partition but FreeBSD doesn’t, so for the fun of it, let’s manage all that under FreeBSD and install the FreeBSD UEFI loader. /dev/ada0p1 is the EFI partition, but you may need to adapt this to your partition scheme though.

# We mount the EFI partition on /boot/efi similarly to Linux.
mkdir /boot/efi
echo '/dev/ada0p1 /boot/efi msdosfs rw,noatime 0 0' >> /etc/fstab
mount /boot/efi

# Install the FreeBSD UEFI loader.
mkdir /boot/efi/EFI/freebsd
cp /boot/boot1.efi /boot/efi/EFI/freebsd/bootx64.efi

Now let’s create an UEFI entry for this loader. Note that this is for FreeBSD’s efibootmgr, not the Linux’s one.

# Create the boot variable.
efibootmgr -c -l /boot/efi/EFI/freebsd/bootx64.efi -L "FreeBSD"

# Check the variable number for the new boot variable and activate it.
efibootmgr
efibootmgr -a 15

# Change the boot order to leave Debian and GRUB in charge.
efibootmgr -o 14,15

Time to reboot! Select the boot menu with (generally with F12, at least on my ThinkPad X250) and FreeBSD should appear. Select it and it should boot FreeBSD directly.

You are done! Next time how to let FreeBSD and Linux talk to each other.

Intel kernel panic

If you recently had your FreeBSD 12.1 running ThinkPad X250 (or any other laptop with a Intel GPU) crashing systematically on boot, it may be because of the i915kms module from the graphics/drm-kmod port. If you did install this or drm-fbsd12.0-kmod through the packages, you should know that the binary package is only compatible with FreeBSD 12.0. If you want this to work (that is, not to cause a kernel panic), you should compile the port manually [1]. In other words:

portsnap fetch update
cd /usr/ports/graphics/drm-fbsd12.0-kmod
make install clean

FreeBSD on Intel Broadwell

Around two years ago I posted about using FreeBSD 10 on the X250. A great deal has happened since then.

It is now possible to use the Intel Broadwell integrated graphic card (among others) under FreeBSD-CURRENT FreeBSD-STABLE! Also if I’m right, this will be integrated in FreeBSD 11.2-RELEASE. What a great day it is for FreeBSD on the desktop. I bet FreeBSD 12 will be truly great!

Note that it works much better on STABLE now than CURRENT because CURRENT is -well- not that stable…

So if you want to try this now, what you first need to do is to upgrade to the STABLE branch. For this you need to fetch the source, buildworld, buildkernel and installworld. Here is a very quick tuto (that you may need to adapt though). You can also find this here.


# Don't forget to upgrade RELEASE
# in any case that there were any bugs in the building tools.
freebsd-update fetch
freebsd-update install
reboot
freebsd-update install

# Replace the current source tree with STABLE.
mv /usr/src /usr/src-RELEASE
svn checkout svn://svn.freebsd.org/base/stable/11 /usr/src

# Build! Build! Build!
cd /usr/src
make buildworld -j4

# Customize (while you are at it) and build STABLE kernel.
cd /usr/src/sys/amd64/conf
cp GENERIC {YOUR-CONF}
vim {YOUR-CONF}
cd /usr/src
make buildkernel KERNCONF={YOUR-CONF}
make installkernel KERNCONF={YOUR-CONF}
reboot

# Now it's time to install world over the new kernel.
# In the meantime we also update configuration files
# with mergemaster.
mergemaster -p
cd /usr/src
make installworld
mergemaster -Ui
reboot

Now that your are on the latest STABLE, you can update the ports tree and install drm-next.


# Install ports tree if needed.
portsnap fetch
portsnap extract

# Install drm-next.
cd /usr/ports/graphics/drm-next-kmod
make install clean

Finally you must tell rc.conf to use the new i915 module instead. That is, add in /etc/rc.conf:


kld_list="/boot/modules/i915kms.ko"

Just one final reboot and you are done! Test this with the xorg and mesa-demos ports. Just startx from your user and check /var/log/Xorg.0.log to see if the intel driver was correctly loaded.