I can't help but suspect the first item on the list was the whole reason for this project. :)
Hardware initialization:
==> Setting the keyboard repeat rate.
Disable interrupts and mask all interrupt levels.
Setting Interrupt descriptor (IDT) and segment descriptor (GDT). As a result,
all selectors (CS, DS, ES, FS, GS) refer to the 4 Gbyte flat linear address space.
Change the address bus to 32 bits (Enable A20 line).
Transition to protected mode.
If the target is ELF64, set the 4G boot pagetable and transition to long mode.
Note that just because you can, it doesn't mean you should. How much maintenance this needs depends on your distro, your machine and firmware's own quirks (if any), and your own usage/update/maintenance patterns/quirks.
Also: directly booting the kernel as a UEFI module makes it much more difficult to set kernel parameters temporarily on boot.
If you need to boot into runlevel 3 (or use init=/bin/bash) for maintenance, it's going to be much more complicated to make this happen than it is when booting through Grub.
You can just boot into the UEFI Interaractive Shell (think of it as a BIOS terminal/cmd.exe), which most BIOSes have, and launch your kernel with those parameters, as regular arguments to a regular command, right?
Not really, the EFISTUB has the kernel arguments baked into it, and to my knowledge, you can't just execute it with arguments and expect it to use them.
According to the Arch Wiki [0] that can be done by using an `.efi` file but it is not necessarily the case. The UEFI can directly load the linux kernel and add parameters.
However, it's not particularly practical.
Of course, as with all things UEFI, YMMV. This worked for me on an HP EliteDesk 800 G2 before I got around to setting up the keys for secure boot.
Is this a joke? Is this something you do yourself with any frequency? Do you realize how utterly painful just typing the correct UUID is? I've had to rescue non-booting systems like this many dozens of times and it makes me absolutely hate my life that on top of having to fix the actual boot problem, I also have to scramble to find a paper and pencil or grab a phone or whatever (or flip back and forth between two screens approximately 51,295,183 times) just to copy 32 random hexadecimal digits from another screen just to test other parameters from a screen I really shouldn't have to bring up in the first place. Especially given the inevitable transcription mistakes that will force you through another reboot cycle. It's such an utter frustration and waste of time to have to go through this nonsense to test a fix to a boot issue. And that's based on the ridiculous assumption that the process is somehow intuitive for people—what fraction of Linux users do you think even know there's both a PARTUUID and a volume UUID? What fraction do you think even know what to type when they face a GRUB screen, and also know what kernel parameters they need to pass? What fraction of those do you think know (and remember!) how to do all this in the UEFI shell?
I never said it was hard, just not as practical as modifying a command line, for example in Grub, that already has the UUID setup.
Also, not sure how many people have the UUID lying around ready to be copied. If you have encryption setup, there's even more parameters to add. Again, it's not hard, but a bootloader with an editable command line is just much simpler.
Just have two UEFI boot entries: one booting the EFI stuff directly, and one booting GRUB, which then boots the same kernel. Then you can use GRUB to change kernel command line.
What tangible benefit do you get from booting directly if you're going to have to maintain the GRUB entries anyway? Some ε > 0 improvement in boot time?
How common are those features? None of my systems have the UEFI shell in firmware or provide that level of control over boot records from the firmware setup interface.
Don't compile as root, there's no need for that. You should only elevate your privileges when needed. The only thing you need root for are modules_install and your install_kernel script.
People always say this, but if a project is malicious, it can take your SSH keys and get persistence even without root. It can alias sudo in your bashrc to get root if it wants too.
Yet if you don't use sudo, some make/compiles fail with random permissions errors.
I mean I see the reasoning, but in 2020 I think the Linux desktop security model is sufficiently broken that it doesn't matter.
Thanks, by "it" I now understand you mean that CONFIG_EFI_STUB=y is on by default. This is the feature required to boot the kernel directly as an UEFI-target, now I need to look into how I make it an UEFI-target, I believe I need to use bootmgr as GP has, but I need to use my kernel image as the EFI image?
EDIT: I managed to create the target, with efibootmgr and boot it partly but it panics. I assume that's due to FDE so I'll have to look into how to configure it to support that (if it's possible without a bootloader).
it's possible, but you must include the path to the initramfs as a kernel parameter (using DOS-style paths, not sure if unix-style works too).
A linux-aware bootloader will usually load the initramfs itself and pass linux the memory address where it's loaded, in UEFI the kernel gets "executed" like a normal executable, so it has a commandline but not a pre-loaded initramfs.
My efibootmgr entry looks like this (root is btrfs on LUKS):
For those interested, a colleague of mine wrote a tutorial series on implementing an OS using Rust that targets RISC-V: https://osblog.stephenmarz.com/
This is lower level than code you normally expect. The change seems to happen around switching addressing modes, so it could be something like pages descriptors not being set up correctly. In short - rust safe memory guarantees don't hold if you mess with memory mapping at runtime.
Not necessarily, there are a bunch of unsafe methods you kinda have to use going this low level and if you're in unsafe mode, then you can overwrite memory or do things to corrupt it.
Honestly, many of rust’s safety promises don’t help the type of low level code I write, so I’m skeptical of the “embedded rust” push. But embedded is a huge field so some people will definitely benefit from what rust makes available.
But yeah, I think for some projects rust brings you a great type system, a gross syntax, and very little additional safety. But OTOH, on those projects writing rust will be not that different than writing C. Either language will still let you forget to sanitize a length value from an external struct that is put into a DMA engine. And either language will let you create a dangerous_u32 type that needs to be sanitized before your routines write it into a peripheral. But rust’s probably would be a little more ergonomic for the programmers, a little harder to use improperly, and involve pressing every punctuation mark on your keyboard.
> Honestly, many of rust’s safety promises don’t help the type of low level code I write, so I’m skeptical of the “embedded rust” push. But embedded is a huge field so some people will definitely benefit from what rust makes available.
Why exactly? Once you write an abstraction on top of the raw addresses for configuring the hardware (usually already provided by a library) you don't need to use unsafe at all. One of the first things you do in C is write macros for all the addresses you use, writing safe wrappers isn't that much more complex than that.
Once you define a safe interface, you only have to audit the implementation of that interface for errors that aren't guarded for in unsafe code.
The safe interface you can then use without fearing memory corruption or having to audit that code for unsafety. Any safe code is pretty much only logic errors.
Using unsafe doesn't disable the safety features that Rust has like ownership rules or type safety, it's an acknowledgement that undefined behaviour can exist and that it's the programmers responsibility to ensure that undefined behaviour isn't introduced into safe Rust. There's no real way around this, if you want to write to arbitrary memory addresses Rust can't magically prove that you're doing so safely but if you can prove you're doing so safely then Rust will take care of the rest and make sure you're not introducing data races, use after free, buffer overflows, etc.
It was still attempting to load images, which probably caused the slowness - there is an option in the cached page header to request a text-only version which will load immediately.