|
Size: 6553
Comment: Update copy script in remove case
|
← Revision 18 as of 2023-08-12 05:10:07 ⇥
Size: 11419
Comment: Rewrite instructions, add UKI info
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 6: | Line 6: |
| Since Wheezy, Debian kernel on x86 contain their own [[BootLoader]] called EFI stub. Therefore it is possible to load the kernel directly, without any additional bootloader (like grub-efi). | Since Wheezy, Debian kernels on platforms with UEFI (e.g. x86, ARM, RISC-V) contain their own [[BootLoader]] called EFI stub. Therefore it is possible to load the kernel directly, without any additional bootloader (like grub-efi). With the help of [[http://manpages.debian.net/cgi-bin/man.cgi?query=systemd-stub|systemd-stub]], it's also possible to create a Unified Kernel Image, combining the kernel, cmdline, initrd, and an optional splash screen into one single EFI binary, convenient for [[SecureBoot]] signing. |
| Line 11: | Line 11: |
| == Manually setting up EFIStub == To set up EFIStub, you need to first copy the kernel and initrd into the EFI system partition, then set up an EFI boot entry for it. |
|
| Line 14: | Line 17: |
| #!/bin/sh cp /vmlinuz /boot/efi/EFI/Debian/ }}} Make it executable, enable it inside update and delete operations, and launch it manually: |
#!/bin/bash set -e cp "$2" /boot/efi/EFI/Debian/vmlinuz }}} Make it executable and create the destination folder, then manually copy the kernel for first use: |
| Line 20: | Line 25: |
| cp /etc/kernel/postinst.d/zz-update-efistub /etc/kernel/postrm.d/zz-update-efistub /etc/kernel/postinst.d/zz-update-efistub }}} /etc/initramfs/post-update.d/zz-update-efistub (create the directory if it does not exist): {{{#!highlight bash #!/bin/sh cp /initrd.img /boot/efi/EFI/Debian/ }}} Make it executable and launch it manually: |
mkdir -p /boot/efi/EFI/Debian cp /vmlinuz /boot/efi/EFI/Debian # Use /boot/vmlinuz if you have a separate /boot partition }}} Repeat for the initrd update hook in /etc/initramfs/post-update.d/zz-update-efistub: {{{#!highlight bash #!/bin/bash set -e cp "$2" /boot/efi/EFI/Debian/initrd.img }}} Make it executable and manually copy the initrd: |
| Line 32: | Line 39: |
| /etc/initramfs/post-update.d/zz-update-efistub | cp /initrd.img /boot/efi/EFI/Debian # Use /boot/initrd.img if you have a separate /boot partition |
| Line 36: | Line 43: |
| Replace /dev/sda3 with the device of your / partition, see the [[http://manpages.debian.net/cgi-bin/man.cgi?query=efibootmgr|efibootmgr manpage]] if you EFI partition is not /dev/sda1: | Replace /dev/sda3 with the device of your / partition. Also see the [[http://manpages.debian.net/cgi-bin/man.cgi?query=efibootmgr|efibootmgr manpage]] if you EFI partition is not /dev/sda1. |
| Line 39: | Line 46: |
| efibootmgr -c -g -L "Debian" -l '\EFI\Debian\vmlinuz' -u "root=UUID=$UUID rw quiet rootfstype=ext4 add_efi_memmap initrd=\\EFI\\Debian\\initrd.img" }}} You may have to add --disk /dev/nvme0n1 in case it's not auto detected (nvme0n1 being the disk with the EFI partition). |
efibootmgr -c -g -L "Debian" -l '\EFI\Debian\vmlinuz' -u "root=UUID=$UUID rw initrd=\\EFI\\Debian\\initrd.img" }}} |
| Line 51: | Line 56: |
| === Or add the boot entry with a script === | == Setting up EFIStub with a script == There are many automated solutions available for EFIStub. Here's an example from [[TriMoon]]: |
| Line 54: | Line 61: |
| * See the [[http://manpages.debian.net/cgi-bin/man.cgi?query=bash|bash]], [[http://manpages.debian.net/cgi-bin/man.cgi?query=findmnt|findmnt]] and [[http://manpages.debian.net/cgi-bin/man.cgi?query=efibootmgr|efibootmgr]] manpage's of the utilities used for/in this script. | * See the [[http://manpages.debian.net/cgi-bin/man.cgi?query=bash|bash]], [[http://manpages.debian.net/cgi-bin/man.cgi?query=findmnt|findmnt]] and [[http://manpages.debian.net/cgi-bin/man.cgi?query=efibootmgr|efibootmgr]] manpages of the utilities used in this script. |
| Line 59: | Line 66: |
| * (./) -- TriMoon <<DateTime(2018-04-24T22:12:01+0300)>> B) {OK} | |
| Line 124: | Line 130: |
| == Setting up a Unified Kernel Image == To build a unified kernel image, you will need the [[DebianPkg:systemd-boot-efi]] and [[DebianPkg:binutils]] packages installed, as well as [[DebianPkg:sbsigntool]] if you want to sign the image. You will also need to place your kernel cmdline into a file to be read by the tool used. === Manually === Some math is used to calculate the offsets that each part of the image are placed in, then objcopy is used to create the image: {{{#!highlight bash align="$(objdump -p /usr/lib/systemd/boot/efi/linuxx64.efi.stub | awk '{ if ($1 == "SectionAlignment"){print $2} }')" align=$((16#$align)) osrel_offs="$(objdump -h "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" | awk 'NF==7 {size=strtonum("0x"$3); offset=strtonum("0x"$4)} END {print size + offset}')" osrel_offs=$((osrel_offs + "$align" - osrel_offs % "$align")) cmdline_offs=$((osrel_offs + $(stat -Lc%s "/usr/lib/os-release"))) cmdline_offs=$((cmdline_offs + "$align" - cmdline_offs % "$align")) splash_offs=$((cmdline_offs + $(stat -Lc%s "/path/to/cmdline"))) splash_offs=$((splash_offs + "$align" - splash_offs % "$align")) initrd_offs=$((splash_offs + $(stat -Lc%s "/path/to/splash.bmp"))) initrd_offs=$((initrd_offs + "$align" - initrd_offs % "$align")) linux_offs=$((initrd_offs + $(stat -Lc%s "/path/to/initrd.img"))) linux_offs=$((linux_offs + "$align" - linux_offs % "$align")) objcopy \ --add-section .osrel="/usr/lib/os-release" --change-section-vma .osrel=$(printf 0x%x $osrel_offs) \ --add-section .cmdline="/path/to/cmdline" --change-section-vma .cmdline=$(printf 0x%x $cmdline_offs) \ --add-section .splash="/path/to/splash.bmp" --change-section-vma .splash=$(printf 0x%x $splash_offs) \ --add-section .initrd="/path/to/initrd.img" --change-section-vma .initrd=$(printf 0x%x $initrd_offs) \ --add-section .linux="/path/to/vmlinuz" --change-section-vma .linux=$(printf 0x%x $linux_offs) \ "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" "/boot/efi/EFI/Linux/debian.efi" }}} Replace example paths with the actual paths to kernel, cmdline, initrd, and the splash image (/dev/null can be used to disable the splash screen). Optionally sign the image for [[SecureBoot]]: {{{ sbsign --key /path/to/db.key --cert /path/to/db.crt --output /boot/efi/EFI/Linux/debian.efi /boot/efi/EFI/Linux/debian.efi }}} This will need to be done every time the kernel is updated, initrd is regenerated, or the cmdline is changed. There are apt hooks like [[https://github.com/benthetechguy/debian-uki-hooks|this]] available that automatically manage this. === With systemd-ukify === systemd's [[http://manpages.debian.net/cgi-bin/man.cgi?query=ukify|ukify]] provides an easy way to generate unified kernel images. To run it automatically with every kernel upgrade and initrd generation, create these two scripts: /etc/kernel/postinst.d/zz-ukify: {{{#!highlight bash #!/bin/bash set -e /usr/lib/systemd/ukify build \ --linux="$2" \ --initrd="/boot/initrd.img-$1" \ --cmdline="replace with your cmdline" \ --splash="/path/to/splash.bmp" \ # Remove this line if you don't want one --output="/boot/efi/EFI/Linux/debian.efi" # Add this line if you want to sign the image for secure boot sbsign --key /path/to/db.key --cert /path/to/db.crt --output /boot/efi/EFI/Linux/debian.efi /boot/efi/EFI/Linux/debian.efi }}} /etc/initramfs/post-update.d/zz-ukify: {{{#!highlight bash #!/bin/bash set -e /usr/lib/systemd/ukify build \ --linux="/boot/vmlinuz-$1" \ --initrd="$2" \ --cmdline="replace with your cmdline" \ --splash="/path/to/splash.bmp" \ # Remove this line if you don't want one --output="/boot/efi/EFI/Linux/debian.efi" # Add this line if you want to sign the image for secure boot sbsign --key /path/to/db.key --cert /path/to/db.crt --output /boot/efi/EFI/Linux/debian.efi /boot/efi/EFI/Linux/debian.efi }}} Make them executable, create the destination folder, and update the initrd to create the first image: {{{ chmod +x /etc/kernel/postinst.d/zz-ukify chmod +x /etc/initramfs/post-update.d/zz-ukify mkdir -p /boot/efi/EFI/Linux update-initramfs -u }}} === Add the boot entry === See the [[http://manpages.debian.net/cgi-bin/man.cgi?query=efibootmgr|efibootmgr manpage]] if you EFI partition is not /dev/sda1. {{{ efibootmgr -c -g -L "Debian" -l '\EFI\Linux\debian.efi' }}} |
Translation(s): none
Since Wheezy, Debian kernels on platforms with UEFI (e.g. x86, ARM, RISC-V) contain their own BootLoader called EFI stub. Therefore it is possible to load the kernel directly, without any additional bootloader (like grub-efi). With the help of systemd-stub, it's also possible to create a Unified Kernel Image, combining the kernel, cmdline, initrd, and an optional splash screen into one single EFI binary, convenient for SecureBoot signing.
Contents
Manually setting up EFIStub
To set up EFIStub, you need to first copy the kernel and initrd into the EFI system partition, then set up an EFI boot entry for it.
Copy the files
The UEFI firmware is only able to load files from the EFI partition (usually FAT). If you use a standard UEFI installation of Debian, you should copy the kernel and the initrd to /boot/efi. The best way to keep it up to date is to place a script in /etc/kernel/postinst.d/zz-update-efistub:
Make it executable and create the destination folder, then manually copy the kernel for first use:
chmod +x /etc/kernel/postinst.d/zz-update-efistub mkdir -p /boot/efi/EFI/Debian cp /vmlinuz /boot/efi/EFI/Debian # Use /boot/vmlinuz if you have a separate /boot partition
Repeat for the initrd update hook in /etc/initramfs/post-update.d/zz-update-efistub:
Make it executable and manually copy the initrd:
chmod +x /etc/initramfs/post-update.d/zz-update-efistub cp /initrd.img /boot/efi/EFI/Debian # Use /boot/initrd.img if you have a separate /boot partition
Add the boot entry
Replace /dev/sda3 with the device of your / partition. Also see the efibootmgr manpage if you EFI partition is not /dev/sda1.
export UUID=$(blkid -s UUID -o value /dev/sda3) efibootmgr -c -g -L "Debian" -l '\EFI\Debian\vmlinuz' -u "root=UUID=$UUID rw initrd=\\EFI\\Debian\\initrd.img"
You can check your new boot entry. Since EFI uses UCS2, it should look like this:
#efibootmgr -v ... .i.n.i.t.r.d.=.\.E.F.I.\.d.e.b.i.a.n.\.i.n.i.t.r.d.
Setting up EFIStub with a script
There are many automated solutions available for EFIStub. Here's an example from TriMoon:
Create the script below with it's contents. (Tip: Highlight and copy with linenumbers hidden)
- Edit the parts to accommodate your needs.
See the bash, findmnt and efibootmgr manpages of the utilities used in this script.
- Make it executable.
chmod a+x /sbin/create_EFI_Boot_Entry.sh
Execute the script as root.
sudo create_EFI_Boot_Entry.sh
Here are some line numbers with usage explanation:
#13 The label you will see in the EFI boot menu.
#14 The kernel image to use by the UEFI-BIOS. (must be inside the EFI partition)
#15 The initrd image to use by the UEFI-BIOS. (must be inside the EFI partition)
#17-20 Compose default kernel parameters.
#18 Sets the file system partition for '/' to use by the kernel. (Automatically found from running system)
#19 Sets the file system type of '/' for use by the kernel. (Automatically found from running system)
#20 Sets the initrd image for use by the kernel. (from value at #15)
#24 Grabs the default kernel parameters in use inside Grub2's config file. (Automatically found from running system)
#27-38 Combine default and extra kernel parameters.
#28-30 Used when Grub2 config is detected (Combines values from #18-20 with #24)
#32-37 Used when there is NO Grub2 config detected. (Combines values from #18-20 with Manual extra kernel parameters)
#34-37 Manual extra kernel parameters that you can set that will be appended to the defaults from #18-20.
1 #!/usr/bin/env bash
2 # /sbin/create_EFI_Boot_Entry.sh v0.2
3 # Automatically create an EFI Boot entry.
4 #
5 # (C) 2018+ ©TriMoon™ <https://github.com/TriMoon>
6 # ------------------------------------------------
7 # License: BY-SA 4.0
8 # This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
9 # https://creativecommons.org/licenses/by-sa/4.0/
10 #
11
12 # First compose the variables used as arguments:
13 label='Debian (EFI stub)'
14 loader='\EFI\debian\vmlinuz' # Use single \'s !
15 initrd='\EFI\debian\initrd.img' # Use single \'s !
16 # Compose default kernel arguments for an EFI-boot
17 printf -v largs "%s " \
18 "root=UUID=$(findmnt -kno UUID /) ro" \
19 "rootfstype=$(findmnt -kno FSTYPE /)" \
20 "initrd=${initrd}"
21 # Grab extra kernel arguments from grub2 config.
22 grub_cmdline=''
23 if test -f /etc/default/grub; then
24 grub_cmdline="$(sed -nE '/^GRUB_CMDLINE_LINUX_DEFAULT=\"/ {s#GRUB_CMDLINE_LINUX_DEFAULT=\"##; s#\"$##; p}' </etc/default/grub)"
25 fi
26 # Append extra kernel arguments
27 if test -n "${grub_cmdline}"; then
28 printf -v largs "%s " \
29 "${largs%* }" \
30 "${grub_cmdline}"
31 else
32 printf -v largs "%s " \
33 "${largs%* }" \
34 "quiet splash" \
35 "add_efi_memmap" \
36 "intel_iommu=on" \
37 "nvidia-drm.modeset=1"
38 fi
39 # echo "${largs%* }"; exit
40 # Then create the EFI entry:
41 efibootmgr -c -L "${label}" -l "${loader}" -u "${largs%* }"
On my system this EFI-entry was created using the script above:
Boot0000* Debian (EFI stub) HD(1,GPT,1e4d16a9-ba85-4a29-9fd1-277c77f4e461,0x800,0x100000)/File(\EFI\DEBIAN\VMLINUZ)r.o.o.t.=.U.U.I.D.=.7.9.2.0.e.1.9.8.-.5.0.5.6.-.4.e.b.4.-.b.3.7.c.-.1.a.b.f.8.1.c.5.a.e.8.d. .r.o. .r.o.o.t.f.s.t.y.p.e.=.e.x.t.4. .i.n.i.t.r.d.=.\.E.F.I.\.d.e.b.i.a.n.\.i.n.i.t.r.d...i.m.g. .q.u.i.e.t. .s.p.l.a.s.h. .i.n.t.e.l._.i.o.m.m.u.=.o.n. .n.v.i.d.i.a.-.d.r.m...m.o.d.e.s.e.t.=.1. .h.u.g.e.p.a.g.e.s.z.=.1.G.B. .h.u.g.e.p.a.g.e.s.=.4.
If you were installing Debian from UEFI medium, efibootmgr should be installed by default. However, sometimes it can report that EFI variables are not supported. If you are sure that you have EFI partition, probably you need to download efivar package and modprobe efivars module.
Setting up a Unified Kernel Image
To build a unified kernel image, you will need the systemd-boot-efi and binutils packages installed, as well as sbsigntool if you want to sign the image. You will also need to place your kernel cmdline into a file to be read by the tool used.
Manually
Some math is used to calculate the offsets that each part of the image are placed in, then objcopy is used to create the image:
1 align="$(objdump -p /usr/lib/systemd/boot/efi/linuxx64.efi.stub | awk '{ if ($1 == "SectionAlignment"){print $2} }')"
2 align=$((16#$align))
3 osrel_offs="$(objdump -h "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" | awk 'NF==7 {size=strtonum("0x"$3); offset=strtonum("0x"$4)} END {print size + offset}')"
4 osrel_offs=$((osrel_offs + "$align" - osrel_offs % "$align"))
5 cmdline_offs=$((osrel_offs + $(stat -Lc%s "/usr/lib/os-release")))
6 cmdline_offs=$((cmdline_offs + "$align" - cmdline_offs % "$align"))
7 splash_offs=$((cmdline_offs + $(stat -Lc%s "/path/to/cmdline")))
8 splash_offs=$((splash_offs + "$align" - splash_offs % "$align"))
9 initrd_offs=$((splash_offs + $(stat -Lc%s "/path/to/splash.bmp")))
10 initrd_offs=$((initrd_offs + "$align" - initrd_offs % "$align"))
11 linux_offs=$((initrd_offs + $(stat -Lc%s "/path/to/initrd.img")))
12 linux_offs=$((linux_offs + "$align" - linux_offs % "$align"))
13
14 objcopy \
15 --add-section .osrel="/usr/lib/os-release" --change-section-vma .osrel=$(printf 0x%x $osrel_offs) \
16 --add-section .cmdline="/path/to/cmdline" --change-section-vma .cmdline=$(printf 0x%x $cmdline_offs) \
17 --add-section .splash="/path/to/splash.bmp" --change-section-vma .splash=$(printf 0x%x $splash_offs) \
18 --add-section .initrd="/path/to/initrd.img" --change-section-vma .initrd=$(printf 0x%x $initrd_offs) \
19 --add-section .linux="/path/to/vmlinuz" --change-section-vma .linux=$(printf 0x%x $linux_offs) \
20 "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" "/boot/efi/EFI/Linux/debian.efi"
Replace example paths with the actual paths to kernel, cmdline, initrd, and the splash image (/dev/null can be used to disable the splash screen). Optionally sign the image for SecureBoot:
sbsign --key /path/to/db.key --cert /path/to/db.crt --output /boot/efi/EFI/Linux/debian.efi /boot/efi/EFI/Linux/debian.efi
This will need to be done every time the kernel is updated, initrd is regenerated, or the cmdline is changed. There are apt hooks like this available that automatically manage this.
With systemd-ukify
systemd's ukify provides an easy way to generate unified kernel images. To run it automatically with every kernel upgrade and initrd generation, create these two scripts:
/etc/kernel/postinst.d/zz-ukify:
1 #!/bin/bash
2 set -e
3
4 /usr/lib/systemd/ukify build \
5 --linux="$2" \
6 --initrd="/boot/initrd.img-$1" \
7 --cmdline="replace with your cmdline" \
8 --splash="/path/to/splash.bmp" \ # Remove this line if you don't want one
9 --output="/boot/efi/EFI/Linux/debian.efi"
10
11 # Add this line if you want to sign the image for secure boot
12 sbsign --key /path/to/db.key --cert /path/to/db.crt --output /boot/efi/EFI/Linux/debian.efi /boot/efi/EFI/Linux/debian.efi
/etc/initramfs/post-update.d/zz-ukify:
1 #!/bin/bash
2 set -e
3
4 /usr/lib/systemd/ukify build \
5 --linux="/boot/vmlinuz-$1" \
6 --initrd="$2" \
7 --cmdline="replace with your cmdline" \
8 --splash="/path/to/splash.bmp" \ # Remove this line if you don't want one
9 --output="/boot/efi/EFI/Linux/debian.efi"
10
11 # Add this line if you want to sign the image for secure boot
12 sbsign --key /path/to/db.key --cert /path/to/db.crt --output /boot/efi/EFI/Linux/debian.efi /boot/efi/EFI/Linux/debian.efi
Make them executable, create the destination folder, and update the initrd to create the first image:
chmod +x /etc/kernel/postinst.d/zz-ukify chmod +x /etc/initramfs/post-update.d/zz-ukify mkdir -p /boot/efi/EFI/Linux update-initramfs -u
Add the boot entry
See the efibootmgr manpage if you EFI partition is not /dev/sda1.
efibootmgr -c -g -L "Debian" -l '\EFI\Linux\debian.efi'
