If you build the drivers for your storage media and filesystem into the kernel (not as a module), and the filesystem is visible to the kernel without any userland setup required beforehand (e.g. the filesystem is not in an LVM volume, not on an MD-RAID array, not encrypted), it is fully capable of mounting the real root filesystem and booting init directly from it.
The only point of consideration is that it doesn't understand filesystem UUIDs or labels (this is part of libuuid which is used by userland tools like mount and blkid), so you have to specify partition UUIDs or labels instead (if you want to use UUIDs or labels). For GPT disks, this is natively available (e.g. root=PARTUUID=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 or root=PARTLABEL=Root). For MS-DOS disks, this is emulated for UUIDs only by using the disk ID and partition number (e.g. root=PARTUUID=11223344-02).
You can also specify the device name directly (e.g. root=/dev/sda2) or the major:minor directly (e.g. root=08:02), but this is prone to enumeration order upset. If you can guarantee that this is the only disk it will ever see, or that it will always see that disk first, this is often the most simple approach, but these days I use GPT partition UUIDs.
In practice, we have generic kernels which require a lot of stuff in modules for real user systems running on distributions. Instead, though, we could have a loader which doesn't require this big relatively-opaque blob and instead loads the modules necessary at boot time (and does any necessary selection of critical boot devices). i.e. like FreeBSD does.
There's advantages each way. You can do fancier things with an initramfs than you ever could do in the loader. On the other hand, you can change what's happening during boot (e.g. loading different drivers) without a lot of ancillary tooling to recover a system.
I did mention that the root filesystem had to be both not encrypted and not require any userland setup.
> I'm not so sure it would be easy to convince the kernel maintainers to add a user prompt for pin code to the kernel
That wouldn't help, as the password is not usually used directly as a volume encryption key. In LUKS2 for example, a memory-hard KDF (Argon2) can be used to transform the password or PIN into a key-slot encryption key which is then used to decrypt that slot to obtain the volume encryption key (which is usually completely random and not at all related to or derived from any kind of password) in order to set up the dm-crypt mapping.
> just to avoid having an initrd.
No distribution has used an initrd in the last several years; initramfs reigns supreme now. They are not the same thing; an initrd is an image of a real filesystem (e.g. squashfs or ext2) that is read-only mounted onto / by the kernel during its startup, while an initramfs is (an optionally-compressed) cpio archive that is extracted to a read-write tmpfs (or ramfs if tmpfs is not available) mounted on / by the kernel during its startup and then the memory occupied by that cpio archive is freed because it is no longer necessary. An initramfs can also be built into the kernel image; an initrd cannot, and must be provided by a bootloader.
And also for e.g. cases where you've got some custom stack of block devices that you need to set up before the root FS and other devices can be mounted. It's not just about loading kernel modules.
I don’t see the point of doing so however.
...But to load it at boot time it absolutely must be done through an initramfs. Is that right?
Yes, because it cannot be part of the kernel image, or it would be illegal (a violation of the GPL license) to distribute that kernel. Therefore, it must be a module, and that module has to live somewhere and be loaded by something. If root is on ZFS, this must therefore live in an initramfs and be loaded by it so that the initramfs can mount the real root filesystem on the kernel's behalf.
That would probably make updates a lot less slower than having zfs shipped in an initramfs though.
The "problem" with the GPL here arises not when you, the end user, take a piece of GPL-licensed software and combine it with other software, as is your GPL-protected right, but when you try to redistribute the result. You see, every end user has the same right to obtain all of the source code for GPL-licensed software that they receive, and for all of that source code to be licensed in a way compatible with the GPL. Once the kernel and non-GPL-licensed modules have been combined into a single piece of software, you are free to use it locally as you wish, but you can't share it, because you would be unable to meet the obligations you owe to the person you give it to.
Bear in mind that the modules are meant to be combined with the kernel, and the method by which that happens isn't specified by the module authors. So, a tool which makes all of this easier for you to do isn't circumventing any restriction meant to stop you from doing this, because no such restriction exists.
Is this the case though? I thought there was an argument that in order to create that tool - you would need enough knowledge that it would require you to basically create a derivative work.
No, not AFAICS it is incorrect.
On UEFI the system boots from a FAT32 partition. Put the kernel directly on that FAT32 partition, and any necessary modules such as ZFS, and the kernel can load the ZFS module from FAT32 and then mount root directly without any need for an initramfs.
This is how systemd-boot works.
I am not advocating systemd-boot -- I found it a pain to work with -- but the point is that it's perfectly possible and doable. The initramfs is a bodge and it's time we did away with it. It should only be needed for installation and rescue media.
- linux tells the bootloader what folder the modules live
- bootloader just puts them all in memory
- linux just picks what it needs.
That's all the initramfs is anyways. The point is there's no reason to prebuild an image from inside Linux, you can just have grub assemble a simple fs on the fly.
But initramfs isn't so bad, and it allows things like ZFS root to have a modicum of smoothness and integration.
Though I only do it for my ARM based devices currently.
And if you're not throwing away build artifacts after each build, then getting stable updates is just a `git pull` and incremental make, which is usually very quick.
That is a lot faster than recovering from a backup.
When I was young and spry, I used to compile them with every new minor revision. Now, it is just maybe a couple times per year. I think that cooling it on how often I do it has helped it not become annoying.
Me too. I go back to within about 3 years of that.
But I expect my distro to handle this for me now.
If the distro compiled and updated the kernel for my hardware then there's be no need for an initramfs.
While initramfs was a simplistic kludge, the UKI idea does not fix it, it wraps a kludge inside a fugly ball of lack of understanding.
There have been several attempts to add features to the grub zfs code over the years, but there are several maintainers of grub who happen to be employees of Oracle, and typically the attempts go nowhere.
I personally can't recommend using grub anymore. The whole "just make 2 pools" solution is unacceptable, and until Oracle stops gatekeeping, their code becomes more obsolete in my eyes.
In many cases, you don't need initramfs. I rarely use one in embedded systems.
[1] https://optee.readthedocs.io/en/latest/general/about.html
You're reliant on the capabilities of the chip that you're working with, and a flaw in that can unravel everything that you've done. In one case, I had to disable the on-chip boot agent once things were provisioned because of flaws in their implementation.
In short, a signed applet could be sent to the chip to do things like read/write NAND or NOR, set fuse bits, etc. When an unsigned applet was sent, it was rejected as expected but they neglected to clear the memory contents in this case. So you could send a malicious applet, let it be rejected, and then just tell it to execute. It's kind of a fascinating writeup if you want to know more [1].
1. https://labs.withsecure.com/advisories/microchip-atsama5-soc...
the other direction is to put everything in systemd. :)
And if this bit is closed source, and something doesn't work, you don't have a recourse.
Having lucked into using Lilo and no initramfs for several years now, I'm very happy with robustness and straightforwardness of the solution.
In contrast, on the rare occasion I've dealt with somebody elses' GRUB and initramfs setups, they turn out brittle and complex.
FreeBSD's loader does this, and its so much easier to deal with. Eg, it understands ZFS, and can pre-load storage driver modules and zfs.ko for the kernel, so that the kernel has everything it needs to boot up. It also understands module dependencies, and will preload all modules that are needed for a module you specify (similar to modprobe).