OpenBSD Kernels
The initial problem
This weekend I’ve installed OpenBSD 6.3 on my old Macbook (Early 2008), and immediately I remember why I love this operating system. However, not everything is completely rosy.
After boot, the inteldrm driver appears to get confused and changes the console resolution to 848x480 (480i), but restricts this to the top left of the Macbook’s 1280x800 panel. Taking a look online, I found the following suggestion here: build a new kernel with DRMDEBUG enabled and consult the output.
Cheat sheet
# export KERNEL_CONFIGURATION_NAME=GENERIC_CUSTOM_NAME.MP
# cat << EOF > /sys/arch/$(machine)/conf/${KERNEL_CONFIGURATION_NAME}
> include "arch/i386/conf/GENERIC.MP"
>
> #option OPTION1
> #option OPTION2
>
> EOF
# mkdir /sys/arch/$(machine)/compile/${KERNEL_CONFIGURATION_NAME}
# cat << EOF > /sys/arch/$(machine)/compile/${KERNEL_CONFIGURATION_NAME}/Makefile
> .include "../Makefile.inc"
> EOF
# cd /sys/arch/$(machine)/compile/${KERNEL_CONFIGURATION_NAME}
# make obj
# make config
# make && make install
# reboot
The process
The first steps are as listed here:
$ cd /usr
$ cvs -qd anoncvs@anoncvs.ca.openbsd.org:/cvs checkout -rOPENBSD_6_3 -P src
This will take a while, and afterwards you’ll have all the source for the kernel and the core userland nicely in place.
Given that it’s been a long time since I’ve compiled an OpenBSD kernel, I thought I’d follow the instructions here pretty much verbatim to start with:
# cd /sys/arch/$(machine)/compile/GENERIC.MP
# make obj
# make config
# make && make install
# reboot
Fingers crossed, breath held and my Macbook comes back up. Success; I know I can build a kernel properly.
Configuration modification
Now, as I’d noted in the introduction, I needed to enable DRMDEBUG to enable the drm debug logging, and the way to do this is via options. Each of the option entries are provided as defines to the kernel build process, so in my case:
option DRMDEBUG
would result in:
-DDRMDEBUG
being added to the compiler flags.
Where to add this?
In the compilation steps, the only obviously variable item (besides the call to machine which will be the i386 for any invocations on this installation) is GENERIC.MP. If we take a look at this directory (ignoring source control files and the generated obj link) we find a single Makefile which is the tail end of the following include hierarchy:
/sys/arch/i386/compile/GENERIC.MP/Makefile/sys/arch/i386/compile/Makefile.inc/usr/src/share/mk/bsd.obj.mk/usr/src/share/mk/bsd.own.mk$MAKECONFor/etc/mk.confif they exist
The target we are interested in, config, is defined in /sys/arch/i386/compile/Makefile.inc as:
config:
config ${.CURDIR:M*.PROF:C/.*/-p/} -b ${.OBJDIR} \
-s ${SYSDIR} ${CONFDIR}/${.CURDIR:T:S/.PROF$//}
This command makes use of config command to create a kernel build directory for a specified top-level source kernel source directory based on the configuration file. This configuration file (${CONFDIR}/${.CURDIR:T:S/.PROF$//}) is the next thing to look at.
Variable interpretation
To work out what this expands to, we need to know a few things from here, namely:
- The built in
.CURDIRvariable, which is the path from whichmakeis called - The
:Smodifier, which performs string replacement on a variable - The
:Tmodifier, which replaces the variable with its last path component
Due to where we called make from, .CURDIR is now:
/sys/arch/i386/compile/GENERIC.MP
Based on this, CONFDIR (defined at the top of /sys/arch/i386/compile/Makefile.inc as the absolute path to ${.CURDIR}/../../conf), becomes:
/sys/arch/i386/conf
so we have:
/sys/arch/i386/conf/${.CURDIR:T:S/.PROF$//}
.CURDIR:T:S/.PROF$// is getting the last path component of /sys/arch/i386/compile/GENERIC.MP and removing the first (and only, based on the regex anchoring) occurence of .PROF.
NOTE: The removal of
.PROFin this case isn’t relevant, but works in concert with${.CURDIR:M*.PROF:C/.*/-p/}in the call toconfigto automatically include profiling code for appropriately named configurations.
Expanding this out, we now have:
/sys/arch/i386/conf/GENERIC.MP
Voila.
The contents of this configuration file (comments removed) are:
include "arch/i386/conf/GENERIC"
option MULTIPROCESSOR
cpu* at mainbus?
which is where we could set our options.
Custom configuration
I say could because it’s not a great idea to modify a configuration file that’s checked into source control, and from the use of include "arch/i386/conf/GENERIC" at the top of the file it’s clear that we can easily extend the configuration, creating our own custom configuration. All we need to do is:
- create the configuration file
- add a correspondingly named directory and
Makefileunder/sys/arch/$(machine)/compile
Given that I’m adding the DRMDEBUG flag, I’m going to name the configuration GENERIC_DRMDEBUG.MP, so the commands look like this:
# cat << EOF > /sys/arch/$(machine)/conf/GENERIC_DRMDEBUG.MP
> include "arch/i386/conf/GENERIC.MP"
>
> option DRMDEBUG
> EOF
# mkdir /sys/arch/$(machine)/compile/GENERIC_DRMDEBUG.MP
# cat << EOF > /sys/arch/$(machine)/compile/GENERIC_DRMDEBUG.MP/Makefile
> .include "../Makefile.inc"
> EOF
Now, the compilation is almost exactly the same as the default:
# cd /sys/arch/$(machine)/compile/GENERIC_DRMDEBUG.MP
# make obj
# make config
# make && make install
# reboot
Once that’s done and the computer restarts, I can check the (voluminous) contents of /var/log/messages for the additional logging information, and hopefully this puts me on the path to working out my initial console resolution issue.