Build and Modify the FreeBSD Kernel
Build and Run the FreeBSD Kernel
Compared to the Linux kernel, it’s relatively easy to build and run the FreeBSD kernel.
Get the Source Code
Typically, the source code is installed along with the operating system in /usr/src
. If this directory doesn’t exist, you can obtain the source code like this:
# git clone https://git.freebsd.org/src.git /usr/src
# cd /usr/src
# git checkout release/14.2.0
Nevertheless, if you have this directory, it’s still recommended to clone the repository and move .git
to /usr/src
so we can perform version control conveniently.
# git clone https://git.freebsd.org/src.git ~/freebsd
# cd ~/freebsd
# git checkout release/14.2.0
# mv ~/freebsd/.git /usr/src
# cd /usr/src
# git status
The above operation will set the directory permissions to be writable only by the root user. If you want normal users to also have write permissions so we can develop in normal user, you can add the user to the wheel
user group and set the directory’s group to wheel
.
# pw groupmod wheel -m your_username
# chgrp -R wheel /usr/src
# chmod g+s /usr/src
# find /usr/src -type d -exec chmod g+rwx {} \;
# find /usr/src -type f -exec chmod g+rw {} \;
Build and Run the FreeBSD Kernel
Caution
Before continue, be sure to back up the virtual machine to prevent it from being unable to start if the kernel is modified.
Let’s first build and install a kernel that uses the default configuration:
$ su root
# cd /usr/src
# make buildkernel -j$(sysctl -n hw.ncpu)
# make installkernel
Where sysctl -n hw.ncpu
returns the value of CPU cores.
After installation, reboot the VM and see if the kernel works.
To generate compile_commands.json
, which provides compilation information for language servers, replace the first make
commands with the following command:
# intercept-build --append make buildkernel -j$(sysctl -n hw.ncpu)
The intercept-build
command is bundled with llvm19
package, which intercepts build process to generate compile_commands.json
. The --append
flag tells the intercept-build
to read an existing compile_commands.json
if it exists and append the results to the database, also merge duplicated command keys.
The buildkernel
target will use a default configuration named GENERIC
, which supports a wide range of hardwares. This configuration file is located in /usr/src/sys/amd64/conf/GENERIC
on x86_64 machine
[freebsd] ch1: x86_64 conf, and /usr/src/sys/arm64/conf/GENERIC
on arm64 machine
[freebsd] ch1: arm64 conf.
To use your own customized kernel configuration, copy the generic configuration file and edit it:
# cd /usr/src/sys/amd64/conf
# cp GENERIC MYKERN
# vim MYKERN
The format of the kernel configuration file is simple. Each line contains a keyword that represents a device or subsystem, an argument, and a brief description. Any text after a #
is considered a comment and ignored. For the specifications of the kernel configuration, refer to config(5).
After editing your configuration file, save it and execute the following command to build the kernel:
# make buildkernel KERNCONF=MYKERN
Modify the FreeBSD Kernel
Same as the Linux kernel, we are about to print a “Hello world!” string when the kernel starts.
The stuff similar to Linux’s arch/x86/kernel/head_64.S
[linux] ch1: entry point x86_64 is sys/amd64/amd64/locore.S
[freebsd] ch1: entry point x86_64,
the stuff similar to Linux’s start_kernel()
[linux] ch1: start_kernel() is mi_startup()
defined in sys/kern/init_main.c
[freebsd] ch1: mi_startup(),
and the stuff similar to Linux’s printk()
[linux] ch1: printk() is printf()
defined in sys/sys/systm.h
[freebsd] ch1: printf().
So all we need to do is adding a printf()
to mi_startup()
that prints “Hello world!” string. The patch is as follows:
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 1575287716ee..4523b912d6be 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -334,6 +334,7 @@ mi_startup(void)
/* Check off the one we're just done */
last = sip->subsystem;
}
+ printf("Hello world!\n")
TSEXIT(); /* Here so we don't overlap with start_init. */
BOOTTRACE("mi_startup done");
Apply this patch, rebuild and install the kernel, reboot the VM and you can see the effect in dmesg
:
$ dmesg | grep Hello
Hello world!