Page MenuHomeFreeBSD

packages: Always install kernel as /boot/kernel.NAME
Needs ReviewPublic

Authored by ivy on Dec 18 2025, 12:52 PM.
Tags
None
Referenced Files
Unknown Object (File)
Wed, Mar 18, 11:09 AM
Unknown Object (File)
Feb 17 2026, 10:10 PM
Unknown Object (File)
Feb 17 2026, 10:10 PM
Unknown Object (File)
Feb 8 2026, 11:11 PM
Unknown Object (File)
Feb 8 2026, 2:01 PM
Unknown Object (File)
Feb 5 2026, 2:17 AM
Unknown Object (File)
Jan 29 2026, 4:34 AM
Unknown Object (File)
Jan 28 2026, 7:41 PM

Details

Reviewers
emaste
imp
kevans
jrtc27
Group Reviewers
pkgbase
manpages
releng
Summary

Currently, when multiple kernels are specified in $KERNCONF when
building base packages, the first kernel would be installed in
/boot/kernel, and the remaining kernels would be installed in
/boot/kernel.NAME.

For example, if KERNCONF='FOO BAR BAZ', three packages would be
created:

  • FreeBSD-kernel-foo, installing in /boot/kernel
  • FreeBSD-kernel-bar, installing in /boot/kernel.BAR
  • FreeBSD-kernel-baz, installing in /boot/kernel.BAZ

This behaviour is not desirable, because it leads to unpredictable
results when building individual kernels; the "default" kernel always
needs to be built as well to ensure the other kernel(s) end up in the
correct place. Aside from that, it's also confusing to have the same
package install files in a different place depending on how it was
built.

Fix this by having the packaged kernels always install in kernel.NAME.

To avoid breaking existing users of distributekernel (which is what we
currently use to stage the kernel), reimplement stage-packages-kernel
to run make install itself rather than changing the existing behaviour
of distributekernel; this means release builds and other downstream
users are not affected by this change.

For the FreeBSD-dtb package, which uses files installed by the kernel
build, take the DTBs from the first kernel listed in KERNCONF. This
preserves the previous behaviour, and since DTBs are always installed
in /boot/dtb, the kernel name issue doesn't affect them.

Remove the "flavor" bits that were previously used to build the -dbg
package containing the debugging symbols. This was confusingly named
because the kernel and its debug symbols aren't flavours of the same
thing, they're different things. This also means we can provide a
separate kernel-dbg-all.ucl template for the debug packages, making
the comment and description more clear.

Remove the _kernconf option from mtree-to-plist.awk, since it's no
longer used.

To prevent breaking upgrades when the kernel moves from /boot/kernel
to /boot/kernel.GENERIC, add a new kernel-support package containing
a trigger that manages a symlink at /boot/kernel. If /boot/kernel
doesn't exist, or is an empty directory, or is a symlink to an empty
directory, remove it and create it as a symlink to an installed
kernel. Try to prefer a GENERIC kernel for this, otherwise pick
any installed kernel. If the user modifies the symlink to point to
a different kernel, the trigger will leave it unmodified.

Usually this will be done by bsdinstall and the symlink won't be
changed after that (unless the user removes the GENERIC kernel),
so this is mainly to handle upgrades.

Update freebsd-base.7 to document the new behaviour.

Suggested relnotes text:

Kernels installed from packages will now always install in
/boot/kernel.NAME, rather than the first built kernel (usually
GENERIC) being installed as /boot/kernel.  The kernel package
will maintain a symlink to an installed kernel at /boot/kernel.
For more details, refer to freebsd-base(7).

MFC after: never
Relnotes: yes

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 69674
Build 66557: arc lint + arc unit

Event Timeline

ivy requested review of this revision.Dec 18 2025, 12:52 PM

this is basically ready, but there are some unresolved issues:

  • pkg seems to have issues running the trigger when using pkg -r, i'll follow up on this separately.
  • the trigger doesn't work on ppc64le because /boot is a FAT filesystem. this just means the user needs to edit /boot/kboot/kboot.conf by hand.
  • do we want bsdinstall to add kernel="kernel.GENERIC" to /boot/loader.conf, or should we teach the loader to resolve the symlink (to set kern.bootfile correctly), or something else?

To avoid breaking existing users of distributekernel (which is what we
currently use to stage the kernel), reimplement stage-packages-kernel
to run make install itself rather than changing the existing behaviour
of distributekernel; this means release builds and other downstream
users are not affected by this change.

Does the confusingly-named NO_INSTALLKERNEL not do what you want?

To avoid breaking existing users of distributekernel (which is what we
currently use to stage the kernel), reimplement stage-packages-kernel
to run make install itself rather than changing the existing behaviour
of distributekernel; this means release builds and other downstream
users are not affected by this change.

Does the confusingly-named NO_INSTALLKERNEL not do what you want?

possibly, but this is an awful hack that works by adding incorrect entries to ${BUILDKERNELS}, which means the logic for create-dtb-package would probably need to be updated to work around that... the amount of new code for this specific change is very small, so i think i prefer doing it this way.

In D54282#1240665, @ivy wrote:

To avoid breaking existing users of distributekernel (which is what we
currently use to stage the kernel), reimplement stage-packages-kernel
to run make install itself rather than changing the existing behaviour
of distributekernel; this means release builds and other downstream
users are not affected by this change.

Does the confusingly-named NO_INSTALLKERNEL not do what you want?

possibly, but this is an awful hack that works by adding incorrect entries to ${BUILDKERNELS}, which means the logic for create-dtb-package would probably need to be updated to work around that... the amount of new code for this specific change is very small, so i think i prefer doing it this way.

I can make NO_INSTALLKERNEL less gross if that would help?

I can make NO_INSTALLKERNEL less gross if that would help?

if you felt like doing that i'd be happy to remove the custom make install bits from this change. i think my only concerns are that 1) it doesn't lie about BUILDKERNELS, and 2) the first kernel is not treated any differently than the others (which might already be the case, i haven't checked).

  • rebase after D54291
  • fix the symlink sometimes having the wrong path
  • make the symlink relative instead of absolute
  • fix a wrong dependency for the kernel-dbg package
  • since the install media uses kernels_autodetect=NO, explicitly set the kernel to GENERIC. the user can override this if they want the media to use a different kernel.

this fixes the installer, but the newly installed system doesn't boot
due to https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=292232.

ivy added a reviewer: releng.

add releng since this touches release/ now.

If I understand it correctly, this change does not affect nextboot either?

Makefile.inc1
2317

Is it safe to replace shell if with make .if there?

IIRC, make directives are evaluated when Makefile is being parsed, not during the actual rule execution. It wouldn't make difference if create-dtb-package is always called like this make create-dtb-package, but it might cause unexpected results when called for example like make foo create-dtb-package where foo creates ${KSTAGEDIR}/${DISTDIR}/dtb.plist.

UPDATING
36

If I understand it correctly, this change does not affect nextboot either?

i am not particularly familiar with nextboot(8) (and did not test this), but from what i understand, it should not have any impact on that.

Makefile.inc1
2317

create-dtb-package is always invoked by Makefile.inc1 as a subtarget of something else (usually make update-packages), so this shouldn't be an issue. in other words, we don't support users doing make something create-dtb-package; these are internal targets.

i don't especially love this and i'm working on a better way to handle this, but in the mean time, i think this is okay.

UPDATING
36

i think we just want to remove the word 'update' here.

I've been using this for decades:

$ grep KODIR /etc/src.conf
KODIR				 = /boot/${KERN_IDENT}

This installs e.g. GENERIC as /boot/GENERIC rather than /boot/kernel.GENERIC. One advantage of doing so is that the space allocated to the kernel name in the loader menu is very limited. Another is that from the loader prompt, you can load and boot the correct kernel by simply typing boot GENERIC instead of boot kernel.GENERIC.

In D54282#1282748, @des wrote:

I've been using this for decades:

$ grep KODIR /etc/src.conf
KODIR				 = /boot/${KERN_IDENT}

This installs e.g. GENERIC as /boot/GENERIC rather than /boot/kernel.GENERIC.

i'm not opposed to that, but it would be a more significant change compared to what pkgbase currently does. do you think we should do it that way?

In D54282#1282749, @ivy wrote:
In D54282#1282748, @des wrote:

I've been using this for decades:

$ grep KODIR /etc/src.conf
KODIR				 = /boot/${KERN_IDENT}

This installs e.g. GENERIC as /boot/GENERIC rather than /boot/kernel.GENERIC.

i'm not opposed to that, but it would be a more significant change compared to what pkgbase currently does. do you think we should do it that way?

I would much prefer if we did it that way. I've been trying to think of reasons not to and the only one I can come up with is that it is theoretically possible to create a kernel config named e.g. efi or lua or modules or zfs which would then collide with /boot/efi, /boot/lua, /boot/modules, or /boot/zfs. Kernel configuration identifiers are traditionally in uppercase, but we don't enforce that. So perhaps if we go that route we should add logic to always convert the identifier to uppercase? I think perhaps @kevans should weigh in here.

one issue here is that the logic in kernel-link.ucl relies on kernels being named kernel.SOMETHING. if the user upgrades from main today to this change and the kernel moves from /boot/kernel to /boot/GENERIC, how should we handle that? treat every X where /boot/X/kernel exists as a valid kernel, perhaps?

Added some comment about the kernel-link.ucl

share/pkg/kernel-link.ucl
47

Should be true, there is nothing in your code from what I ready which execute anything so it should be safe to be sandboxed, and if sandboxed the trigger will not be defered but execute directly (since pkg 2.6)

97

maybe also check for GENERIC-NODEBUG ?

In D54282#1282753, @des wrote:
In D54282#1282749, @ivy wrote:
In D54282#1282748, @des wrote:

I've been using this for decades:

$ grep KODIR /etc/src.conf
KODIR				 = /boot/${KERN_IDENT}

This installs e.g. GENERIC as /boot/GENERIC rather than /boot/kernel.GENERIC.

i'm not opposed to that, but it would be a more significant change compared to what pkgbase currently does. do you think we should do it that way?

I would much prefer if we did it that way. I've been trying to think of reasons not to and the only one I can come up with is that it is theoretically possible to create a kernel config named e.g. efi or lua or modules or zfs which would then collide with /boot/efi, /boot/lua, /boot/modules, or /boot/zfs. Kernel configuration identifiers are traditionally in uppercase, but we don't enforce that. So perhaps if we go that route we should add logic to always convert the identifier to uppercase? I think perhaps @kevans should weigh in here.

"always convert to upper case" HARD NO. Lots of people use lowercase and it would be needless confusion for 0 benefit.

Since we're noodlng on ideas, maybe we change how we do things a little and have /boot/kernels (note plural) and have the pattern be /boot/kernels/${CONFIGNAME} so that it's completely separate. That would keep it in the right namespace and might help some of the issues. We could create a compat /boot/kernel -> symlink to /boot/kernels/GENERIC as well (but that just changes the target of what's above.

We can also rework the menus to give more space to names too... They are the way they are because they look mostly like the 4th menus they replaced, but there's no hard requirement for that.

i'm inclined to say we should leave the /boot/GENERIC thing for later. this change matches what both pkgbase and installkernel currently does, more or less. if we want to change that, i'm not opposed, but i don't want this review to get bikeshedded on that.

In D54282#1282769, @ivy wrote:

i'm inclined to say we should leave the /boot/GENERIC thing for later. this change matches what both pkgbase and installkernel currently does, more or less. if we want to change that, i'm not opposed, but i don't want this review to get bikeshedded on that.

Agreed. I didn't notice this was one of the 'I want to land these' emails in hackers@ til now.

ngie added inline comments.
Makefile.inc1
2149–2150
share/pkg/kernel-link.ucl
4
50–51

Does this work with ZFS? I remember there being a weird scenario where symlinks didn't work with ZFS in older versions of FreeBSD.

share/pkg/kernel-link.ucl
50–51

it does work on my amd64 development VM, which uses ZFS root. it doesn't work on ppc64le, because we don't have a bootloader there and /boot is a FAT filesystem.

i haven't tested other platforms, but i believe it should work on any platform where /boot is either UFS or ZFS.