Install Arch Linux on EFI

Most what you will find in this post comes from this gist. I’m rewritting this here as a note in any case. Some more info about the installation process here on ArchWiki and also more info about the post-installation process.

  1. Boot USB flash drive and make sure it’s connected via Ethernet.
  2. Change terminal keys if you are not in qwerty:
    loadkeys fr
  3. Disable the beeping sound (this one will save your ears and sanity):
    setterm -blength 0
  4. Check if the system was booted with UEFI:
    cat /sys/firmware/efi/fw_platform_size

    It should exists and be 64 if it’s booted in UEFI x86_64. If that’s the case, continue.

  5. Check that you have an IP address and try a ping to check your Internet connectivity:
    ip address
    ping 8.8.8.8
    
  6. Update system clock and check status:
    timedatectl set-ntp true
    timedatectl status
  7. Enable SSH, this might be useful if you want to continue the installation from elsewhere or transfer files via sftp:
    systemctl start sshd
  8. List the disks then proceed with creating the partitions:
    fdisk -l
    cfdisk /dev/sda
    

    Create a EFI partition of 256M to 512M, a several GB swap partition and what is left with a Linux root partition.

  9. Format the partitions:
    mkfs.fat -F32 /dev/sda1
    mkfs.ext4 -L root -m 0 /dev/sda3
    
  10. Mount the root partition:
    mount -o noatime /dev/sda3 /mnt
    
  11. Install the base packages:
    pacstrap -Ki /mnt base linux linux-firmware
    
  12. Generate the fstab:
    genfstab -U -p /mnt >> /mnt/etc/fstab
    
  13. Chroot in the filesystem:
    arch-chroot /mnt
    
  14. Configure the terminal keyboard:
    vim /etc/vconsole.conf
  15. Set the timezone:
    ln -sf /usr/share/zoneinfo/Europe/Brussels /etc/localtime
    
  16. Update the hardware clock:
    hwclock --systohc
    
  17. Install other packages:
    pacman -S grub efibootmgr dosfstools openssh os-prober mtools net-tools inetutils netctl dhcpcd dhclient vim
    
  18. Edit and set-up the locale:
    vim /etc/locale.gen
    locale-gen
    
  19. Setup root password:
    passwd
    
  20. Create and mount EFI directory:
    mkdir /boot/EFI
    mount -o noatime /dev/sda1 /boot/EFI
  21. Time to install the GRUB bootloader and write the config:
    grub-install --target=x86_64-efi --bootloader-id=grub_uefi --recheck
    grub-mkconfig -o /boot/grub/grub.cfg
    
  22. If needed you might configure an extra entry within the GRUB boot list, for instance for a dualboot with FreeBSD. To that end, edit /etc/grub.d/40_custom and add (at the end of this file):
    menuentry FreeBSD {
      insmod ufs2
      set root='(hd0,gpt3)'
      chainloader /boot/loader.efi
    }
    

    Then update the grub configuration with:

    grub-mkconfig -o /boot/grub/grub.cfg
  23. Time to reboot:
    exit
    reboot
    

Post install ArchLinux

In the past few months, I had to install ArchLinux several times. While it’s now my Linux distribution of choice for an everyday use, a clean install of Arch is rather bland. So in this post, I’ll try to resume the different step I took to spice a default Arch install a bit more to my taste. Most of the choices here are purely personals.

New user

By default, no user is created, so you have to create one along with its home directory. Also ensure that your home is in 750 instead of 755.

useradd -m youruser
chmod 750 /home/youruser

Fstab and tmpfs

By default, on a new install, /etc/fstab comes up mostly empty as most of it is hidden away by systemd. But I usually change some options and add tmpfs. Here’s an example:

/dev/vda2 / ext4 rw,noatime,nodiscard,stripe=4 0 1
/dev/vda1 /boot vfat rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro	0 2

/dev/vdb1 none swap sw 0 0
/dev/vdb2 /mnt/data ext4 rw,noatime,nodiscard 0 0

tmpfs /tmp tmpfs noatime,mode=1777 0 0
tmpfs /run tmpfs noatime,nosuid,noexec,mode=755 0 0
tmpfs /run/shm tmpfs noatime,nosuid,nodev,mode=1777 0 0

pacman cache

If you have a separate data partition/hdd, it may be a good idea to move the pacman cache there. However you cannot do so using symlinks, pacman won’t like that at all. Instead you have to edit the CacheDir entry in /etc/pacman.conf.

yay

Arch comes with its binary package manager (pacman) and also the community maintained Arch User Repository (AUR) providing access to more packages that are generally built from source. Yay is a AUR package manager so you don’t have to clone and install AUR repos manually.

Note that the commands below need to be run as your normal user, otherwise makepkg will complain about possible catastrophic happenstances.

sudo pacman -S --needed base-devel git
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si

legacy network interface name

Back in the days, network interfaces on Linux had simple names like eth0, wlan0, and so on. This changed multiple times because the order in which the interface drivers are loaded make these names not 100% predictable. However, if you know that your boot order is pretty static and never change, you might want to get the legacy naming scheme. To do so, either add net.ifnames=0 to the kernel parameters or override the appropriate udev rule. In this case I use the latter option.

ln -s /dev/null /etc/udev/rules.d/80-net-setup-link.rules

netctl

I prefer to use netctl instead of systemd-networkd to manage the network. Since I constantly use other Unix and Unix-likes systems that are not Linux, and since I’ve been doing so for decades, I also prefer to use ifconfig instead of ip. When asked I also choose openresolv instead of systemd-resolved, the latter tries to do too many things in your back.

pacman -S net-tools inetutils netctl dhcpcd dhclient
systemctl enable netctl

Then you have to create a default profile, for instance in /etc/netctl/network. Here is a default config that configures the interface with DHCP for IPv4 and SLAAC for IPv6:

Description="Basic DHCP ethernet connection"
Interface=eth0
Connection=ethernet
IP=dhcp
IP6=stateless

You still have to enable the profile:

netctl enable network

Some packages

Here is the bare minimum I would install on a new install, whether headless or xorg powered.

  • uptimed
  • ntp/chrony
  • ncdu
  • zsh
  • htop
  • starship
  • neovim
  • wget/curl/lynx
  • tcpdump/nmap
  • fzf
  • tree
  • bzip2/xz/gzip/zstd
  • the_silver_searcher
  • git
  • cpio
  • rsync
  • dialog
  • ipv6calc
  • dos2unix
  • exa/bat

Some extra packages

  • openssh: remote access/sync stuff and so on
  • bindfs: useful if you need to rebind user/permission on mount points, for instance on a shared mount
  • tldr: recall any command usage (I recommend the tealdeer client, written in Rust)
  • doggo: DNS queries
  • vulkan-virtio/mesa-vdpau: useful for graphical acceleration in a Qemu VM

HiFiBerry on Debian ARM64

Long are gone the days of the ten thousands songs Winamp playlist, the modern way of listening to music consists solely of spotify blasting its (not-so-randomly) set of tracks and ads on random variants of laptop/phones/speakers.

But I will forever say no to that.
Spotify is bad for the artists, for you, our planet and it has as much a good impact on musical culture as Facebook has on our social life. Today, the common physical storage available locally (if you don’t depend uniquely on the cloud) has more than enough room to host all the music you’d ever want to listen to. Of course this means that you have to handle your music playlist manually. But that effort will refine your tastes as to what is genuinely good music to your ears, and what is just effective product placement.

To handle my music media center, I always had a RPi stucked to my HiFi system. This RPi would only handle playing music (mpd) and remote control (Cantata, MPDroid, ). This music would be stored remotely on my NAS and accessible in read-only from NFS (yup NFS not SAMBA/CIFS).

The music is played through a RPi HAT, the HiFiBerry DAC+ based on Texas Instruments PCM5102A DAC chip. This was done on a common Raspbian (the only viable solution back then), may be you could do the same easily on the new RaspberryPi OS. I did try to replicate the same setup on FreeBSD but neither the HiFiBerry nor the PCM5102 codec were supported. Attempts to play the music through a USB audio device instead of the HiFiBerry HAT were ultimately unsuccessful probably because of the USB DWC2 host driver. The same attempt on a FreeBSD running RPi4 with PCIe XHCI USB host ran the same USB audio devices perfectly well.

[Debian Diversity Logo -- https://gitlab.com/valessiobrito/artwork (GPLv3 -- https://gitlab.com/valessiobrito/artwork)]

But since I only had a single RPi4 that was already in use, and the fact that RPi4 are currently way overpriced and out-of-stock, I resolved to try a Linux based setup on a RPi3B. But you see, Raspbian is rather restricted by the fact that the RPi platforms ranges from ARMv6 to ARMv8 SoC. That’s 32 to 64-bit, so as a compromise Raspbian runs everything in 32-bit even on ARM64 capable SoC like the RPi3 or better (the new Raspberry Pi OS has some ARM64 images although it’s not widely advertised). The challenge was that it should run Debian ARM64 and play audio through the HiFiBerry DAC+.

The main problem is that the Debian ARM64 image runs a mainline/vanilla Linux kernel. Among other things this version of the kernel does not have support for the HiFiBerry. Instead I resolved to compile my own kernel with the appropriate driver included. Also to avoid the hurdle of porting everything HiFiBerry related and other RPi/BCM goodies to the mainline kernel, I used the Raspberry Pi Foundation kernel source tree.

As a starting point, I used the configuration of the RPi3B kernel from the Debian ARM64 image, which you can find in /boot/config-5.10.0-8-arm64. Crosscompiling the kernel for ARM64 was pretty straight forward:

# Mount the RPi image
mount /dev/sdf1 /mnt/rpi/fat32
mount /dev/sdf2 /mnt/rpi/ext4

# Install and clone the kernel
apt-get install crossbuild-essential-arm64
git clone git://github.com/raspberrypi/linux.git

# Setup some variable for cross-compiling.
cd linux
export KERNEL=kernel8
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

# Kernel configuration
# (be sure to select the appropriate platform or the Device Tree Blob won't be compiled)
cp /mnt/rpi/ext4/boot/config-5.10.0-8-arm64 .config
make oldconfig
make menuconfig

# Compile!
make Image modules dtbs -j32

# Install
# (you might have to create the 'overlays' directory in the fat32 partition)
VMLINUZ=vmlinuz-5.10.74+
make INSTALL_MOD_PATH=/mnt/rpi/ext4 modules_install
cp arch/arm64/boot/dts/broadcom/*.dtb  /mnt/rpi/fat32
cp arch/arm64/boot/dts/overlays/*.dtb* /mnt/rpi/fat32/overlays/
cp arch/arm64/boot/Image "/mnt/rpi/fat32/${VMLINUZ}"
cp arch/arm64/boot/Image "/mnt/rpi/ext4/boot/${VMLINUZ}"

# Umount the RPi image and boot it still on the old working kernel.
umount /dev/sdf1
umount /dev/sdf2

# Connect to the RPi and create the initrd.
# This should also adapt the boot config. 
update-initramfs -c -k 5.10.74+

If you want to play with Device Tree overlays for example to use a RPi HAT like the HiFiBerry, you will have to compile the dtoverlay manipulation command from the RPi userland repository. Install libfdt-dev, compile and install libdtovl in helpers/dtoverlay, compile dtoverlay in host_applications/linux/apps/dtoverlay.

You need ConfigFS and the following kernel options for the dtoverlay command to work with dynamic DT:

CONFIG_DTC=y
CONFIG_OF=y
CONFIG_OF_UNITTEST=y
CONFIG_OF_DYNAMIC=y
CONFIG_OF_OVERLAY=y
CONFIG_OF_CONFIGFS=y

Also mount ConfigFS:

mkdir /config
mount -t configfs none /config

The command expects to find the overlays in /boot/overlays but on the Debian ARM64 image they will probably be in /boot/firmware/overlays. I fixed this with a symlink.

Next I had to fiddle a bit with the Device Tree sources. If you want some nice documentation about them, here’s a nice pdf from Freescale that explains a lot.

When I first tried to add the HiFiBerry overlay with dtoverlay hifiberry-dacplus, it could not apply because of “incompatible devices”. This was caused by discrepancies between the ARM and ARM64 DT sources for the RPi. This driver was made for the ARM arch than runs Raspbian, not ARM64. And the ARM arch DTS/DTSI exposes devices differently than ARM64. I added the missing devices on ARM64, recompiled and reinstalled the DTB on the RPi image. After that the DT overlay applied like a charm.

The HiFiBerry DAC+ is now happily playing music on Debian ARM64. The RPi3B runs at ~1.14W on idle and ~1.35W when playing music. I don’t how know much the fat-free low-power kernel config contributes to that, but it seems to run at ~1.25W on Debian’s vanilla kernel and I have some ideas to reduce the consumption even further.

App. freezing in i3

If you encounter some applications freezing or taking a long time to start while using i3, I think in particular about Skype, Discord, CMST (Connman QT GUI), Hexchat, … then may be here is a solution for you. Those app do not appreciate when the desktop does not have any notification daemon running. So you might just install and start one when i3 starts.

So I’ve just installed lxqt-notificationd. Then you can start it from i3’s config file:

exec --no-startup-id lxqt-notificationd

Now all my applications work like a charm, and I’ve no reason whatsoever to temporarily switch to XFCE4.

Beyond dual boot, make Linux and FreeBSD friends

This is a continuation of a previous post on dual boot UEFI Linux/FreeBSD.

Dual boot is not enough and we want both FreeBSD and Linux to get along for the better. To this end we will discuss several aspect of making both OS recognize each other and work in parallel.

Note that this post in particular is subject to changes. These things evolve rapidly so some details may not be accurate, not up-to-date or differ from your specific setup. So please feel free to comment/update/add ideas/point out errors or missing details. Thanks!

We will look at the following aspect:

Access each other data

The first step is to recall your partition layout and what it looks like on FreeBSD and Linux. Take time to note it on a piece of paper. That’s especially useful if you have extra hard disks with additional data partitions. To recall in the previous post we had:

Name FreeBSD Linux
EFI /dev/ada0p1 /dev/sda1
Linux SWAP /dev/ada0p2 /dev/sda2
Linux ‘/’ (ext4) /dev/ada0p3 /dev/sda3
FreeBSD SWAP /dev/ada0p4 /dev/sda4
FreeBSD ‘/’ (UFS) /dev/ada0p5 /dev/sda5

FreeBSD and Linux can both access their counterpart ext4 and UFS partition. In particular, FreeBSD can also write to Linux’s ext4 partitions. Linux supports writing to UFS in theory, but I would strongly recommend against that. Last time I tested, it only completely wrecked the UFS partition and had to reformat it. In fact, I’d recommend that you mount the counterpart OS partition in read-only to avoid messing with anything. Eventually setup another shared ext4 partition that you access in writing from both Linux and FreeBSD. At least if something goes wrong, you only loose that.

As for the swap partitions, both OS can use each other partition. Linux however requires a special signature which can be created with mkswap. However I don’t think this is still required and it works fine without it.

We will add the mount point in /mnt, that’s as good a place as any. Of course everything below must be done as root.

FreeBSD

Create the mount point for Linux:

mkdir /mnt/linux

We want to mount the second (Linux swap) and third (Linux ext4) partitions, that is for FreeBSD /dev/ada0p2 and /dev/ada0p3. Add the partitions to the end of /etc/fstab:

/dev/ada0p2 none swap sw 0 0
/dev/ada0p3 /mnt/linux ext2fs failok,ro 0 0

Notice the failok option for /mnt/linux. It means that the FreeBSD boot should not fail if the ext4 partition fails to mount. Otherwise, if the partition was marked as dirty by Linux (for instance you did a hard reboot) and then you reboot directly into FreeBSD, mounting the ext4 partition would fail because it requires an fsck.

Linux

Create the mount point for FreeBSD:

mkdir /mnt/freebsd

We want to mount the fourth (FreeBSD swap) and fifth (FreeBSD UFS) partitions, that is for Linux /dev/sda4 and /dev/sda5. Add the partitions to the end of /etc/fstab:

/dev/sda4 none swap sw 0 0
/dev/sda5 /mnt/freebsd ufs nofail,ro,ufstype=ufs2 0 0

Notice the nofail similar to failok in FreeBSD.

Share documents

Now that both OS can access each other data, it’s time to see if we can put this to some use. A first thing that you might do is to share some parts of your home directory. Of course this will be read-only.

What I personally do is selecting the OS that I use most frequently. This one contains everything. Then on the other OS, I use symlinks to some part of my home directory. For instance on Linux:

  • /home/user/Music    -> /mnt/freebsd/home/user/Music
  • /home/user/Pictures -> /mnt/freebsd/home/user/Pictures
  • /home/user/Videos   -> /mnt/freebsd/home/user/Videos

Those don’t change that often when I’m on Linux, but I least I got to listen to music, watch movies and can access pictures.

Share ssh keys

If you frequently use ssh to access your laptop or rsync+ssh to sync your documents, you will soon find yourself with ssh complaining that the host key has changed on the same host. Of course FreeBSD and Linux will both have a separate set of ssh host keys. Thankfully we can use the same key on both.

Suppose that we use FreeBSD’s ssh host keys. On Linux, go into /etc/ssh:

# Remove Linux's ssh host keys
rm ssh_host_*key*

# Link FreeBSD's ssh host keys
for key in /mnt/freebsd/etc/ssh/ssh_host_*key*
do
  ln -s "$key"
done

Don’t forget to service ssh restart. Now you can access both Linux and FreeBSD with ssh as if it was the same host (which it is actually).

Share WPA supplicant (WiFi)

Same principle now for WPA supplicant configuration file. However it’s not as simple as it was for ssh. You see, the WPA supplicant configuration needs different options for the control socket on FreeBSD and Linux. Unfortunately, wpa_supplicant.conf does not allow for file include. Actually it should be possible to arrange FreeBSD and Linux so that the same wpa_supplicant.conf is used on both OS. But this option allows for more flexibility. So here is what I do.

First I create /etc/wpa in both FreeBSD and Linux. Then I edit /etc/wpa/local.conf with the wpa_supplicant options specific to this OS. Then I use this small script to select a particular profile and create the appropriate wpa_supplicant.conf.

#!/bin/sh

if [ ! -r "$1" ]
then
  echo "error: cannot read '$1'"
  exit 1
fi

cat /etc/wpa/local.conf > /etc/wpa_supplicant.conf
cat "$1" >> /etc/wpa_supplicant.conf

The idea behind those profiles is to restrict scanning of new networks depending on the situation. For instance you can have one profile for your home, one for your working place, one when you go abroad. It’s easier to organize your configuration that way and also avoids to send probe requests on the air that can disclose information about you.

Thus on FreeBSD, I create /etc/wpa/profiles along with the various profiles and on Linux, I just link to it.

Share nullmailer

If you happen to use nullmailer as your local MTA, you can share your smtp credentials too. But there is a catch. The remotes file in the nullmail configuration must be owned by the nullmailer user/group. This user/group is different on Linux than it is on FreeBSD (nullmail on FreeBSD, mail on Linux). Fortunately when you mount a filesystem, it only cares about the UID/GID, not the actual user/group name. So if we change the UID/GID of the user/group mail to match the UID/GID of the nullmail user/group on FreeBSD, it will appear as the same user but with a different name on each OS. That’s what we’ll do on Linux, we will change the UID/GID of mail to match the one on FreeBSD.

First, let’s list all files owned by user mail:

find / -xdev -user mail > user
find / -xdev -group mail > group

Second, check that we won’t mess around too much by changing these files:

$ cat user group | sort | uniq
/etc/nullmailer/remotes
/usr/bin/dotlockfile
/usr/bin/mailq
/usr/sbin/nullmailer-queue
/var/mail
/var/spool/nullmailer
/var/spool/nullmailer/failed
/var/spool/nullmailer/tmp
/var/spool/nullmailer/trigger

Seems OK. Now let’s find out the UID/GID of the nullmail user group on FreeBSD:

$ cat /mnt/freebsd/etc/passwd | grep nullmail
nullmail:*:522:522:Nullmailer Mail System:/var/spool/nullmailer:/bin/sh
$ cat /mnt/freebsd/etc/group | grep nullmail
nullmail:*:522:

The UID/GID is 522:522 on FreeBSD. We will change user/group mail on Linux to UID/GID 522:

# Stop nullmailer so that we can change the UID/GID
service nullmailer stop

# Change UID/GID
usermod -u 522 mail
groupmod -u 522 mail

# The files are still owned by the old UID/GID.
# We change that
cat user | while read file
do
  chown mail: "$file"
done
cat group | while read file
do
  chown :mail "$file"
done

# Clean
rm user group

Now we link nullmailer configuration into Linux:

rm -rf /etc/nullmailer
ln -s /mnt/freebsd/usr/local/etc/nullmailer /etc/nullmailer

You should be able to service nullmailer restart now.

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.

Epson 3490 Scanner

This is an information that tends to be forgotten on the Internet, so I’m publishing it here. How to get an Epson Perfection 3490 Photo scanner running under Linux, FreeBSD or whatever. Paths may change on your system, so you may need to adapt the instructions below.

1. Install xsane.

2. Download the Epson firmwares. For the Epson 3490, you need esfw52.bin. You may find this file on Internet, although it tends to disappear. But in any case you can also find this file here.

3. Uncompress the firmwares. That is, sudo tar -Jxvf epson-firmwares.tar.xz -C /usr/local/share/sane.

4. Modify /usr/local/etc/sane.d/snapscan.conf, change the firmware line to point to the esfw52.bin firmware. That is following the commands above, change the firmware line to firmware /usr/local/share/sane/epson-firmwares/esfw52.bin.

If you are running FreeBSD

You should still ensure that you can use the scanner as a normal user.

5.Let’s change the owner of the scanner so that it’s available to users in the saned group. Create /etc/devd/saned.conf and add:

notify 100 {
  match "system" "USB";
  match "subsystem" "INTERFACE";
  match "type" "ATTACH";
  match "cdev" "ugen[0-9].[0-9]";
  match "vendor" "0x04b8";
  match "product" "0x0122";
  action "chown -L cups:saned /dev/$cdev && chmod -L 660 /dev/$cdev";
};

Notice the 0x4b8:0x0122, identifying the scanner USB device which you can get from the lsusb command while the scanner is plugged in.

6.Restart devd with service devd restart.

7.Add yourself to the saned group with sudo pw groupmod saned -m {{your-user}}

8.You may need to log in again so that new group changes are taken into account.

Disable XF86Back/Forward

Real ThinkPad keyboards (not this monstruous ignominy) have directly accessible keys for XF86Back and XF86Forward. That is really problematic with web browsers such as Firefox or Chromium since pressing those keys transparently go back or forward into your history, discarding anything you were typing in the process, including that 3 hours long bug report you were just about to submit. That’s rather annoying, to say the least.

Some other blog post suggest to simply disable them with xmodmap. That is in ~/.xmodmaprc (or whatever it is you use):

keycode 166 = NoSymbol
keycode 167 = NoSymbol

I personally prefer to remap them to Next/Prior keys. Having these near the navigation keys might come up handy:

keycode 166 = Next
keycode 167 = Prior

That’s on Linux though, on FreeBSD the keycodes are 233 and 234:

keycode 233 = Next
keycode 234 = Prior

Anyway use the xev command and xmodmap -pke to find the keycodes and remap them to any other interesting key symbol.

Hide logs from wheel users

If you have grown accustomed to FreeBSD administration, you’ve probably learned that users need to be member of the wheel group to be able to use the su command. Some in the land of GNU don’t agree so much with this way of doing and firmly believe that wheel is an instrument of power (which is true in a literal sens) but that’s another story.

In fact I am perfectly fine with this save for one little detail. By default most log files are owned by root:wheel. Altough while some of them have permission 600, a lot of them are 640 which means that members of the wheel group will be able to read them. We have basically two solutions to fix this:

  • Fix permissions in /etc/newsyslog.conf.
  • Use another group instead of wheel for the su command.

Fixing newsyslog.conf is quite easy, just replace the mode column with any permission you fancy (in our case 600). Don’t forget to restart newsyslog and fix existing permissions with find /var/log -type f -exec chmod 600 {} \;.

However that might not be enough. You see on most BSD wheel has gid 0, whereas on Linux it is root that has gid 0. Nobody is supposed to be a member of root, but it serves as a general purpose group for anything owned solely by root. As such you can often use chown 0:0 as a synonym of owned by root.

But root:root on Linux would not have the same meaning as root:wheel on BSD. In particular you can generally suppose that files owned by root:root with permission 640 on Linux are only readable by the root user but the same supposition doesn’t translate so well for us BSD users.

While I’m not keen of importing such kind of Linuxism into FreeBSD, one way to deal with it would be to use another group for su users. For this we would:

  • Create the su system group.
  • Move all members of wheel to this group.
  • Modify /etc/pam.d/su to use group=su instead of group=wheel.

Now I don’t personally do that, but I guess what you do it’s your business.