Sunday, June 25, 2023

Installing Debian 12 and morrownr's Realtek driver (2023-07-03 edit)

Due to deepening dissatisfaction with Canonical, I replaced my Ubuntu Studio installation with Debian 12 “bookworm” recently.


  1. My backups, including the driver source, were compressed with lzip for reasons, but I fell back on a previously-built rescue partition to get the system online.
  2. I ended up with an improper grub installation, that couldn’t find /boot/grub/i386-pc/normal.mod. I rebooted the install media in rescue mode, got a shell in the environment, verified the disk structure with fdisk -l, and then ran grub-install /dev/___ to fix it. Replace the blank with your device, but beware: using the wrong device may make the OS on it unbootable.
  3. The USB doesn’t work directly with apt-cdrom to install more packages offline. I “got the ISO back” from dd if=/dev/sdd of=./bookworm.iso bs=1M count=4096 status=progress conv=fsync (1M * 4096 = 4G total, which is big enough for the 3.7G bookworm image; you may need to adjust to suit), then made it available with mount -o loop,ro ~+/bookworm.iso /media/cdrom0 (the mount point is the target of /media/cdrom.)
  4. Once finished, I found out the DVD had plzip, and if I’d searched for it (lzip), I could have used it (plzip). I didn’t actually need the rescue partition.
  5. Once finished, I realized I hadn’t needed to dd the ISO back from the USB stick. The downloaded ISO was on my external drive all along, and I could have loop-mounted that.
  6. [Added 2023-07-02]: Letting the swap partition get formatted gave it a new UUID. Ultimately, I would need to update the recovery partition’s /etc/fstab with the new UUID, and follow up with update-initramfs -u to get the recovery partition working smoothly again.

Full, detailed rambling with too much context (as usual) below.

The Wi-Fi driver

My Wi-Fi adapter is an Archer T4U Plus (realtek / RTL 8822BU) wi-fi adapter. To get the system online prior to kernel 6.2, I need to build morrownr’s driver (generic link, not the specific version.) I knew from DistroWatch that Debian 12 has kernel 6.1, so I downloaded the DVD-1 image to be reasonably sure it had all of the development tools necessary to do this.  I did not expect Debian to provide this driver on the DVD.

I had a working, up-to-date copy of the driver code on the Ubuntu partition I would be replacing.  That code was included into my backups, and copied onto an external hard disk.  The plan was to install Debian, install build-essential, iw, and the like from the install media, unpack my backups, and build the driver.

On backups

I ran into this issue last, but it is incredibly important to know before beginning a process like this, so I’m putting it first: my backups were compressed with lzip.  It wasn’t pre-installed, there was no lzip package, and I didn’t know about plzip or do any searches that would find it.  I may have tried harder in different circumstances, but I already had another plan: I also had a rescue partition I built (Debian 11 / bullseye) for when I broke the Wi-Fi driver in Ubuntu.

To get at the backups, then, I jumped into the rescue partition (with networking), chroot’ed to the new install, and pulled lzip from the online repositories.

The missing normal.mod

The installation appeared to go smoothly, but on rebooting, I met my first problem: grub couldn’t find /boot/grub/i386-pc/normal.mod.  I thought “do not install on my primary hard drive” would have meant “don’t write it onto /dev/sda”, especially since I could pick “sdb” from the next menu.  This did indeed skip installing to sda, but also clearly didn’t finish installing to sdb and sdb1.

(When I first installed it, Ubuntu managed to irretrievably corrupt Windows booting when I wrote the bootloader to the primary disk.  Windows won’t install itself over grub, either.  I found something else that was supposed to be a Windows-flavor bootblock; it didn’t allow Windows 10 to boot, but it did allow Windows to reinstall to that drive/partition afterward.  It even kindly hid all my user/app data in C:\Windows.old without telling me.  yay.)

To fix the issue with grub on Debian 12, I rebooted into the installation media in rescue mode, had a worrying number of identical prompts to the initial installation, and finally got into a shell in the new root partition. From there, I figured out the necessary commands:

CAUTION: your device nodes will differ.  You can break things doing this. Be sure you have the right device!  I have changed the drive letter to something extremely unlikely to ruin your OS if you copy and paste this, but you have been warned anyway.

# fdisk -l /dev/sdz
[made sure it’s my 256 GB Linux SSD,
not my 1 TB SSD with Windows]
# grub-install /dev/sdz
# ls /boot/grub/i386-pc
[there should be a lot of files there now]

After rebooting, I was blessed with the Grub menu, instead of the error and the grub rescue> prompt.  The system was then able to boot into Debian 12 just fine.

Preview: the other problem with the installation was that I let it reformat the swap partition, which gave it a new UUID.  I should have changed it to “use as swap, do not format.”

The USB stick is not /media/cdrom

The next order of business was to get build-essential and friends installed. Unfortunately, trying to run apt commands would only endlessly ask for the disc to be put into /media/cdrom.

The internet suggested copying the image of the USB stick back into a file, then loop-mounting that.

(I would realize later that I had saved the ISO on an external/portable drive, and I could have loop-mounted that directly, instead of using the dd command below.  But since that’s not what I did…)

First, I had to log out and log back in to unmount the stick.  I had tried reading some of the offline documentation, which left a ‘zygote’ browser process running in the background with its working directory on the stick, preventing unmount.

Anyway, we had to learn about the mount point.

# ls -ld /media/cdrom
[…] -> cdrom0
# ls -ld /media/cdrom0
drwxr-xr-x […] /media/cdrom0

Okay.  apt wants to use /media/cdrom, which is a symlink to a normal directory.  We’ll get the image, then we’ll mount it over /media/cdrom0, and finally we’ll hope it works even though we never saw a Packages.gz or anything on the USB file system.

The commands for getting the image back off the USB (attached at /dev/sdd) and using it are:

# dd if=/dev/sdd of=bookworm.iso bs=1M count=4096 \
    status=progress conv=fsync
# mount -o loop,ro ~+/bookworm.iso /media/cdrom0
# apt install build-essential make

Note for the future: I knew the image was 3.7G from putting it on the USB stick in the first place, so I am providing the command to dump the first 4.0G of it (4K * 1M) back to the file.  Your image may be larger.  (I actually ran it without a count at all, and it started dumping my entire 30G stick, so I interrupted it with Ctrl+C when I noticed around the 10G mark.)

Hey, good news: it worked.  I got a bunch of packages installed, without setting up a network connection.

Unpacking the backups

I finally learned I couldn’t unpack my backups.  They were compressed with lzip, but the DVD only contained gzip, bzip2, xz, and lzma (from xz-utils).

I would find out later that the DVD contains plzip, a parallel version of lzip that is fully compatible with it, but I guess I didn’t search for lzip so much as expected to find “the package named lzip.”

Fortunately, in the past, I had run into problems rebuilding the driver, compounded by its recommendations to reboot and my own misunderstanding of how to do an upgrade (tl;dr on that: never run and reboot if you have dkms.  During install, it removes itself from dkms, which is effectively the same thing; but it does this after checking installation requirements, which is helpful when a new one has been added.)

So… I had used resize2fs to make some space, modified my partition table, (added swap space while I was in there, because having no swap hurts), and made room for a Debian 11 install (notes on that). It also needed the driver, but the basic theory was, I should have a working driver in one OS or the other, all the time.  I’d upgrade the driver on the Ubuntu partition periodically, and if it worked, go upgrade the driver in Debian.  Ubuntu could fix Debian, or vice versa, depending on what happened.

Aside: swap and GUID

During the Debian 12 installation, I had done a custom installation, formatting my Ubuntu partition as ext4 for /, and letting it format the swap partition for swap, which it wanted to do already.

When I booted Debian 11, I had to wait a minute and a half for the swap mount to time out.  It had been listed by UUID in /etc/fstab, so systemd waited for the UUID to appear, but it had been overwritten.

I used lsblk -f to get the updated UUID, copied it, and updated the fstab file.  (Pro tip from times long past: if you’ve installed Linux text-only, also install gpm to copy and middle-click-paste with the mouse on the console.)

[Updated 2023-07-03: I would later discover I should have run update-initramfs -u -k all afterward, to put the new swap UUID into initramfs.  Otherwise, the initrd waits around a bit for the original UUID to appear.  This is what it’s doing when it repeatedly prints something like Begin: Running /scripts/local-bottom ... done. It’s trying to wait for local filesystems before continuing the init process.]

Using my recovery partition

Back to the present.  With Debian 11 booted, I had to do a few things to get everything working.  Properly entering Debian 12 as a chroot required:

# mount /dev/sdb1 /mnt
# for i in dev dev/pts sys proc
    do mount --bind "/$i" "/mnt/$i"
# cp /etc/resolv.conf /mnt/etc/resolv.conf
# cp /etc/apt/sources.list \
# chroot /mnt /bin/bash
# nano /etc/apt/sources.list.d/network.list
[change ‘bullseye’ to ‘bookworm’]
[change ‘main’ to ‘main non-free-firmware’]
# apt update

If /dev/pts isn’t available in the chroot, then sudo will fail with “Could not allocate pty.”  The shaggy dog here is that sudo wasn’t actually important.

If /etc/resolv.conf isn’t available, DNS doesn’t work, and apt can’t really get anything from the network.

If the copied sources.list file has the wrong distribution… Bad Things May Happen.  Fortunately, I hadn’t copied the resolv.conf the first time, so it just failed to update, and I spotted the wrong distro in the output rather quickly.

The final change to add non-free-firmware quiets a message about it from apt in a way that I didn’t have to look up on the internet.  Quite a bit of time was spent already.

Anyway, that let me install lzip and rfkill from the tubes.  I probably could have gotten rfkill locally, but since I had the network temporarily working, this was the path of least resistance.

I unpacked the driver from my backups and tried to run, but it needs headers for the kernel currently running, which of course is not from the right distribution, so the headers aren’t there.  I had to reboot back into Debian 12 to run the install.

Don’t forget to clean up safely when you’re leaving the chroot:

# exit
# umount /mnt/{dev/pts,dev,sys,proc} /mnt
# reboot

Driver installation

With all that, the driver installed smoothly in Debian 12.

[Updated 2023-07-03: The rest of this section was basically rewritten to be useful, instead of a bland “It worked!”]

It was a matter of changing to the directory with the driver code, 88x2bu-20210702, and running sudo ./ from the (offline as of yet) Debian 12 environment.  After rebooting, I was able to configure the network in System Settings, and it all worked.

Arcana for anyone who needs it: I installed KDE, and the underlying network configuration tool is NetworkManager.  systemd-networkd is not installed.

Per previous experience, I also decided to store the Wi-Fi password “for everyone (unencrypted)”.  With the wallet configured to lock when locking the screen, I needed to type my password twice when unlocking the screen after suspend: once to log in, once to unlock the Wi-Fi.  That’s too much typing.

A note about driver uninstallation

When upgrading to Ubuntu 23.04, I found out that the script may not remove a file that prevents loading the in-tree driver.  It seems that in the current driver, the relevant line is part of /etc/modprobe.d/88x2bu.conf, but I could swear it was somewhere else in older versions.

Regardless, if you upgrade to kernel 6.2+, remove morrownr’s 88x2bu driver, and you still don’t have Wi-Fi, try grep -r 'blacklist.*rtw' /etc/modprobe.d to see if a file shows up.  I can’t give any general advice on whether to delete the file or comment out the line, but getting rtw88_8822bu off the list of blocked modules should make it work again.  (At least, for my Archer T4U Plus, which is an 8822BU chip.)

The end?

I want to set up mainline kernels in Debian 12, preferably in a way that I don’t have to track my own from, so that I can have 6.2+ and not worry about this driver anymore.  It’s such a pain. But, whatever happens there will be a different post.

No comments: