Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sd-boot: add EFI boot manager and stub loader
- Loading branch information
1 parent
484adfd
commit 0fa2cac
Showing
19 changed files
with
3,690 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
|
||
dnl SET_ARCH(ARCHNAME, PATTERN) | ||
dnl | ||
dnl Define ARCH_<archname> condition if the pattern match with the current | ||
dnl architecture | ||
dnl | ||
AC_DEFUN([SET_ARCH], [ | ||
cpu_$1=false | ||
case "$host" in | ||
$2) cpu_$1=true ;; | ||
esac | ||
AM_CONDITIONAL(AS_TR_CPP(ARCH_$1), [test "x$cpu_$1" = xtrue]) | ||
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/sd_boot.so | ||
/stub.so |
Oops, something went wrong.
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These magic numbers have propagated around the internet, cargo-culted in to various guides to setting up secureboot. As far as I can tell, this is where they first came from. Do you know the origins of these values?
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some time of fiddling in QEMU and later on real hardware until it started to work reliably. Just straight-forward guesswork :)
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Just checking, would it be reasonable to set each of those to, say (pseudocode):
or am I misunderstanding what is going on here?
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I never tried to figure out why exactly, but the initrd needed to be placed at the higher address. That wasn't just a different number.
All the other addresses did not matter, as long as there it enough room for the data, I think.
The time this all was tested, your setup would not boot. Might be all different today.
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@grahamc, I tried the solution proposed by you and works well (the size can be obtained with 'stat -c%s $FILE'). Thanks!
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to provide more information about my use case. Particularly, I also have a splash, and I had a problem with it, because (with the magic numbers, not the same as the ones presented here, but different) it was showing "incomplete". By implementing the proposed by @grahamc, this is fixed now.
Here is the implementation:
Anyway, I've also tried without the 'change-section-vma' and it seems to work fine. Am I missing something?
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case,
objcopy
is used to modify existing 'systemd-stub binary'linuxx64.efi.stub
by adding new sections(--add-section) and save it as new EFI kernel image. Theoretically, if the address of newly added section don't overlap with the previous one, there should not be any problem.Address layout and size of 'systemd-stub binary' can be checked using
objdump
utility.Last section
.sdmagic
is at1a8c0
(VMA column) and has size of27
. So the next section(.osrel
) can start after0x1a8c0 + 0x27
=1a8e7
, and so on. The caveat is that, future versions of systemd-stub binary might look different than this.One thing I noticed that, even the systemd-stub binary is not aligned perfectly and section addresses start with some round numbers(4000, 11000, 12000, 16000, 17000...). Or these might be some magic addresses.
Using the script provided by @gustingonzalez , I set the
OSRELEASE_OFFSET=$(echo $((0x1a8e8)))
which works perfectly.Kernel EFI image now includes original sections from systemd-stub and added sections
.osrel
,.cmdline
,.linux
,.initrd
..osrel
section is exactly at0x1a8e8
as expected.0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I bring this topic up for discussion again. Previously, I commented that the proposed implementation by using dynamic offsets (originally outlined by @grahamc) was working well for me. Well... That was true on Ubuntu 20.04 with 5.x kernels. Latter, I realized that it wasn’t true for Ubuntu 16.04 and 4.x kernels, where I was getting the following error:
For the case, the EFI components were arranged as the following:
[OSRELEASE, CMDLINE, SPLASH, KERNEL, INITRD]
. Although that is in line with the indicated by @kaysievers, placing the initrd at the higher address was not working for me in 16.04, of course, when using dynamic offsets and the proposed EFI components arrangement. Then, and following the idea of the initrd position, I tried placing it in the lowest memory space (instead of the highest one). That is:[INITRD, OSRELEASE, CMDLINE, SPLASH, KERNEL]
. Luckily, this worked fine on both 16.04 and 20.04! However, this was still some shady for me...In a following experiment, I changed my original configuration, but now moving the kernel after the splash, that is:
[OSRELEASE, CMDLINE, KERNEL, SPLASH, INITRD]
. And that worked fine, too! So, I started to suspect that the problem with that was actually the kernel position, and not the initrd one. Searching on how these components are loaded, I found the following article: Linux Boot Process — Part 2. More specifically, the part that shed light for me was:Then, if at an early initialization stage the kernel is decompressed in place, it now made more sense that initrd could not be loaded with the configuration
[OSRELEASE, CMDLINE, SPLASH, KERNEL, INITRD]
. Specifically, it seems that in this case, the decompressed kernel (which, in theory, now takes up more space than before) overlaps some bytes of the initrd.In a nutshell, the solution was to put the kernel in the last position. For the case, the configuration
[OSRELEASE, CMDLINE, SPLASH, INITRD, KERNEL]
works fine for me, regardless of the arrangement of the other components behind the kernel.But, what about this? In the following case, the kernel is behind the initrd!:
Well, if we look at the difference between the initrd section beginning and the kernel section beginning, we have 0x3000000 - 0x40000 = 0x2FC0000 = 50,069,504 bytes for the kernel area. That is, we have ~50 MB available. For the case of the kernels that I tested, these did not exceed ~20 MB. So it seems reasonable that reserving more than twice the size of the kernel works well.
However, what about the fact that the initially described EFI components arrangement fails with 16.04, but works well with 20.04? Well, in this case, I don't have a formed answer. I honestly don't know how kernel decompression works in more technical terms, but I guess maybe this is done differently between both versions. Suggestions and explanations are of course welcome!
Finally, I think that kernel decompression as the cause of the issue I had makes a lot of sense, but if I'm wrong about anything, please let me know. As I said, I don't really have a very technical understanding of how the kernel decompression is done, beyond what is described above.
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following is a gist containing an implementation to generate an image in the mentioned way: https://gist.github.com/gustingonzalez/d92338c63396f0a34b01d9da781735cb.
0fa2cac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gustingonzalez
The gist does not align the sections according to the SectionAlignment property of the stub, see:
https://github.com/dracutdevs/dracut/blob/b2c6b584e2227e68f54c8843925dcb73aefe87ac/dracut.sh#L2515
https://github.com/brandsimon/verity-squash-root/pull/51/files