Categories
Linux Pictures

My 2002 Linux desktop

Just thought I would share this just for fun – screenshots of my Linux desktop from around the year 2002. If I remember correctly, this was the Mandrake Linux distribution, and I used the Blackbox X11 window manager.

Linux desktop screenshot showing the RiPcd-app.

This screenshot shows a TUI frontend-app I made for ripping audio CDs. I find it amusing that TUIs (Text User Interfaces) are apparently gaining popularity. New developer toys like those agent orchestration apps that talk to the LLMs in the sky. And a whole slew of other things, for instance in the frontend world. Very fancy TUIs actually. I’ve been using the command line and TUIs for over 25 years and still love the simplicity and purity.

This one is obviously more of a show-off screenshot with a different theme. Some great apps here: MPlayer, XMMS (audio player), Emacs (of course, still great), and lets not forget top(1) running in the background.

I used 6 virtual desktops, and this screenshot shows my «AllSeeingEye» desktop. Apparently just different logs/apps being tailed/watched in borderless and transparent terminal windows. Funny how the web server traffic is obviously some script kiddie trying to hack me.

My Linux desktop today is much more boring.

Categories
Hardware Linux

Kernel module amdgpu failed to load after BIOS upgrade

I recently did a BIOS upgrade on my main desktop machine (ASUS motherboard). It runs Ubuntu 24.04, has a dedicated AMD GPU and I use the proprietary AMD driver packages for ROCm compute support. What came as a surprise was the slow Gnome Shell experience that greeted me after the BIOS upgrade. I could tell something was off, and it didn’t take me long to notice that the KMS graphics subsystem was using some generic driver with poor acceleration. How can a BIOS upgrade cause this to happen ? Was my GPU suddenly bricked in some way ?

No, fortunately ! I just forgot about the fact that ASUS BIOS upgrades tend to mess around with the UEFI Secure boot key database, which is in essence a firmware trust store of public keys that is used to verify signatures of operating system binary artifacts (like boot loaders, kernel images and modules). After probing around for while, I discovered that attempting to load the amdgpu kernel module failed with an error related to cryptographic signature. (I cannot remember the exact message at this time.) Since a lot of other kernel modules where already loaded successfully, I figured this has to be caused by the proprietary driver being compiled (and signed) externally by DKMS.

The obvious next step was to attempt a complete re-installation of the AMD driver packages and DKMS, which I hoped would fix-up the module signature issues. But it didn’t help at all, even though a full recompilation of the AMD kernel modules was completed without any obvious error messages popping up. The resulting module was still not trusted by the kernel. (Even wiping all packages and re-installing didn’t do it.)

I wasn’t planning on spending my morning messing with the UEFI firmware keys, and so I pondered just going back to the open source AMD driver, which already comes bundled with each kernel package (and no ROCm compute support..). But then I discovered references to DKMS and a cryptographic key pair, lurking under the system directory /var/lib/shim-signed/mok:

# ls /var/lib/shim-signed/mok
MOK.priv  MOK.der

That’s a certificate and private key, and «MOK» refers to the Secure Boot concept Machine Owner Key. You are normally allowed to adjust what Secure Boot trusts, if you have access to the physical machine on which it runs, which means you can modify the key database (trust store). After some research (and remembering I already did something very similar years ago), I figured I needed to try enrolling this public key into the UEFI key database:

mokutil --import /var/lib/shim-signed/mok/MOK.der

The mokutil command is used to interface with UEFI machine owner keys, and you can also check which MOKs are already enrolled using --list-enrolled.

The utility will ask for a password and you can simply invent something simple here. It is used only once as a challenge when entering the UEFI Mok manager utility after rebooting. From that firmware user interface you can then choose to enroll the new key and continue booting. After completing this step, the proprietary amdgpu kernel module loaded successfully once again and the problem was fixed.

I was disappointed by the Linux user experience here. A non-working graphics driver is not an obvious consequence of a BIOS upgrade, and had it not been for years of experience with Linux desktops, I would probably have given up much sooner. I don’t know if it’s just a bug that the key was not automatically re-enrolled by DKMS on re-installation, but that is certainly not a user friendly experience.

Categories
Code Linux

Handling OS events in Emacs Lisp

Emacs can access files on any remote server running an ssh or SFTP service, assuming that an ssh client is installed on the host where Emacs runs. I use this extensively, since I run my own personal home servers available over the internet. On those servers, I have files and resources that I access all time, from anywhere.

/ssh:server.example.com:~/myfile.txt

Opening this path in Emacs will automatically open an ssh-connection to server.example.com and transparently allow editing of myfile.txt. Emacs uses the TRAMP package (Transparent Remote Access, Multiple Protocols) to provide this functionality.

TRAMP is designed to re-use existing ssh-connections for accessing multiple resources (on the same server). When using a laptop, where network conditions change and the system is frequently suspended, such persistent connections tend to hang for a while after the operating system has resumed operation, which can block Emacs. This is annoying, especially when I’d like to access a remote file immediately, and ssh hasn’t yet detected that its TCP connection has become unusable.

TRAMP provides a convenient function to clean up all existing connections, aptly named tramp-cleanup-all-connections, which I want to automatically call when the operating system wakes up from a suspended state or if the network changes.

Detecting operating system events on Linux

If running in a typical Linux environment, you can make Emacs listen for DBUS system bus events. Check out my packages nm.el and upower.el for code which reacts to networking and power management events.

For example, to automatically clean up remote connections whenever network connects or re-connects, the following code would work (requires that NetworkManager is used by Linux distro):

(load-file "/path/to/nm.el")
(add-hook 'nm-connected-hook 'tramp-cleanup-all-connections)
(nm-enable)

Or to do the same whenever the machine resumes from suspend:

(load-file "/path/to/upower.el")
(add-hook 'upower-resume-hook 'tramp-cleanup-all-connections)
(upower-enable)

Detecting resume by using system clock

I also use Emacs on Windows sometimes, in a WSL environment where DBUS is not available. But we can still detect if the machine has been resumed in a generic manner, by observing the system clock:

(defvar clock-jump-detector-hook nil
  "Functions to run when a system clock jump is detected.")
(defvar clock-jump-detector-threshold (* 5 60)
  "Minimum time skip (in seconds) to consider
it a system clock jump. When it is detected that
the system clock jumps with more than this number of seconds, then hooks in `clock-jump-detector-hook'
are run.")

(setq clock-jump-detector-time (current-time))
(defun clock-jump-detector ()
  (let ((time-passed (float-time (time-since clock-jump-detector-time))))
    (setq clock-jump-detector-time (current-time))
    (when (> time-passed clock-jump-detector-threshold)
      (message "Clock jump of %f seconds detected, running hooks .." time-passed)
      (run-hooks 'clock-jump-detector-hook))))
(run-at-time t 15 'clock-jump-detector)

The code records the current time every 15 seconds, and if a time jump beyond a threshold is detected (a «clock jump»), then all functions in hook-variable clock-jump-detector-hook are invoked.

By having Emacs listen for operating system events over DBUS and invoking functions in hook-variables, you can make anything happen in a loosely coupled fashion.