[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs.
From: |
Stefan |
Subject: |
[bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs. |
Date: |
Sun, 24 May 2020 02:22:47 +0200 |
Hi Mathieu!
> Am 23.05.2020 um 10:10 schrieb Mathieu Othacehe <address@hidden>:
>
>> + #~(lambda (bootloader target mount-point)
>> + "Install GRUB as e.g. \"bootx64.efi\" or \"bootarm64.efi\" \"into
>> +EFI-SUBDIR, which is usually \"efi/boot\" or \"efi/Guix\" below the
>> directory
>
> Is that TARGET or EFI-SUBDIR?
I really mean with EFI-SUBDIR the argument from the enclosing
install-grub-efi-net function, and with TARGET the argument of the lambda
function. The prototype of the lambda function is fixed by some other guix
machinery, it is not possible to pass an EFI-SUBDIR argument directly.
Take for example this path, the default: "/mnt/boot/efi/boot". Then MOUNT-POINT
is "/mnt" (like in 'guix system init config.scm /mnt'), TARGET is "/boot"
(which you also have to specify inside (operating-system (bootloader (target
"/boot") …) …), and EFI-SUBDIR is the remaining "efi/boot".
In my personal case I need MOUNT-POINT as "/" (well, 'guix system init …' was
only necessary once), TARGET as "boot-nfs" (my special setup), and EFI-SUBDIR
as "efi/boot" (because the U-Boot is using this path by default).
For a TFFP server this TARGET with /boot (or /boot-nfs in my case) is the
directory whose content has to be served. It can’t be /boot/efi (like for the
normal grub-efi bootloader), as the TFTP server needs to serve several firmware
files and the U-Boot.¹ When the U-Boot takes control, by default it tries to
load /efi/boot/bootaa64.efi via TFTP.
It may be possible to configure the U-Boot to look for files below a /efi/Guix
directory or any other path, I’m not really sure about this yet. At least
/efi/boot is the documented last resort for UEFI systems to look for some
“removable madia” to boot over TFTP.
Next GRUB takes control and looks for its grub.cfg and all its other files via
TFTP at the path specified during 'grub-mknetdir --subdir=…'. As the TFTP root
is /boot (where U-Boot and other stuff may live), this now has to be efi/boot.
So you get all GRUB files like /boot/efi/boot/grub.cfg served via TFTP from the
directory /boot/efi/boot.
For the usual grub-efi-bootloader this is a bit different. Here the normal path
is /mnt/boot/efi/Guix and for the 'grub-install' command these parameters are
required: '—-boot-directory /mnt/boot --bootloader-id Guix --efi-directory
/boot/efi'. Here the "boot" part to '--boot-directory' is hard coded, as well
as "Guix". So the only part you are free to chose is "efi" in (operating-system
(bootloader (target "boot/efi") …) …). Additionally the usual
grub-efi-bootloader looks for /boot/grub.cfg which thus is not residing inside
the efi partition like all its other files.
>> +TARGET for the system whose root is mounted at MOUNT-POINT."
>> + (let* ((mount-point-list (delete "" (string-split mount-point #\/)))
>> + (target-list (delete "" (string-split target #\/)))
>> + (net-dir
>> + (string-append "/" (string-join (append
>> + mount-point-list
>> + target-list)
>> + "/")))
>
> I think you can use something like "(in-vicinity mount-point target)"
> to do the same job.
MOUNT-POINT may be just "/", TARGET is "/boot". I’m avoiding double slashes,
like "//boot", also for all the other paths. In an earlier version I had the
“problem” that GRUB searched files with the prefix "//efi/boot" via TFTP. This
confused me on one side, but on the other side I feared that another TFTP
server might get problems with this.
Avoiding double slashes seems not to be something that in-vicinity is taking
care about. And TARGET with its "/boot" looks like an absolute path, making it
an improper argument to in-vicinity: “in-vicinity should allow filename to
override vicinity when filename is an absolute pathname and vicinity is equal
to the value of (user-vicinity). The behavior of in-vicinity when filename is
absolute and vicinity is not equal to the value of (user-vicinity) is
unspecified.”
A bit further down I need to count the directory levels up to the "/gnu" store
to construct a proper link, so I need the result of a string-split anyway.
So all in all – although it looks a bit complicated – I’d like to keep this.
Hm, but I wasn’t that strict with the EFI-SUBDIR argument. And potentially
MOUNT-POINT may be a relative path, may it? Do you know? In that case there is
a bug in prepending the "/" to net-dir, turning a relative into an absolute
path.
>
>> + ;; Tell 'grub-install' that there might be a LUKS-encrypted /boot
>> or
>> + ;; root partition.
>> + (setenv "GRUB_ENABLE_CRYPTODISK" "y")
>> + (invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
>> + (string-append "--net-directory=" net-dir)
>> + (string-append "--subdir=" subdir))
>> + (false-if-exception
>> + (delete-file efi-bootloader-link))
>> + (symlink #$efi-bootloader
>> + efi-bootloader-link)
>> + (false-if-exception
>> + (delete-file store-link))
>> + (symlink store
>> + store-link)))))
>
> What's the purpose of those two symlinks, isn't grub-mknetdir taking
> care of all this?
No, it doesn’t. The final .efi file after calling 'grub-mknetdir' is
/boot/efi/boot/arm64-efi/core.efi. I guess when using PXE there is a way to
point to this efi file, so GRUB doesn’t care. But without this the U-Boot looks
for the standardised /efi/boot/bootaa64.efi file via TFTP. So the first symlink
fixes this gap without removing other possibilities.
The second symlink is for GRUB itself. Inside /boot/efi/boot/grub.cfg there are
commands to specify the root device, usually via a file system label or a UUID.
But in this case the root device specification is just ”set root=(tftp)”.
Following lines look up files by e.g.
/gnu/store/…-grub-2.04/share/grub/unicode.pf2, which GRUB will then try to
access via TFTP. But the root for the TFTP server is /boot from the TARGET
argument, and not /. So GRUB trying to access /gnu/store/… results in an access
to /boot/gnu/store/…. Therefore the symlink from /boot/gnu to ../gnu is needed.
And as TARGET can freely be chosen the number of up-levels needs to be
calculated.
Where the usual grub-efi-bootloader is able to find and access the real root
device directly, the grub-efi-net-bootloader can only use TFTP. Therefore we
have to make the real “root device” accessible via TFPT. I’m not sure if this
is wise from a security point of view. But otherwise all files listed in the
grub.cfg would need to be copied. This would be an overhead and leads to more
complications, when deleting system generations; then obsolete copies need
determined and removed again.
> Creating a system test for this may be a bit difficult, but if you could
> add a section in the documentation describing how to setup a
> 'grub-efi-net-bootloader, that would be great!
I have some difficulties with this – despite not having knowledge with texi
yet. So help is very welcome.
You need to make use of an NFS server, serving your / directory.
You need a TFTP server set up to serve the files of our /boot directory with
access to your /gnu store via the /boot/gnu symlink as well.
You need to setup your DNS server to send some boot-options.
I use a “DiskStation” with its UI for all this but needed to fiddle around with
dnsmasq for the DNS. So this is nothing for a guix documentation. However, this
might be even out of scope. But ideally there would be examples of how to
achieve all this with guix itself. I have no experience using guix for anything
of this.
Then I use all this to boot a Raspberry Pi 3b in aarch64 mode. This requires a
none free firmware, additional configuration files for the firmware, the
(modified) U-Boot. And there is even more. I compiled the kernel linux
(currently from the mainline) with a Raspberry specific defconfig-package as an
input for the linux package and an additional function to modify the defconfig
on the fly.
There are more patches to follow for at least parts of all this.
But what I actually want to say with this: Even to reproduce my setup, still a
lot other stuff is missing. And I have no other computer for tinkering. I can’t
try out this patch on a usual x86…64 machine. I can't really tell, if this will
work right out of the box for other people on different computers.
Before documenting this for the public, I would wish that at least someone else
with access to an x86_64 UEFI system gives it a try. I'm pretty sure it will
work.
Besides all the server stuff with NFS, TFTP and DNS, there are only few
specialities to know:
(operating-system
(file-systems (cons (file-system
(mount-point "/")
(type "nfs")
(device ":/your/servers/path/to/guix-root")
(options "addr=10.11.12.2,vers=4.1"))
%base-file-systems))
(bootloader
(target "/boot")
(bootloader-configuration (bootloader grub-efi-net-bootloader)
…))
…)
The IP address of your server needs to be specified via an “addr=” option. To
make use of the defaults of the new grub-efi-net-bootloader, the target field
has to be "/boot".
Bye
Stefan
¹ Well, actually – as for grub-efi-net-bootloader you are now free to use any
path for target – you can use "/boot/efi". But then you need to make this your
TFTP server’s root, and you need to use the make-grub-efi-net-bootloader macro
with "/boot/efi" as well, and you will end up in having double efi folders as
in /boot/efi/efi/boot/grub.cfg etc. So this doesn’t make sense.
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Stefan, 2020/05/01
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Mathieu Othacehe, 2020/05/23
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Stefan, 2020/05/24
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Danny Milosavljevic, 2020/05/24
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Stefan, 2020/05/24
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Danny Milosavljevic, 2020/05/24
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Danny Milosavljevic, 2020/05/24
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Stefan, 2020/05/24
- [bug#41011] [PATCH] gnu: grub: Support for network boot via tftp/nfs., Stefan, 2020/05/24