[PATCH] Install guix system on Raspberry Pi

OpenSubmitted by Stefan.
Details
6 participants
  • Danny Milosavljevic
  • Ludovic Courtès
  • Maxime Devos
  • phodina
  • Stefan
  • Vagrant Cascadian
Owner
unassigned
Severity
normal
S
S
Stefan wrote on 9 May 2021 17:32
Patches to install guix system on Raspberry Pi
(address . guix-patches@gnu.org)
19E4796A-B0DB-444F-8773-2E8D3EF6132D@vodafonemail.de
Hi!

This patch series adds support for the Raspberry Pi. It allows to use ‘sudo -E guix system init … /mnt’ with the root partition mounted at /mnt and the boot partition mounted at /mnt/boot/efi, as you would expect it for a PC with UEFI. Installing for netboot is possible as well.

It is currently not possible to build an image with this patch series, because of the intercepting handling for efi system image creation.

Some of these patches are generic and not related to the Raspberry Pi. I hope they will be a useful contribution for everyone.

Here is a quick overview of the single patches:

01: Disable the tests on aarch64 for qemu-minimal, because it is non-deterministic but needed to build grub.

02: Rework the grub-efi-netboot-bootloader and add a grub-efi-netboot-removable-bootloader which then are pre-installed. This allows a simplification of the efi-bootloader-chain, as these pre-installed bootloaders just need to be copied and can therefore easily be collected in a bootloader-profile.

03: A new build-side module to modify a defconfig. It is used to customize U-Boot and Linux packages.

04: Customized and pre-installed U-Boot packages for the Raspberry Pi.

05: Fixed the EXTRAVERSION variable used to build Linux, so that the extra-version argument will be visible with uname.

06: New function to modify a Linux package by using another defconfig and/or adding or removing configurations.

07: Raspberry Pi specific defconfig objects.

08: Some helpers to construct config.txt files for the Raspberry Pi firmware.

09: A function to create a package with device-tree files from a Linux package for the Raspberry Pi.

10: A bootloader for the Raspberry Pi. Additionally two examples of operating-system definitions to boot from local storage or over network, the latter is making necessary configuration changes to Linux.

The firmware topic is excluded. In the same way that guix assumes that some UEFI firmware is already present on a PC, this patch series assumes that a firmware to start U-Boot is already present.

The grub bootloaders are usable on PCs as well. In contrast to the normal grub-efi, all grub files are copied to the EFI system partition, instead of the root partition. This is a side effect of the netboot capability. Maybe this is helpful for some spacial cases. I realized for example that the normal grub-efi locates the partition containing the grub.cfg by a device name like (hd0,gpt1), this may be problematic when adding disks to a system. The new grub bootloaders determine the partition by UUID.

The new possibility to customize Linux with (modify-linux) will be useful for anyone in need to do small configuration changes. There is also the possibility to pass an own defconfig file to this function. It can either be the name of a defconfig file from the Linux sources, or it can be a file-like object, like produced by (local-file) or possibly downloaded with the new (make-defconfig) function.


Bye

Stefan
S
S
Stefan wrote on 16 May 2021 14:46
(address . 48314@debbugs.gnu.org)
53799D56-08BA-401A-BC09-81BA61736AAC@vodafonemail.de
Hi!

There were errors in the patches 05 and 06 in the EXTRAVERSION handling and in the modify-linux function.

Here an updated patch series. They apply to commit f661e6883ec345258634940ce5d52957e1bb90c3.


Bye

Stefan
D
D
Danny Milosavljevic wrote on 19 Jun 2021 20:11
(name . Stefan)(address . stefan-guix@vodafonemail.de)
20210619201103.69502840@scratchpost.org
Hi Stefan,

Thanks!

Pushed 05-gnu-linux-correct-name-of.patch to guix master as commit b04cba9ee533945f90ffd72637f064c60188f945.

(I've also started testing the other patches of this patchset, but it will take a while)

Toggle diff (36 lines)
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 84ea849108..51e692a8c3 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -749,9 +749,9 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
 
 (define* (make-linux-libre version hash-string supported-systems
                            #:key
+                           (extra-version #f)
                            ;; A function that takes an arch and a variant.
                            ;; See kernel-config for an example.
-                           (extra-version #f)
                            (configuration-file #f)
                            (defconfig "defconfig")
                            (extra-options %default-extra-linux-options)
@@ -770,9 +770,9 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
 
 (define* (make-linux-libre* version source supported-systems
                             #:key
+                            (extra-version #f)
                             ;; A function that takes an arch and a variant.
                             ;; See kernel-config for an example.
-                            (extra-version #f)
                             (configuration-file #f)
                             (defconfig "defconfig")
                             (extra-options %default-extra-linux-options))
@@ -838,7 +838,8 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
                  (format #t "`CROSS_COMPILE' set to `~a'~%"
                          (getenv "CROSS_COMPILE"))))
 
-             (setenv "EXTRA_VERSION" ,extra-version)
+             (setenv "EXTRAVERSION" ,(and extra-version
+                                          (string-append "-" extra-version)))
 
              (let ((build  (assoc-ref %standard-phases 'build))
                    (config (assoc-ref (or native-inputs inputs) "kconfig")))
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEds7GsXJ0tGXALbPZ5xo1VCwwuqUFAmDOMzcACgkQ5xo1VCww
uqVnVgf+MFlQTHVvJg/06G3HbaXgAe0tqPql7swHL83tSPikO1XRB9VjGp2FdzSH
NqFiGnGhVwUboEH4x3i6DuK8BOPz2A6Xc8aUDG4taNr0Tc9rttde5qg7cOY5lzj5
4dJuDURrUvvM5HQir73Kb/kgkAqvpqLQMwESl6uYE6nPDdLZaQLXuSYclnkrVFAI
MpViIUWfEVuMJlKId59YnzSXcoTgFwHgFN7SO1dGAyjL9Dl4+EqQMWkUAR1UQ32s
oXEaapihBsIN+bkNA9iSDXSTM02mJvdg0vDjEsFARSIzsK4x1n/2TC7Um+Fzq6Hp
Dr2r5W3qo9c8pOvHYWxbdyjNCHN/Tw==
=f5GG
-----END PGP SIGNATURE-----


D
D
Danny Milosavljevic wrote on 19 Jun 2021 20:13
(name . Stefan)(address . stefan-guix@vodafonemail.de)(address . 48314@debbugs.gnu.org)
20210619201311.7f3c5f60@scratchpost.org
Hi Stefan,

Since bug 43534 is closed, does that mean I can drop patch 01-gnu-qemu-disable-tests-on.patch ?
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEds7GsXJ0tGXALbPZ5xo1VCwwuqUFAmDOM7gACgkQ5xo1VCww
uqVt6gf/YjZphtgKR4fzrQCi9gra8qv1hMqQvAPlE1MKha8AFUEPnHI29vIKX/pT
w2TUUEoh10mk0yfOD+V+WhU4YB3PyN1x6J86iAIF3dY9MPejh/vPWxUsMXsY3uVH
VyKDwYjfkHJbDlS3hr4wVXHic+IKixR3tBF4myXpyA5IVSqL/92Q1EWCTH9CVEby
5E9qH9tgGhoCbuCtYOSeNuhS+W5z2YirRaogcSRaNS7zzH7eNBWSxXuehfBYDHX+
+M5ZeJSu3bKghk2CK5x6ioxbGxe/lv97fy+vPtVN5OX7Nff5OQBrCc7yhdhoVe0b
AFsbNwinvUkU1xRhcNOSmQRMZcRJOg==
=QWVZ
-----END PGP SIGNATURE-----


D
D
Danny Milosavljevic wrote on 19 Jun 2021 21:04
(name . Stefan)(address . stefan-guix@vodafonemail.de)(address . 48314@debbugs.gnu.org)
20210619210417.67c21720@scratchpost.org
Hi Stefan,

In 04-gnu-bootloader-add-u-boot.patch, I think that having #:name is too magical
(it still only replaces part of the package name, and then still only after
substitution). But if made non-magical, then it has too little benefit.

Likewise for #:description.

If it's alright with you, can we just drop #:name xxx and #:description xxx
altogether and instead do:

(define-public u-boot-rpi-3-efi
(package
(inherit
(make-preinstalled-u-boot-package
"rpi_3_32b"
"arm-linux-gnueabihf"
#:name "rpi-3-efi"
#:configs %u-boot-rpi-efi-configs
#:description %u-boot-rpi-efi-description-32-bit))
(name "u-boot-rpi-3-efi")
(description %u-boot-rpi-efi-description-32-bit)))

And similar for all the other u-boot definitions, and for
the usage of make-u-boot-package inside make-preinstalled-u-boot-package ?

Or are there upsides to doing it like you did it?

I'm aware that the same can be said for "board" ... which is used already.
However, that parameter is also used for something else, so it needs to be there.

NAME isn't used for anything else but for doing what a regular package inherit
could do anyway. Is there a downside when using package inherit?
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEds7GsXJ0tGXALbPZ5xo1VCwwuqUFAmDOP7EACgkQ5xo1VCww
uqVAaAf9HBxCMDHNFiQOsIsHVDFut+nWPG+PQGUa/IvGqBZglqoAZU/PH1XpmAhB
kuF4mcd4OUl88BADffwa2ur3ymgdrxYZweOlEZNPg5GoqoJd9LoEGjBJdfU+l4kK
/aWZlDWxLSX1LLRZGO5vIydWdEO+ClzRPmVit1z6UnGCZOLrs2hpnxNVoAI/7VaK
aVLhfskhoiR98rUOH5RseV2vxzafpkWL7QEkMbnUieE8WnNmi4ziYWADlJmnJjBc
n0gIoIrKdKoITdRME1oJM1kt/E4wC0nK5vdzn9/JtnYlp3saHgxJb4wbSxWNcbLW
S22zXd1f9GsnncLbh9wtJJzCNdGgLQ==
=1Gd1
-----END PGP SIGNATURE-----


D
D
Danny Milosavljevic wrote on 19 Jun 2021 21:10
(name . Stefan)(address . stefan-guix@vodafonemail.de)
20210619211026.5eb44073@scratchpost.org
Hi Mark,
Hi Leo,

could you look at 06-gnu-linux-new-function-to.patch of this patchset?

It provides the user a means of (slightly) editing kernel configs using a
high-level interface, called "modify-linux".

What do you think?

@Stefan: On the other hand, I'm not sure of the general utility of make-defconfig.
I've never needed something like it in decades. Is it worth exporting as public
from (gnu packages linux) ? Sounds like a too weird special case to have general
utility.
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEds7GsXJ0tGXALbPZ5xo1VCwwuqUFAmDOQSIACgkQ5xo1VCww
uqX35Qf/UePQutH3t4R3n2mL1izoKqJD7RNq+4T6RYkC+Ic8I4w3+aig9akcAmR0
7WxTZ33N3bhhV05VrMH8kyZftlSQky6JfslqgxIkJXFZwi81Qf+2unr5+GAaVdy5
+ATIRs2/M4C+/Xs55dMoVaOpw4ZfhGcG4nVKLkt3UbUdxSA7ZS4B3V/UwvzpF2NQ
COTP9VzrqEzH8aVlGgWgOn/XuV4YxLMUrNFncTegjtDs/HVnq1NlhBkCwVGEw2+a
g7mF2O/QbEV2GKu12jipQWf6+fajBqCaNEuYSvwN/ny+x1p+f8PrB5+spBadFdwf
7rVmslqAuLXnUFV+4RClU3pRfjhGRg==
=qGer
-----END PGP SIGNATURE-----


S
S
Stefan wrote on 19 Jun 2021 21:10
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)(address . 48314@debbugs.gnu.org)
D30A68B9-D3C1-4DF7-BE68-7ECE39EE296E@vodafonemail.de
Hi Danny!

Toggle quote (2 lines)
> Since bug 43534 is closed, does that mean I can drop patch 01-gnu-qemu-disable-tests-on.patch ?

Yes.

On the other side I have a bad experience with qemu substitutes for aarch64 and building qemu on a Raspberry takes a night and then still fails during the test. I hope the substitute situation improves, otherwise this patch should still be considered.


Bye

Stefan
S
S
Stefan wrote on 19 Jun 2021 21:18
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)(address . 48314@debbugs.gnu.org)
56852507-062B-4242-8584-488E691DCD84@vodafonemail.de
Hi Danny!

Toggle quote (3 lines)
> If it's alright with you, can we just drop #:name xxx and #:description xxx
> altogether

That’s OK.


Bye

Stefan
S
S
Stefan wrote on 19 Jun 2021 22:21
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)
897B7FF7-24C1-4B96-8441-415596267E99@vodafonemail.de
Hi!

Toggle quote (2 lines)
> @Stefan: On the other hand, I'm not sure of the general utility of make-defconfig.

There is currently no simple way change the Linux configuration. Also by modifying the final .config as of today (which kind of contains all CONFIG_…-variables), as far as I know dependencies will not be resolved and conflicting configurations can easily happen.

A defconfig however gets striped down to a minimum of required CONFIG_…-variables and all “missing” ones get either default values or get determined through dependecies. So adding /removing/changing some few configurations to a defconfig is less error-prone. Further defconfig files are easier to maintain in git. There is a reason that only defconfig files are maintained in the Linux sources.

Please note that the patch allows to select a defconfig file from the Linux sources (if the parameter is a string), and also to provide an own defconfig file (if it is a file-like object).

Toggle quote (2 lines)
> Sounds like a too weird special case to have general utility.

Well, there is the need already in Guix to have e.g. the predefined linux-libre-arm64-generic kernel, wich just uses a certain defconfig file from the Linux sources. But this possibility is not exported.

There are many defconfig files for all sorts of boards, especially for arm32. Why shouldn’t we allow to use any of these? Why should users be restrict to “selected” configurations? Why should Guix’ kernel configuration be preferred over the plain x86_64_defconfig?

And take a look at the last patch: In order to make that kernel boot on a Raspberry from an NFS root, some few configurations are missing, which can easily be added with the “modify-linux” function. By the way, maybe “customize-linux” would be a better name.

And there is another patch from me to make the NFS root test pass. As the Linux kernel build by Guix is not able to boot over NFS root in qemu, I used the same function there to add the missing configurations.

Oh, and finally, I need the same underlying kconfig.scm and a similar defconfig modification for U-Boot as well, which allowed me to simplify the existing U-Boot packages.


Bye

Stefan
S
S
Stefan wrote on 28 Jul 2021 20:58
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)
BDB9E76C-37FF-4033-81C1-9D5F0AA575F2@vodafonemail.de
Hi Danny!

Are there any news on this topic¹?


Bye

Stefan


S
S
Stefan wrote on 31 Oct 2021 23:07
(address . 48314@debbugs.gnu.org)(name . Danny Milosavljevic)(address . dannym@scratchpost.org)
AFD31F40-6691-4B53-ACA9-7F821D139124@vodafonemail.de
Hi!

I did a rebase of the patch series to avoid bit-rotting. One patch got obsolete meanwhile.

This series applies on GIT commit 1a80b8909a521b91d30649a011b0257d0fadc18c.


Bye

Stefan
S
S
Stefan wrote on 13 Nov 2021 14:57
Adding patch tags
(address . control@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
BD1F8187-4952-4B75-A76E-F06C79A4BCF6@vodafonemail.de
tags 47744 + patch
tags 48314 + patch
block 47744 by 48314
retitle 48314 [PATCH] Install guix system on Raspberry Pi
retitle 47744 [PATCH] nfs-root test is failing
quit

Hi Ludovic!

Just for your information: The nfs-root test is kind of fixed, it was once blocking some other issue that you linked.


Bye

Stefan
V
V
Vagrant Cascadian wrote on 13 Nov 2021 19:05
Re: [bug#48314] Patches to install guix system on Raspberry Pi
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)
87czn4aq2s.fsf@ponder
On 2021-10-31, Stefan wrote:
Toggle quote (4 lines)
> I did a rebase of the patch series to avoid bit-rotting. One patch got obsolete meanwhile.
>
> This series applies on GIT commit 1a80b8909a521b91d30649a011b0257d0fadc18c.

And still applies on master as of
193d7b5b450d2004c26720e488a9cce930542e9e :)

Subject: [PATCH 3/8] * gnu/packages/bootloader.scm (make-u-boot-package): Add
keyword parameters 'name' and 'description'.
...
(u-boot-rpi-0-w, u-boot-rpi, u-boot-rpi-2, u-boot-rpi-3,
u-boot-rpi-4, u-boot-rpi-64, u-boot-rpi-0-w-efi, u-boot-rpi-efi,
u-boot-rpi-2-efi, u-boot-rpi-3-efi, u-boot-rpi-4-efi, u-boot-rpi-efi-64): New
packages.

The u-boot-rpi-0-w and u-boot-rpi variants are ARMv6 boards, and Guix's
armhf baseline is ARMv7, so those won't work with guix system. Are there
other use-cases for providing u-boot builds for these boards?

Upstream provides defconfigs for these variants:

armv6 variants (unsupported on guix's armhf, maybe other use-cases?):

rpi_0_w
rpi

armhf-capable variants:

rpi_2
rpi_3_32b
rpi_4_32b

aarch64 variants:

rpi_3
rpi_3_b_plus
rpi_4
rpi_arm64 (supports rpi 3 and 4 variants?)


+(define-public u-boot-rpi-3
+ (make-preinstalled-u-boot-package
+ "rpi_3_32b"
+ "arm-linux-gnueabihf"
+ #:name "rpi-3"
+ #:description %u-boot-rpi-description-32-bit))

I would name this "u-boot-rpi-3-32b"


+(define-public u-boot-rpi-4
+ (make-preinstalled-u-boot-package
+ "rpi_4_32b"
+ "arm-linux-gnueabihf"
+ #:name "rpi-4"
+ #:description %u-boot-rpi-description-32-bit))

And this "u-boot-rpi-4-32b".

+(define-public u-boot-rpi-64
+ (make-preinstalled-u-boot-package
+ "rpi_arm64"
+ "aarch64-linux-gnu"
+ #:name "rpi-64"
+ #:description %u-boot-rpi-description-64-bit))

And this "u-boot-rpi-arm64".

In other words, keep names consistent with the upstream defconfig they
are based on.

I presume you didn't add the aarch64 rpi_3 and rpi_4 variants because
they are supported by rpi_arm64?


I think without addressing the rest of the patch series, adding to guix
master the following packages could make the remaining diff smaller:

u-boot-rpi-2 (rpi_2_defconfig)
u-boot-rpi-3-32b (rpi_3_32b_defconfig)
u-boot-rpi-4-32b (rpi_4_32b_defconfig)
u-boot-rpi-arm64 (rpi_arm64_defconfig)

We wouldn't have a relevent installation configuration, but at least it
would allow building them and manually copying u-boot.bin to the
firmware partition...


live well,
vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYY/+gAAKCRDcUY/If5cW
quCEAP4qWZUmOoFzSzr9IAEciGDq1GtmAkTpByfpGYp9N43UOAEA6qfQUtP/OWCl
mY66LgQssmL/BipkXW6FXbQixP3Epwk=
=Dw5b
-----END PGP SIGNATURE-----

V
V
Vagrant Cascadian wrote on 13 Nov 2021 19:23
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)
87a6i7c3sw.fsf@ponder
On 2021-10-31, Stefan wrote:
...
Subject: [PATCH 3/8] * gnu/packages/bootloader.scm (make-u-boot-package): Add
keyword parameters 'name' and 'description'.
(make-preinstalled-u-boot-package): New function to make minimal packages.

+(define*-public (make-preinstalled-u-boot-package board
+ triplet
+ #:key
+ defconfig
+ configs
+ name
+ description
+ (u-boot-file "u-boot.bin"))
+ "Returns a package with a single U-BOOT-FILE for BOARD cross-compiled for
+TRIPLET with the optional DEFCONFIG file and optional configuration changes
+from CONFIGS. Either NAME, if used, or otherwise BOARD will be part of the
+package name. DESCRIPTION will be appended to the package description."

u-boot-file appears to be hard-coded; there may be other boards which
use a different u-boot artifact. Also, why return a single file, rather
than just building a package and then allowing other functions to pick
the appropriate file out of the resulting package?

I wondered "why does it have to be cross-compiled" but then realized
that came from the existing make-u-boot-package function. I've mostly
been building u-boot natively these days. :)


live well,
vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYZACwgAKCRDcUY/If5cW
qnWGAP9uooKKUAaUXpv9QlckQptiHVjOe9Htm7L6dNLaqDwRiQEAx0Cy4tB+jrAS
bvKHMzVyrqdJvlI1kqKM+5ORgkTV0wM=
=RuTm
-----END PGP SIGNATURE-----

V
V
Vagrant Cascadian wrote on 13 Nov 2021 19:51
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)
875ysvc2it.fsf@ponder
On 2021-11-13, Vagrant Cascadian wrote:
Toggle quote (7 lines)
> Subject: [PATCH 3/8] * gnu/packages/bootloader.scm (make-u-boot-package): Add
> keyword parameters 'name' and 'description'.
> ...
> (u-boot-rpi-0-w, u-boot-rpi, u-boot-rpi-2, u-boot-rpi-3,
> u-boot-rpi-4, u-boot-rpi-64, u-boot-rpi-0-w-efi, u-boot-rpi-efi,
> u-boot-rpi-2-efi, u-boot-rpi-3-efi, u-boot-rpi-4-efi, u-boot-rpi-efi-64): New
> packages.
...
Toggle quote (11 lines)
> +(define-public u-boot-rpi-64
> + (make-preinstalled-u-boot-package
> + "rpi_arm64"
> + "aarch64-linux-gnu"
> + #:name "rpi-64"
> + #:description %u-boot-rpi-description-64-bit))
>
> And this "u-boot-rpi-arm64".
>
> In other words, keep names consistent with the upstream defconfig they
> are based on.
...
Toggle quote (8 lines)
> I think without addressing the rest of the patch series, adding to guix
> master the following packages could make the remaining diff smaller:
>
> u-boot-rpi-2 (rpi_2_defconfig)
> u-boot-rpi-3-32b (rpi_3_32b_defconfig)
> u-boot-rpi-4-32b (rpi_4_32b_defconfig)
> u-boot-rpi-arm64 (rpi_arm64_defconfig)

Patch that builds, but haven't tested on an actual board (do have rpi2
and rpi3b+ could test sometime):

Toggle diff (45 lines)
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 706ddf0207..f5a3fd51e0 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -994,6 +994,18 @@ (define-public u-boot-pinebook-pro-rk3399
        `(("firmware" ,arm-trusted-firmware-rk3399)
          ,@(package-native-inputs base))))))

+(define-public u-boot-rpi-2
+  (make-u-boot-package "rpi_2" "arm-linux-gnueabihf"))
+
+(define-public u-boot-rpi-3-32b
+  (make-u-boot-package "rpi_3_32b" "arm-linux-gnueabihf"))
+
+(define-public u-boot-rpi-4-32b
+  (make-u-boot-package "rpi_4_32b" "arm-linux-gnueabihf"))
+
+(define-public u-boot-rpi-arm64
+  (make-u-boot-package "rpi_arm64" "aarch64-linux-gnu"))
+
 (define-public vboot-utils
   (package
     (name "vboot-utils")



Which leads me to wonder, why have the name and description argument at
all, when you could just inherit and set the name, like done with the
boneblack?

(define-public u-boot-am335x-boneblack
  (let ((base (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf")))
    (package
      (inherit base)
      (name "u-boot-am335x-boneblack")
      (description "U-Boot is a bootloader used mostly for ARM
boards. It also initializes the boards (RAM etc).
...


And of course, thanks for working on this! :)


live well,
  vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYZAJPwAKCRDcUY/If5cW
qnxYAP0Z7B/K+KyoxrUExE7pXIkYiRyTF+WD8UKCOGclCukR4gD/bZKdtBpvgjOA
D6LTIr2JWJZbDpiSroRJDq5hGDfgWwI=
=HhQ2
-----END PGP SIGNATURE-----

V
V
Vagrant Cascadian wrote on 13 Nov 2021 21:21
(name . Danny Milosavljevic)(address . dannym@scratchpost.org)
87zgq7ajt5.fsf@ponder
On 2021-10-31, Stefan wrote:
Toggle quote (5 lines)
> +(define-public %u-boot-rpi-efi-configs
> + '("CONFIG_OF_EMBED="
> + "CONFIG_OF_BOARD=y"
> + "CONFIG_BOOTDELAY=0"))

This is surely a matter of opinion, but CONFIG_BOOTDELAY=0 is kind of
nasty; it makes it nearly impossible to debug from a u-boot prompt if
needed. The default is probably "2" ... long enough to actually
interrupt it, but short enough that it shouldn't cause huge delays in
the boot process...

I know grub-efi will add it's own delay, so in a working environment,
this just seems like an additional two seconds, but u-boot's EFI
implementation is changing often enough that I wouldn't be surprised if
you need to occasionally debug something.


live well,
vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYZAePQAKCRDcUY/If5cW
qsx8AQCVOpicppWo+OHD/jlMDlBJ/27wMT3mFNLksdYI75+iUQD/VHPEdzfJpsv6
9cW4FCgwCuRy5dtkOqh7migzIkd8XAA=
=UWBU
-----END PGP SIGNATURE-----

P
P
phodina wrote on 17 Nov 2021 15:00
Install guix system on Raspberry Pi
(name . 48314@debbugs.gnu.org)(address . 48314@debbugs.gnu.org)
OahXqPKMATT16YqLIphkEprs1qTp5g42cHom8LCs7nzh7sIvl7z2VxyMPa5_K3c-A8kdSGF2OKDdv6x5QeMqm7Fu0Ta0EApAP0paB3wawbo=@protonmail.com
Hi Stefan,

I've attempted to cross compile the system on x86_64 machine and I must report here are still several issue.

- Firstly it has to be attempted off the branch core-updates as there is the latest packaged meson build system which allows cross compilation.

guix system: error: gnu/packages/glib.scm:172:2: glib@2.62.6: build system `meson' does not support cross builds

Note that a minor issue happens when applying your patches on top of core-updates is patch-04 failing due to collision in the header with your email address.
- Secondly there are some packages that need to be patched. See the attached file.

- Thirdly there is some issue in the optional test cases in the package lsof which fail if executed on btrfs (unfortunately that's my case so I disabled them, just the optional part).

If I apply all the changes I can build the system.

- However, that brings me to the last issue. There is a package efivar which does not build. The issue there is described here [1].

Then again I haven't actually ran the system on Raspberry Pi itself. I'll attempt to setup Debian and build it natively as you suggested.

Kind regards
Petr

PS: Sorry Stefan for the late answer

From 48ccde0b13a471040eccd87e409ae0cfe29fbc79 Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Tue, 16 Nov 2021 14:16:16 +0100
Subject: [PATCH] Fixes to cross compile system for aarch64.


Toggle diff (145 lines)
diff --git a/gnu/packages/certs.scm b/gnu/packages/certs.scm
index 39c3ebd128..311d5d4974 100644
--- a/gnu/packages/certs.scm
+++ b/gnu/packages/certs.scm
@@ -158,7 +158,7 @@ that was originally contributed to Debian.")
                 '(set-paths install-locale unpack))
          (add-after 'unpack 'install
            (lambda _
-             (let ((certsdir (string-append %output "/etc/ssl/certs/")))
+             (let ((certsdir (string-append (assoc-ref %outputs "out") "/etc/ssl/certs/")))
                (with-directory-excursion "nss/lib/ckfw/builtins/"
                  (unless (file-exists? "blacklist.txt")
                    (call-with-output-file "blacklist.txt" (const #t)))
@@ -206,7 +206,7 @@ taken from the NSS package and thus ultimately from the Mozilla project.")
 
            ;; Create hash symlinks suitable for OpenSSL ('SSL_CERT_DIR' and
            ;; similar.)
-           (chdir (string-append %output "/etc/ssl/certs"))
+           (chdir (string-append (assoc-ref %outputs "out") "/etc/ssl/certs"))
            (invoke (string-append perl "/bin/perl")
                    (string-append openssl "/bin/c_rehash")
                    ".")))))
diff --git a/gnu/packages/disk.scm b/gnu/packages/disk.scm
index 7d6f3811dd..fe30f0c08c 100644
--- a/gnu/packages/disk.scm
+++ b/gnu/packages/disk.scm
@@ -447,7 +447,7 @@ to recover data more efficiently by only reading the necessary blocks.")
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags (list "--enable-compat-symlinks")
-       #:make-flags (list (string-append "PREFIX=" %output)
+       #:make-flags (list (string-append "PREFIX=" (assoc-ref %outputs "out"))
                           "CC=gcc")))
     (native-inputs
      `(("autoconf" ,autoconf)
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index f8db781446..5910647e7a 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -2851,7 +2851,7 @@ external rate conversion.")
     (arguments
      '(#:tests? #f       ; no test suite
        #:configure-flags ; add $libdir to the RUNPATH of executables
-       (list (string-append "LDFLAGS=-Wl,-rpath=" %output "/lib"))))
+       (list (string-append "LDFLAGS=-Wl,-rpath=" (assoc-ref %outputs "out") "/lib"))))
     (home-page "https://www.netfilter.org/projects/iptables/index.html")
     (synopsis "Programs to configure Linux IP packet filtering rules")
     (description
@@ -4323,9 +4323,9 @@ dm-thin, dm-cache and dm-era device-mapper targets.")
     (build-system gnu-build-system)
     (arguments
      `(#:make-flags
-       (list (string-append "PREFIX=" %output)
-             (string-append "INSTALL_MAN=" %output "/share/man")
-             (string-append "LDFLAGS=-Wl,-rpath=" %output "/lib")
+       (list (string-append "PREFIX=" (assoc-ref %outputs "out"))
+             (string-append "INSTALL_MAN=" (assoc-ref %outputs "out") "/share/man")
+             (string-append "LDFLAGS=-Wl,-rpath=" (assoc-ref %outputs "out") "/lib")
              "BUILD_STATIC=")
        #:phases
        (modify-phases %standard-phases
@@ -5343,7 +5343,7 @@ Linux Device Mapper multipathing driver:
     (arguments
      `(#:make-flags
        (let ((target ,(%current-target-system)))
-         (list (string-append "prefix=" %output)
+         (list (string-append "prefix=" (assoc-ref %outputs "out"))
                (string-append
                 "CC=" (if target
                           (string-append (assoc-ref %build-inputs "cross-gcc")
@@ -6791,10 +6791,12 @@ under OpenGL graphics workloads.")
     (arguments
      `(;; Tests require a UEFI system and is not detected in the chroot.
        #:tests? #f
-       #:make-flags (list (string-append "prefix=" %output)
-                          (string-append "libdir=" %output "/lib")
+       #:make-flags (list (string-append "prefix=" (assoc-ref %outputs
+	   "out"))
+                          (string-append "libdir=" (assoc-ref %outputs "out") "/lib")
                           (string-append "CC_FOR_BUILD=" ,(cc-for-target))
-                          (string-append "LDFLAGS=-Wl,-rpath=" %output "/lib"))
+                          (string-append "LDFLAGS=-Wl,-rpath=" (assoc-ref
+						  %outputs "out") "/lib"))
        #:phases
        (modify-phases %standard-phases
          (delete 'configure))))
@@ -6825,8 +6827,8 @@ interface to the variable facility of UEFI boot firmware.")
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f ;no tests
-       #:make-flags (list (string-append "prefix=" %output)
-                          (string-append "libdir=" %output "/lib")
+       #:make-flags (list (string-append "prefix=" (assoc-ref %outputs "out"))
+                          (string-append "libdir=" (assoc-ref %outputs "out") "/lib")
                           ;; EFIDIR denotes a subdirectory relative to the
                           ;; EFI System Partition where the loader will be
                           ;; installed (known as OS_VENDOR in the code).
diff --git a/gnu/packages/lsof.scm b/gnu/packages/lsof.scm
index b317902ee7..519f7f15b2 100644
--- a/gnu/packages/lsof.scm
+++ b/gnu/packages/lsof.scm
@@ -90,7 +90,10 @@
                 (invoke "./Add2TestDB")
 
                 ;; The ‘standard’ tests suggest running ‘optional’ ones as well.
-                (invoke "make" "standard" "optional")))
+				;; optional test fail on BTRFS
+				;; https://www.spinics.net/lists/linux-btrfs/msg09044.html
+				;; https://githubmemory.com/repo/lsof-org/lsof/issues/152?page=2
+                (invoke "make" "standard" )));"optional")))
             #t))
         (replace 'install
           (lambda* (#:key outputs #:allow-other-keys)
diff --git a/gnu/packages/man.scm b/gnu/packages/man.scm
index b4431e5b08..ac4920d836 100644
--- a/gnu/packages/man.scm
+++ b/gnu/packages/man.scm
@@ -183,9 +183,9 @@ a flexible and convenient way.")
                        (string-append "--with-col=" util "/bin/col")
                        ;; The default systemd directories ignore --prefix.
                        (string-append "--with-systemdsystemunitdir="
-                                      %output "/lib/systemd/system")
+                                      (assoc-ref %outputs "out") "/lib/systemd/system")
                        (string-append "--with-systemdtmpfilesdir="
-                                      %output "/lib/tmpfiles.d"))
+                                      (assoc-ref %outputs "out") "/lib/tmpfiles.d"))
                  (map (lambda (prog)
                         (string-append "--with-" prog "=" groff-minimal
                                        "/bin/" prog))
diff --git a/gnu/packages/ntp.scm b/gnu/packages/ntp.scm
index 55b9a73b22..0d8c409b6e 100644
--- a/gnu/packages/ntp.scm
+++ b/gnu/packages/ntp.scm
@@ -159,7 +159,8 @@ time-stamping or reference clock, sub-microsecond accuracy is possible.")
             `(("libcap" ,libcap))
             '())))
    (arguments
-    `(#:phases
+    `(#:configure-flags (list "--with-yielding-select=yes")
+	  #:phases
       (modify-phases %standard-phases
         (add-after 'unpack 'disable-network-test
                    (lambda _
-- 
2.33.1
P
P
phodina wrote on 14 Apr 09:38 +0200
(name . 48314@debbugs.gnu.org)(address . 48314@debbugs.gnu.org)
1JV7YdNsB7LB0ij9pMN5ktIsdpU8g98Lpu0yOrl_r6wFvRjqRJ5XqOktugKlia2rSeyNVEwY0b8VJrFJr1TsWgOIo-JW6EmTpj6Bz4dNzxQ=@protonmail.com
Hi,

I've rebased the patches to latest master and fixed some conflicts.

However, I'm unable to build the system on my Pinebook (aarch64 for native build).

./pre-inst-env guix system build gnu/system/examples/raspberry-pi-64.tmpl
substitute: updating substitutes from 'https://ci.guix.gnu.org'...substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0%
substitute: updating substitutes from 'https://bordeaux.guix.gnu.osubstitute:updating substitutes from 'https://bordeaux.guix.gnu.org'... 100.0%
The following derivation will be built:
/gnu/store/p50i4lk8ajcgrgz8m11vqifvh4ggin2w-linux-libre-arm64-generic-5.16.19.drv
building /gnu/store/p50i4lk8ajcgrgz8m11vqifvh4ggin2w-linux-libre-arm64-generic-5.16.19.drv...
ice-9/read.scm:126:4: In procedure read-expr*:
/gnu/store/9gxgha6r0ab5g44mnb3rgyjkrhc709rq-linux-libre-arm64-generic-5.16.19-builder:1:3290: Unknown # object: "#<"
builder for `/gnu/store/p50i4lk8ajcgrgz8m11vqifvh4ggin2w-linux-libre-arm64-generic-5.16.19.drv' failed with exit code 1
build of /gnu/store/p50i4lk8ajcgrgz8m11vqifvh4ggin2w-linux-libre-arm64-generic-5.16.19.drv failed
View build log at '/var/log/guix/drvs/p5/0i4lk8ajcgrgz8m11vqifvh4ggin2w-linux-libre-arm64-generic-5.16.19.drv.gz'.guix system: error: build of `/gnu/store/p50i4lk8ajcgrgz8m11vqifvh4ggin2w-linux-libre-arm64-generic-5.16.19.drv' failed

Unfortunately the build log is not helpful uncovering the cause (at least to me).

I've also attempted to cross-compile the system (from x86_64) but there is at least one package that can't be build - guile-fibers-1.1.0. I've attached the build log as well.

Kind regards,
Petr
Attachment: file
From 13c3cf5f1df923eddcf48b69f0c26c7cfa2e6d4d Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:32 +0200
Subject: [PATCH v3 6/8] gnu: raspberry-pi: Add helpers for config.txt file
generation.

* gnu/packages/raspberry-pi.scm (raspi-config-file, raspi-custom-txt):
New functions.
(%raspi-config-txt, %raspi-bcm27-dtb-txt, %raspi-bcm28-dtb-txt
%raspi-u-boot-bootloader-txt): New variables.

Toggle diff (66 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index a2ab300531..0707516f72 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -238,6 +238,59 @@ (define-public raspi-arm64-chainloader
                #t))))))))
     (supported-systems '("aarch64-linux"))))
 
+(define-public (raspi-config-file name content)
+  "Make a configuration file like config.txt for the Raspberry Pi firmware.
+CONTENT can be a list of strings, which are concatenated with a newline
+character.  Alternatively CONTENT can be a string with the full file content."
+  (plain-file
+   name
+   (if (list? content)
+       (string-join content "\n" 'suffix)
+       content)))
+
+(define-public %raspi-config-txt
+  ;; A config.txt file to start the ARM cores up in 64-bit mode if necessary
+  ;; and to include a dtb.txt, bootloader.txt, and a custom.txt, each with
+  ;; separated configurations for the Raspberry Pi firmware.
+  (raspi-config-file
+   "config.txt"
+   `("# See https://www.raspberrypi.org/documentation/configuration/config-txt/README.md for details."
+     ""
+     ,(string-append "arm_64bit=" (if (target-aarch64?) "1" "0"))
+     "include dtb.txt"
+     "include bootloader.txt"
+     "include custom.txt")))
+
+(define-public %raspi-bcm27-dtb-txt
+  ;; A dtb.txt file to be included by the config.txt to ensure that the
+  ;; downstream device tree files bcm27*.dtb will be used.
+  (raspi-config-file
+   "dtb.txt"
+   "upstream_kernel=0"))
+
+(define-public %raspi-bcm28-dtb-txt
+  ;; A dtb.txt file to be included by the config.txt to ensure that the
+  ;; upstream device tree files bcm28*.dtb will be used.
+  ;; This also implies the use of the dtoverlay=upstream.
+  (raspi-config-file
+   "dtb.txt"
+   "upstream_kernel=1"))
+
+(define-public %raspi-u-boot-bootloader-txt
+  ;; A bootloader.txt file to be included by the config.txt to load the
+  ;; U-Boot bootloader.
+  (raspi-config-file
+   "bootloader.txt"
+   '("dtoverlay=upstream"
+     "enable_uart=1"
+     "kernel=u-boot.bin")))
+
+(define-public (raspi-custom-txt content)
+  "Make a custom.txt file for the Raspberry Pi firmware.
+CONTENT can be a list of strings, which are concatenated with a newline
+character.  Alternatively CONTENT can be a string with the full file content."
+  (raspi-config-file "custom.txt" content))
+
 (define (make-raspi-defconfig arch defconfig sha256-as-base32)
   "Make for the architecture ARCH a file-like object from the DEFCONFIG file
 with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
-- 
2.35.1
From 7b9aa4a57404d39f2aed940aef2026667bfca34e Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:02:07 +0200
Subject: [PATCH v3 1/8] gnu: bootloader: Rework chaining, add
grub-efi-netboot-removable-bootloader.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* doc/guix.texi (Bootloader Configuration): Describe the new
‘grub-efi-netboot-removable-bootloader’. Mention used sub-directories and
that the UEFI Boot Manager is not modified. Advice to disable write-access
over TFTP.
* gnu/bootloader.scm (efi-bootloader-profile): Allow a list of packages and
collect everything directly in the profile, avoiding a separate collection
directory. Renamed the profile from "bootloader-profile" to
"efi-bootloader-profile".
[bootloader-collection]: Renamed to …
[efi-bootloader-profile-hook]: … this and removed unused modules and the
creation of the now unneeded collection directory.
(efi-bootloader-chain): Added packages and disk-image-installer arguments.
Removed handling of the collection directory, now only calling the given
installer procedure.
* gnu/bootloader/grub.scm (make-grub-efi-netboot-installer): New helper.
(make-grub-configuration): New helper based on (grub-configuration-file).
Adding grub argument, fixed indentation, removend code to get grub.
(grub-configuration-file): Now using (make-grub-configuration).
(grub-efi-configuration-file): New function using (make-grub-configuration).
Instead of getting the grub-efi package from the bootloader-configuration
this function refers to the grub-efi package directly.
(grub-cfg): New variable to replace "/boot/grub/grub.cfg".
(install-grub-efi-netboot): Removed, the functionality got moved.
(make-grub-efi-netboot-installer): New helper function to return a customized
installer for a certain efi-sub-directory. The installer basically copies
a pre-installed efi-bootloader-profile, and adds needed symlinks for booting
over network, or – on an ESP – an intermediate grub-cfg to load the final
grub-cfg file.
(grub-bootloader): Now using the grub-cfg variable.
(grub-efi-bootloader): Now using the grub-cfg variable. Removed inheritance,
giving complete set of fields.
(make-grub-efi-netboot-bootloader): New helper function.
(grub-efi-netboot-bootloader): Now using the helper.
(grub-efi-netboot-removable-bootloader): New bootloader using the helper.
It uses the efi-sub-directory "efi/boot" for removable media.
* gnu/packages/bootloaders.scm (make-grub-efi-netboot): New function to return
a grub-efi package pre-installed via grub-mknetdir, customized for an
efi-sub-directory and able to boot via network and local storage.

The rework allows to use an (efi-bootloader-chain) like this, which is able
to boot over network or local storage, depending on the symlink-support at
the bootloader-target:

(operating-system
(bootloader
(bootloader-configuration
(bootloader
(efi-bootloader-chain
grub-efi-netboot-removable-bootloader
#:packages (list my-firmware-package
my-u-boot-package)
#:files (list (plain-file "config.txt"
"kernel=u-boot.bin"))
#:hooks my-special-bootloader-profile-manipulator))
(target "/booti/efi")
…))
…)
)

Toggle diff (688 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index a865b2e2e4..4b35142e95 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -35710,8 +35710,9 @@ The type of a bootloader configuration declaration.
 @cindex BIOS, bootloader
 The bootloader to use, as a @code{bootloader} object.  For now
 @code{grub-bootloader}, @code{grub-efi-bootloader},
-@code{grub-efi-netboot-bootloader}, @code{extlinux-bootloader} and
-@code{u-boot-bootloader} are supported.
+@code{grub-efi-netboot-bootloader},
+@code{grub-efi-netboot-removable-bootloader},
+@code{extlinux-bootloader} and @code{u-boot-bootloader} are supported.
 
 @cindex ARM, bootloaders
 @cindex AArch64, bootloaders
@@ -35737,9 +35738,10 @@ build a diskless Guix system.
 
 The installation of the @code{grub-efi-netboot-bootloader} generates the
 content of the TFTP root directory at @code{targets} (@pxref{Bootloader
-Configuration, @code{targets}}), to be served by a TFTP server.  You may
-want to mount your TFTP server directories onto the @code{targets} to
-move the required files to the TFTP server automatically.
+Configuration, @code{targets}}) below the sub-directory @file{efi/Guix}, to be
+served by a TFTP server.  You may want to mount your TFTP server directories
+onto the @code{targets} to move the required files to the TFTP server
+automatically during installation.
 
 If you plan to use an NFS root file system as well (actually if you mount the
 store from an NFS share), then the TFTP server needs to serve the file
@@ -35773,13 +35775,23 @@ directory to your @code{targets}.
 It is important to note that symlinks pointing outside the TFTP root directory
 may need to be allowed in the configuration of your TFTP server.  Further the
 store link exposes the whole store through TFTP@.  Both points need to be
-considered carefully for security aspects.
+considered carefully for security aspects.  It is advised to disable any TFTP
+write access!
+
+Please note, that this bootloader will not modify the ‘UEFI Boot Manager’ of
+the system.
 
 Beside the @code{grub-efi-netboot-bootloader}, the already mentioned TFTP and
 NFS servers, you also need a properly configured DHCP server to make the booting
 over netboot possible.  For all this we can currently only recommend you to look
 for instructions about @acronym{PXE, Preboot eXecution Environment}.
 
+@vindex grub-efi-netboot-removable-bootloader
+@code{grub-efi-netboot-removable-bootloader} is identical to
+@code{grub-efi-netboot-bootloader} with the exception that the sub-directory
+@file{efi/boot} will be used instead of @file{efi/Guix} to comply to the UEFI
+specification for removable media.
+
 @item @code{targets}
 This is a list of strings denoting the targets onto which to install the
 bootloader.
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index 9cf5457873..797908e24a 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -259,26 +259,22 @@ (define (lookup-bootloader-by-name name)
             (force %bootloaders))
       (leave (G_ "~a: no such bootloader~%") name)))
 
-(define (efi-bootloader-profile files bootloader-package hooks)
-  "Creates a profile with BOOTLOADER-PACKAGE and a directory collection/ with
-links to additional FILES from the store.  This collection is meant to be used
-by the bootloader installer.
+(define (efi-bootloader-profile packages files hooks)
+  "Creates a profile from the lists of PACKAGES and FILES from the store.
+This profile is meant to be used by the bootloader-installer.
 
 FILES is a list of file or directory names from the store, which will be
-symlinked into the collection/ directory.  If a directory name ends with '/',
-then the directory content instead of the directory itself will be symlinked
-into the collection/ directory.
+symlinked into the profile.  If a directory name ends with '/', then the
+directory content instead of the directory itself will be symlinked into the
+profile.
 
-FILES may contain file like objects produced by functions like plain-file,
+FILES may contain file like objects produced by procedures like plain-file,
 local-file, etc., or package contents produced with file-append.
 
 HOOKS lists additional hook functions to modify the profile."
-  (define (bootloader-collection manifest)
+  (define (efi-bootloader-profile-hook manifest)
     (define build
-        (with-imported-modules '((guix build utils)
-                                 (ice-9 ftw)
-                                 (srfi srfi-1)
-                                 (srfi srfi-26))
+        (with-imported-modules '((guix build utils))
           #~(begin
             (use-modules ((guix build utils)
                           #:select (mkdir-p strip-store-file-name))
@@ -302,7 +298,7 @@ (define name-ends-with-/? (cut string-suffix? "/" <>))
             (define (name-is-store-entry? name)
               "Return #t if NAME is a direct store entry and nothing inside."
               (not (string-index (strip-store-file-name name) #\/)))
-            (let* ((collection (string-append #$output "/collection"))
+            (let* ((output #$output)
                    (files '#$files)
                    (directories (filter name-ends-with-/? files))
                    (names-from-directories
@@ -311,11 +307,11 @@ (define (name-is-store-entry? name)
                                 directories))
                    (names (append names-from-directories
                                   (remove name-ends-with-/? files))))
-              (mkdir-p collection)
+              (mkdir-p output)
               (if (every file-exists? names)
                   (begin
                     (for-each (lambda (name)
-                               (symlink-to name collection
+                               (symlink-to name output
                                             (if (name-is-store-entry? name)
                                                 strip-store-file-name
                                                 basename)))
@@ -323,57 +319,63 @@ (define (name-is-store-entry? name)
                     #t)
                   #f)))))
 
-    (gexp->derivation "bootloader-collection"
+    (gexp->derivation "efi-bootloader-profile"
                       build
                       #:local-build? #t
                       #:substitutable? #f
                       #:properties
                       `((type . profile-hook)
-                        (hook . bootloader-collection))))
+                        (hook . efi-bootloader-profile-hook))))
 
-  (profile (content (packages->manifest (list bootloader-package)))
-           (name "bootloader-profile")
-           (hooks (append (list bootloader-collection) hooks))
+  (profile (content (packages->manifest packages))
+           (name "efi-bootloader-profile")
+           (hooks (cons efi-bootloader-profile-hook hooks))
            (locales? #f)
            (allow-collisions? #f)
            (relative-symlinks? #f)))
 
-(define* (efi-bootloader-chain files
-                               final-bootloader
+(define* (efi-bootloader-chain final-bootloader
                                #:key
+                               (packages '())
+                               (files '())
                                (hooks '())
-                               installer)
-  "Define a bootloader chain with FINAL-BOOTLOADER as the final bootloader and
-certain directories and files from the store given in the list of FILES.
+                               installer
+                               disk-image-installer)
+  "Define a chain of bootloaders with the FINAL-BOOTLOADER, optional PACKAGES,
+and optional directories and files from the store given in the list of FILES.
 
-FILES may contain file like objects produced by functions like plain-file,
-local-file, etc., or package contents produced with file-append.  They will be
-collected inside a directory collection/ inside a generated bootloader profile,
-which will be passed to the INSTALLER.
+The package of the FINAL-BOOTLOADER and all PACKAGES and FILES will be placed
+in an efi-bootloader-profile, which will be passed to the INSTALLER.
+
+FILES may contain file like objects produced by procedures like plain-file,
+local-file, etc., or package contents produced with file-append.
 
 If a directory name in FILES ends with '/', then the directory content instead
-of the directory itself will be symlinked into the collection/ directory.
+of the directory itself will be symlinked into the efi-bootloader-profile.
 
 The procedures in the HOOKS list can be used to further modify the bootloader
 profile.  It is possible to pass a single function instead of a list.
 
-If the INSTALLER argument is used, then this function will be called to install
-the bootloader.  Otherwise the installer of the FINAL-BOOTLOADER will be called."
-  (let* ((final-installer (or installer
-                              (bootloader-installer final-bootloader)))
-         (profile (efi-bootloader-profile files
-                                          (bootloader-package final-bootloader)
-                                          (if (list? hooks)
-                                              hooks
-                                              (list hooks)))))
-    (bootloader
-     (inherit final-bootloader)
-     (package profile)
-     (installer
-      #~(lambda (bootloader target mount-point)
-          (#$final-installer bootloader target mount-point)
-          (copy-recursively
-           (string-append bootloader "/collection")
-           (string-append mount-point target)
-           #:follow-symlinks? #t
-           #:log (%make-void-port "w")))))))
+If the INSTALLER argument is used, then this gexp procedure will be called to
+install the efi-bootloader-profile.  Otherwise the installer of the
+FINAL-BOOTLOADER will be called.
+
+If the DISK-IMAGE-INSTALLER is used, then this gexp procedure will be called
+to install the efi-bootloader-profile into a disk-image.  Otherwise the
+disk-image-installer of the FINAL-BOOTLOADER will be called."
+  (bootloader
+    (inherit final-bootloader)
+    (name "efi-bootloader-chain")
+    (package
+     (efi-bootloader-profile (cons (bootloader-package final-bootloader)
+                                   packages)
+                             files
+                             (if (list? hooks)
+                                 hooks
+                                 (list hooks))))
+    (installer
+     (or installer
+         (bootloader-installer final-bootloader)))
+    (disk-image-installer
+     (or disk-image-installer
+         (bootloader-disk-image-installer final-bootloader)))))
diff --git a/gnu/bootloader/grub.scm b/gnu/bootloader/grub.scm
index 120cd55012..0ba6aa4dad 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -50,11 +50,12 @@ (define-module (gnu bootloader grub)
             grub-theme-color-highlight
             grub-theme-gfxmode
 
-            install-grub-efi-netboot
+            make-grub-efi-netboot-installer
 
             grub-bootloader
             grub-efi-bootloader
             grub-efi-netboot-bootloader
+            grub-efi-netboot-removable-bootloader
             grub-mkrescue-bootloader
             grub-minimal-bootloader
 
@@ -348,7 +349,7 @@ (define (grub-root-search device file)
         ((or #f (? string?))
          #~(format #f "search --file --set ~a" #$file)))))
 
-(define* (grub-configuration-file config entries
+(define* (make-grub-configuration grub config entries
                                   #:key
                                   (locale #f)
                                   (system (%current-system))
@@ -378,27 +379,27 @@ (define (menu-entry->gexp entry)
                 (initrd (normalize-file (menu-entry-initrd entry)
                                         device-mount-point
                                         store-directory-prefix)))
-         ;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
-         ;; Use the right file names for LINUX and INITRD in case
-         ;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
-         ;; separate partition.
-
-         ;; When BTRFS-SUBVOLUME-FILE-NAME is defined, prepend it the linux and
-         ;; initrd paths, to allow booting from a Btrfs subvolume.
-         #~(format port "menuentry ~s {
+            ;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
+            ;; Use the right file names for LINUX and INITRD in case
+            ;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
+            ;; separate partition.
+
+            ;; When BTRFS-SUBVOLUME-FILE-NAME is defined, prepend it the linux and
+            ;; initrd paths, to allow booting from a Btrfs subvolume.
+            #~(format port "menuentry ~s {
   ~a
   linux ~a ~a
   initrd ~a
 }~%"
-                   #$label
-                   #$(grub-root-search device linux)
-                   #$linux (string-join (list #$@arguments))
-                   #$initrd))
+                      #$label
+                      #$(grub-root-search device linux)
+                      #$linux (string-join (list #$@arguments))
+                      #$initrd))
           (let ((kernel (menu-entry-multiboot-kernel entry))
                 (arguments (menu-entry-multiboot-arguments entry))
                 (modules (menu-entry-multiboot-modules entry))
                 (root-index 1))            ; XXX EFI will need root-index 2
-        #~(format port "
+            #~(format port "
 menuentry ~s {
   multiboot ~a root=device:hd0s~a~a~a
 }~%"
@@ -435,9 +436,7 @@ (define (sugar)
   (define locale-config
     (let* ((entry (first all-entries))
            (device (menu-entry-device entry))
-           (mount-point (menu-entry-device-mount-point entry))
-           (bootloader (bootloader-configuration-bootloader config))
-           (grub (bootloader-package bootloader)))
+           (mount-point (menu-entry-device-mount-point entry)))
       #~(let ((locale #$(and locale
                              (locale-definition-source
                               (locale-name->definition locale))))
@@ -463,8 +462,6 @@ (define locale-config
 
   (define keyboard-layout-config
     (let* ((layout (bootloader-configuration-keyboard-layout config))
-           (grub   (bootloader-package
-                    (bootloader-configuration-bootloader config)))
            (keymap* (and layout
                          (keyboard-layout-file layout #:grub grub)))
            (entry (first all-entries))
@@ -515,6 +512,16 @@ (define builder
                  #:options '(#:local-build? #t
                              #:substitutable? #f)))
 
+(define (grub-configuration-file config . args)
+  (let* ((bootloader (bootloader-configuration-bootloader config))
+         (grub (bootloader-package bootloader)))
+    (apply make-grub-configuration grub config args)))
+
+(define (grub-efi-configuration-file . args)
+  (apply make-grub-configuration grub-efi args))
+
+(define grub-cfg "/boot/grub/grub.cfg")
+
 
 
 ;;;
@@ -608,42 +615,31 @@ (define install-grub-efi
                         "--bootloader-id=Guix"
                         "--efi-directory" target-esp)))))
 
-(define (install-grub-efi-netboot subdir)
-  "Define a grub-efi-netboot bootloader installer for installation in SUBDIR,
-which is usually efi/Guix or efi/boot."
-  (let* ((system (string-split (nix-system->gnu-triplet
-                                (or (%current-target-system)
-                                    (%current-system)))
-                               #\-))
-         (arch (first system))
-         (boot-efi-link (match system
-                          ;; These are the supportend systems and the names
-                          ;; defined by the UEFI standard for removable media.
-                          (("i686" _ ...)        "/bootia32.efi")
-                          (("x86_64" _ ...)      "/bootx64.efi")
-                          (("arm" _ ...)         "/bootarm.efi")
-                          (("aarch64" _ ...)     "/bootaa64.efi")
-                          (("riscv" _ ...)       "/bootriscv32.efi")
-                          (("riscv64" _ ...)     "/bootriscv64.efi")
-                          ;; Other systems are not supported, although defined.
-                          ;; (("riscv128" _ ...) "/bootriscv128.efi")
-                          ;; (("ia64" _ ...)     "/bootia64.efi")
-                          ((_ ...)               #f)))
-         (core-efi (string-append
-                    ;; This is the arch dependent file name of GRUB, e.g.
-                    ;; i368-efi/core.efi or arm64-efi/core.efi.
-                    (match arch
-                      ("i686"    "i386")
-                      ("aarch64" "arm64")
-                      ("riscv"   "riscv32")
-                      (_         arch))
-                    "-efi/core.efi")))
-    (with-imported-modules
-     '((guix build union))
-     #~(lambda (bootloader target mount-point)
-         "Install the BOOTLOADER, which must be the package grub, as e.g.
-bootx64.efi or bootaa64.efi into SUBDIR, which is usually efi/Guix or efi/boot,
-below the directory TARGET for the system whose root is mounted at MOUNT-POINT.
+(define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
+  "Make a bootloader-installer for a grub-efi-netboot bootloader, which expects
+its files in SUBDIR and its configuration file in GRUB-CFG.
+
+As a grub-efi-netboot package is already preinstalled by 'grub-mknetdir', the
+installer basically copies all files from the bootloader-package (or profile)
+into the bootloader-target directory.
+
+Additionally for network booting over TFTP, two relative symlinks to the store
+and to the GRUB-CFG file are necessary.  Due to this a TFTP root directory must
+not be located on a FAT file-system.
+
+If the bootloader-target does not support symlinks, then it is assumed to be a
+kind of EFI System Partition (ESP).  In this case an intermediate configuration
+file is created with the help of GRUB-EFI to load the GRUB-CFG.
+
+The installer is usable for any efi-bootloader-chain, which prepares the
+bootloader-profile in a way ready for copying.
+
+The installer does not manipulate the system's 'UEFI Boot Manager'."
+  (with-imported-modules '((guix build union))
+    #~(lambda (bootloader target mount-point)
+        "Copy the BOOTLOADER, which must be a preinstalled grub-efi-netboot
+package with a SUBDIR like efi/boot or efi/Guix, below the directory
+TARGET for the system whose root is mounted at MOUNT-POINT.
 
 MOUNT-POINT is the last argument in 'guix system init /etc/config.scm mnt/point'
 or '/' for other 'guix system' commands.
@@ -653,17 +649,18 @@ (define (install-grub-efi-netboot subdir)
 
 (operating-system
  (bootloader (bootloader-configuration
-              (targets '(\"/boot\"))
+              (targets '(\"/boot/efi\"))
               …))
  …)
 
 TARGET is required to be an absolute directory name, usually mounted via NFS,
 and finally needs to be provided by a TFTP server as the TFTP root directory.
 
+Usually the installer will be used to prepare network booting over TFTP.  Then
 GRUB will load tftp://server/SUBDIR/grub.cfg and this file will instruct it to
 load more files from the store like tftp://server/gnu/store/…-linux…/Image.
 
-To make this possible two symlinks will be created. The first symlink points
+To make this possible two symlinks will be created.  The first symlink points
 relatively form MOUNT-POINT/TARGET/SUBDIR/grub.cfg to
 MOUNT-POINT/boot/grub/grub.cfg, and the second symlink points relatively from
 MOUNT-POINT/TARGET/%store-prefix to MOUNT-POINT/%store-prefix.
@@ -673,34 +670,78 @@ (define (install-grub-efi-netboot subdir)
 
 It is also important to note that both symlinks will point outside the TFTP root
 directory and that the TARGET/%store-prefix symlink makes the whole store
-accessible via TFTP. Possibly the TFTP server must be configured
-to allow accesses outside its TFTP root directory. This may need to be
-considered for security aspects."
-         (use-modules ((guix build union) #:select (symlink-relative)))
-         (let* ((net-dir (string-append mount-point target "/"))
-                (sub-dir (string-append net-dir #$subdir "/"))
-                (store (string-append mount-point (%store-prefix)))
-                (store-link (string-append net-dir (%store-prefix)))
-                (grub-cfg (string-append mount-point "/boot/grub/grub.cfg"))
-                (grub-cfg-link (string-append sub-dir (basename grub-cfg)))
-                (boot-efi-link (string-append sub-dir #$boot-efi-link)))
-           ;; Prepare the symlink to the store.
-           (mkdir-p (dirname store-link))
-           (false-if-exception (delete-file store-link))
-           (symlink-relative store store-link)
-           ;; Prepare the symlink to the grub.cfg, which points into the store.
-           (mkdir-p (dirname grub-cfg-link))
-           (false-if-exception (delete-file grub-cfg-link))
-           (symlink-relative grub-cfg grub-cfg-link)
-           ;; Install GRUB, which refers to the grub.cfg, with support for
-           ;; encrypted partitions,
-           (setenv "GRUB_ENABLE_CRYPTODISK" "y")
-           (invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
-                         (string-append "--net-directory=" net-dir)
-                         (string-append "--subdir=" #$subdir))
-           ;; Prepare the bootloader symlink, which points to core.efi of GRUB.
-           (false-if-exception (delete-file boot-efi-link))
-           (symlink #$core-efi boot-efi-link))))))
+accessible via TFTP.  Possibly the TFTP server must be configured to allow
+accesses outside its TFTP root directory.  This all may need to be considered
+for security aspects.  It is advised to disable any TFTP write access!
+
+The installer can also be used to prepare booting from local storages, if the
+underlying file-system, like FAT on an EFI System Partition (ESP), does not
+support symlinks.  In this case the MOUNT-POINT/TARGET/SUBDIR/grub.cfg will be
+created with the help of GRUB-EFI to load the /boot/grub/grub.cfg file.  A
+symlink to the store is not needed in this case."
+        ;; In context of a disk image creation TARGET will be #f and an
+        ;; installer is expected to do necessary installations on MOUNT-POINT,
+        ;; which will become the root file system.
+        ;; If TARGET is #f, this installer has nothing to do, as it only cares
+        ;; about the EFI System Partition (ESP).
+        (when target
+          (use-modules ((guix build union) #:select (symlink-relative))
+                       (ice-9 popen)
+                       (ice-9 rdelim))
+          (let* ((mount-point/target (string-append mount-point target "/"))
+                 ;; When installing Guix, it is common to mount TARGET below
+                 ;; MOUNT-POINT rather than the root directory.
+                 (bootloader-target (if (file-exists? mount-point/target)
+                                        mount-point/target
+                                        target))
+                 (store (string-append mount-point (%store-prefix)))
+                 (store-link (string-append bootloader-target (%store-prefix)))
+                 (grub-cfg (string-append mount-point #$grub-cfg))
+                 (grub-cfg-link (string-append bootloader-target
+                                               #$subdir "/"
+                                               (basename grub-cfg))))
+            ;; Copy the bootloader into the bootloader-target directory.
+            ;; Should we beforehand recursively delete any existing file?
+            (copy-recursively bootloader bootloader-target
+                              #:follow-symlinks? #t
+                              #:log (%make-void-port "w"))
+            ;; For TFTP we need to install additional relative symlinks.
+            ;; If we install on an EFI System Partition (ESP) or some other FAT
+            ;; file-system, then symlinks cannot be created and are not needed.
+            ;; Therefore we ignore exceptions when trying.
+            ;; Prepare the symlink to the grub.cfg.
+            (mkdir-p (dirname grub-cfg-link))
+            (false-if-exception (delete-file grub-cfg-link))
+            (if (unspecified?
+                (false-if-exception (symlink-relative grub-cfg grub-cfg-link)))
+              ;; Symlinks are supported.
+              (begin
+                ;; Prepare the symlink to the store.
+                (mkdir-p (dirname store-link))
+                (false-if-exception (delete-file store-link))
+                (symlink-relative store store-link))
+              ;; Creating symlinks does not seem to be supported.
+              ;; Probably an ESP is used.
+              ;; Instead we can script to search and load the actual grub.cfg.
+              (let* ((probe #$(file-append grub-efi "/sbin/grub-probe"))
+                     (port
+                       (open-pipe* OPEN_READ probe "--target=fs_uuid" grub-cfg))
+                     (search-root
+                       (match (read-line port)
+                         ((? eof-object?)
+                           ;; There is no UUID available. As a fallback search
+                           ;; everywhere for the grub.cfg.
+                           (string-append "search --file --set " #$grub-cfg))
+                         (fs-uuid
+                           ;; The UUID to load the grub.cfg from is known.
+                           (string-append "search --fs-uuid --set " fs-uuid))))
+                     (load-grub-cfg (string-append "configfile " #$grub-cfg)))
+                (close-pipe port)
+                (with-output-to-file grub-cfg-link
+                  (lambda ()
+                    (display (string-join (list search-root
+                                                load-grub-cfg)
+                                          "\n")))))))))))
 
 
 
@@ -718,7 +759,7 @@ (define grub-bootloader
    (package grub)
    (installer install-grub)
    (disk-image-installer install-grub-disk-image)
-   (configuration-file "/boot/grub/grub.cfg")
+   (configuration-file grub-cfg)
    (configuration-file-generator grub-configuration-file)))
 
 (define grub-minimal-bootloader
@@ -728,17 +769,29 @@ (define grub-minimal-bootloader
 
 (define grub-efi-bootloader
   (bootloader
-   (inherit grub-bootloader)
+   (name 'grub-efi)
+   (package grub-efi)
    (installer install-grub-efi)
    (disk-image-installer #f)
-   (name 'grub-efi)
-   (package grub-efi)))
+   (configuration-file grub-cfg)
+   (configuration-file-generator grub-configuration-file)))
 
-(define grub-efi-netboot-bootloader
+(define (make-grub-efi-netboot-bootloader name subdir)
   (bootloader
-   (inherit grub-efi-bootloader)
-   (name 'grub-efi-netboot-bootloader)
-   (installer (install-grub-efi-netboot "efi/Guix"))))
+   (name name)
+   (package (make-grub-efi-netboot (symbol->string name) subdir))
+   (installer (make-grub-efi-netboot-installer grub-efi grub-cfg subdir))
+   (disk-image-installer #f)
+   (configuration-file grub-cfg)
+   (configuration-file-generator grub-efi-configuration-file)))
+
+(define grub-efi-netboot-bootloader
+  (make-grub-efi-netboot-bootloader 'grub-efi-netboot-bootloader
+                                    "efi/Guix"))
+
+(define grub-efi-netboot-removable-bootloader
+  (make-grub-efi-netboot-bootloader 'grub-efi-netboot-removable-bootloader
+                                    "efi/boot"))
 
 (define grub-mkrescue-bootloader
   (bootloader
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 7ea6f5a647..6876ab17b9 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -15,6 +15,7 @@
 ;;; Copyright © 2020, 2021 Pierre Langlois <pierre.langlois@gmx.com>
 ;;; Copyright © 2021 Vincent Legoll <vincent.legoll@gmail.com>
 ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -66,13 +67,17 @@ (define-module (gnu packages bootloaders)
   #:use-module (gnu packages virtualization)
   #:use-module (gnu packages xorg)
   #:use-module (guix build-system gnu)
+  #:use-module (guix build-system trivial)
   #:use-module (guix download)
+  #:use-module (guix gexp)
   #:use-module (guix git-download)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix packages)
   #:use-module (guix utils)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26)
+  #:use-module (ice-9 match)
+  #:use-module (ice-9 optargs)
   #:use-module (ice-9 regex))
 
 (define unifont
@@ -366,6 +371,91 @@ (define-public grub-hybrid
                   (scandir input-dir))
                  #t)))))))))
 
+(define-public (make-grub-efi-netboot name subdir)
+  "Make a grub-efi-netboot package named NAME, which will be able to boot over
+network via TFTP by accessing its files in the SUBDIR of a TFTP root directory.
+This package is also able to boot from local storage devices.
+
+A bootloader-installer basically needs to copy the package content into the
+bootloader-target directory, which will usually be the TFTP root, as
+'grub-mknetdir' will be invoked already during the package creation.
+
+Alternatively the bootloader-target directory can be a mounted EFI System
+Partition (ESP), or a similar partition with a FAT file system, for booting
+from local storage devices.
+
+The name of the GRUB EFI binary will conform to the UEFI specification for
+removable media.  Depending on the system it will be e.g. bootx64.efi or
+bootaa64.efi below SUBDIR.
+
+The SUBDIR argument needs to be set to \"efi/boot\" to create a package which
+conforms to the UEFI specification for removable media.
+
+The SUBDIR argument defaults to \"efi/Guix\", as it is also the case for
+'grub-efi-bootloader'."
+  (package
+    (name name)
+    (version (package-version grub-efi))
+    ;; Source is not needed, but it cannot be omitted.
+    (source #f)
+    (build-system trivial-build-system)
+    (arguments
+     (let* ((system (string-split (nix-system->gnu-triplet
+                                  (or (%current-target-system)
+                                      (%current-system)))
+                                  #\-))
+            (arch (first system))
+            (boot-efi
+             (match system
+               ;; These are the supportend systems and the names defined by
+               ;; the UEFI standard for removable media.
+               (("i686" _ ...)        "/bootia32.efi")
+               (("x86_64" _ ...)      "/bootx64.efi")
+               (("arm" _ ...)         "/bootarm.efi")
+               (("aarch64" _ ...)     "/bootaa64.efi")
+               (("riscv" _ ...)       "/bootriscv32.efi")
+               (("riscv64" _ ...)     "/bootriscv64.efi")
+               ;; Other systems are not supported, although defined.
+               ;; (("riscv128" _ ...) "/bootriscv128.efi")
+               ;; (("ia64" _ ...)     "/bootia64.efi")
+               ((_ ...)               #f)))
+            (core-efi (string-append
+                       ;; This is the arch dependent file name of GRUB, e.g.
+                       ;; i368-efi/core.efi or arm64-efi/core.efi.
+                       (match arch
+                         ("i686"    "i386")
+                         ("aarch64" "arm64")
+                         ("riscv"   "riscv32")
+                         (_         arch))
+                       "-efi/core.efi")))
+       `(#:modules ((guix build utils))
+         #:builder
+         (begin
+           (use-modules (guix build utils))
+           (let* ((bootloader (assoc-ref %build-inputs "grub-efi"))
+                  (net-dir (assoc-ref %outputs "out"))
+                  (sub-dir (string-append net-dir "/" ,subdir "/"))
+                  (boot-efi (string-append sub-dir ,boot-efi))
+                  (core-efi (string-append sub-dir ,core-efi)))
+             ;; Install GRUB, which refers to the grub.cfg, with support for
+             ;; encrypted partitions,
+             (setenv "GRUB_ENABLE_CRYPTODISK" "y")
+             (invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
+                           (string-append "--net-directory=" net-dir)
+                           (string-append "--subdir=" ,subdir)
+                           ;; These modules must be preloaded to allow booting
+                           ;; from an ESP or a similar partition with a FAT
+                           ;; file system.
+                           (string-append "--modules=part_msdos part_gpt fat"))
+             ;; Move GRUB's core.efi to the removable media name.
+             (false-if-exception (delete-file boot-efi))
+             (rename-file core-efi boot-efi))))))
+    (inputs `(("grub-efi" ,grub-efi)))
+    (synopsis (package-synopsis grub-efi))
+    (description (package-description grub-efi))
+    (home-page (package-home-page grub-efi))
+    (license (package-license grub-efi))))
+
 (define-public syslinux
   (let ((commit "bb41e935cc83c6242de24d2271e067d76af3585c"))
     (package
-- 
2.35.1
From f6e01db0581ad7c291a20f5a8b15bd5925ba70af Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:11:20 +0200
Subject: [PATCH v3 3/8] gnu: bootloader: Add U-Boot packages for Raspberry Pi
models.

* gnu/packages/bootloader.scm (make-u-boot-package): Add keyword
parameters 'name' and 'description'.
(make-preinstalled-u-boot-package): New function to make minimal packages.
(%u-boot-rpi-efi-configs): New helper list with config strings.
(%u-boot-rpi-description-32-bit, %u-boot-rpi-description-64-bit,
%u-boot-rpi-efi-description, %u-boot-rpi-efi-description-32-bit): New helper
strings.
(u-boot-rpi-0-w, u-boot-rpi, u-boot-rpi-2, u-boot-rpi-3, u-boot-rpi-4,
u-boot-rpi-64, u-boot-rpi-0-w-efi, u-boot-rpi-efi, u-boot-rpi-2-efi,
u-boot-rpi-3-efi, u-boot-rpi-4-efi, u-boot-rpi-efi-64): New packages.

Toggle diff (199 lines)
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 10f2dd5fad..84d65c94cd 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -748,17 +748,30 @@ (define-public u-boot-tools
 also initializes the boards (RAM etc).  This package provides its
 board-independent tools.")))
 
-(define*-public (make-u-boot-package board triplet #:key defconfig configs)
+(define*-public (make-u-boot-package board
+                                     triplet
+                                     #:key
+                                     defconfig
+                                     configs
+                                     name
+                                     description)
   "Returns a u-boot package for BOARD cross-compiled for TRIPLET with the
-optional DEFCONFIG file and optional configuration changes from CONFIGS."
+optional DEFCONFIG file and optional configuration changes from CONFIGS.
+Either NAME, if used, or otherwise BOARD will be part of the package name.
+DESCRIPTION will be appended to the package description."
   (let ((same-arch? (lambda ()
                       (string=? (%current-system)
                                 (gnu-triplet->nix-system triplet)))))
     (package
       (inherit u-boot)
       (name (string-append "u-boot-"
-                           (string-replace-substring (string-downcase board)
-                                                     "_" "-")))
+                           (string-replace-substring
+                            (string-downcase (or name board))
+                            "_" "-")))
+      (description (if description
+                       (string-append (package-description u-boot)
+                                      "\n" description)
+                       (package-description u-boot)))
       (native-inputs
        `(,@(if (not (same-arch?))
              `(("cross-gcc" ,(cross-gcc triplet))
@@ -1117,6 +1130,157 @@ (define-public u-boot-pinebook-pro-rk3399
        `(("firmware" ,arm-trusted-firmware-rk3399)
          ,@(package-native-inputs base))))))
 
+(define*-public (make-preinstalled-u-boot-package board
+                                                  triplet
+                                                  #:key
+                                                  defconfig
+                                                  configs
+                                                  name
+                                                  description
+                                                  (u-boot-file "u-boot.bin"))
+  "Returns a package with a single U-BOOT-FILE for BOARD cross-compiled for
+TRIPLET with the optional DEFCONFIG file and optional configuration changes
+from CONFIGS.  Either NAME, if used, or otherwise BOARD will be part of the
+package name.  DESCRIPTION will be appended to the package description."
+  (let* ((name-suffix "-complete")
+         (u-boot-package (make-u-boot-package board
+                                              triplet
+                                              #:defconfig defconfig
+                                              #:configs configs
+                                              #:name (string-append
+                                                      (or name board)
+                                                      name-suffix)
+                                              #:description description)))
+    (package
+      (name (string-drop-right (package-name u-boot-package)
+                               (string-length name-suffix)))
+      (version (package-version u-boot-package))
+      (source #f)
+      (build-system trivial-build-system)
+      (arguments
+       `(#:builder
+         (begin
+           (let ((out (assoc-ref %outputs "out")))
+             (mkdir out)
+             (symlink (string-append (assoc-ref %build-inputs "u-boot")
+                                   "/libexec/"
+                                   ,u-boot-file)
+                      (string-append out "/" ,u-boot-file))))))
+      (inputs `(("u-boot" ,u-boot-package)))
+      (home-page (package-home-page u-boot-package))
+      (synopsis (package-synopsis u-boot-package))
+      (description (package-description u-boot-package))
+      (license (package-license u-boot-package)))))
+
+(define-public %u-boot-rpi-efi-configs
+  '("CONFIG_OF_EMBED="
+    "CONFIG_OF_BOARD=y"
+    "CONFIG_BOOTDELAY=0"))
+
+(define %u-boot-rpi-description-32-bit
+  "This is a 32-bit build of U-Boot.")
+
+(define %u-boot-rpi-description-64-bit
+  "This is a common 64-bit build of U-Boot for all 64-bit capable Raspberry Pi
+variants.")
+
+(define %u-boot-rpi-efi-description
+  "It allows network booting and uses the device-tree from the firmware,
+allowing the usage of overlays.  It can act as an EFI firmware for the
+grub-efi-netboot-removable-bootloader.")
+
+(define %u-boot-rpi-efi-description-32-bit
+  (string-append %u-boot-rpi-efi-description "  "
+                 %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-0-w
+  (make-preinstalled-u-boot-package
+   "rpi_0_w"
+   "arm-linux-gnueabihf"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi
+  (make-preinstalled-u-boot-package
+   "rpi"
+   "arm-linux-gnueabihf"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-2
+  (make-preinstalled-u-boot-package
+   "rpi_2"
+   "arm-linux-gnueabihf"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-3
+  (make-preinstalled-u-boot-package
+   "rpi_3_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-3"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-4
+  (make-preinstalled-u-boot-package
+   "rpi_4_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-4"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-64
+  (make-preinstalled-u-boot-package
+   "rpi_arm64"
+   "aarch64-linux-gnu"
+   #:name "rpi-64"
+   #:description %u-boot-rpi-description-64-bit))
+
+(define-public u-boot-rpi-0-w-efi
+  (make-preinstalled-u-boot-package
+   "rpi_0_w"
+   "arm-linux-gnueabihf"
+   #:name "rpi-0-w-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-efi
+  (make-preinstalled-u-boot-package
+   "rpi"
+   "arm-linux-gnueabihf"
+   #:name "rpi-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-2-efi
+  (make-preinstalled-u-boot-package
+   "rpi_2"
+   "arm-linux-gnueabihf"
+   #:name "rpi-2-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-3-efi
+  (make-preinstalled-u-boot-package
+   "rpi_3_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-3-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-4-efi
+  (make-preinstalled-u-boot-package
+   "rpi_4_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-4-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-efi-64
+  (make-preinstalled-u-boot-package
+   "rpi_arm64"
+   "aarch64-linux-gnu"
+   #:name "rpi-efi-64"
+   #:configs %u-boot-rpi-efi-configs
+   #:description (string-append %u-boot-rpi-efi-description "  "
+                                %u-boot-rpi-description-64-bit)))
+
 (define-public vboot-utils
   (package
     (name "vboot-utils")
-- 
2.35.1
From e0020032e80181eaad4c92d2c7641cd14f2b533f Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:41 +0200
Subject: [PATCH v3 8/8] gnu: raspberry-pi: Add a bootloader-chain for the
Raspberry Pi and os examples.

* gnu/packages/raspberry-pi.scm (grub-efi-bootloader-chain-raspi-64): New
bootloader variable, capable to boot a Raspberry Pi over network or from a
local storage.
* gnu/system/examples/raspberry-pi-64.tmpl: New operating-system example.
* gnu/system/examples/raspberry-pi-64-nfs-root.tmpl: New operating-system
example for booting over network.

Toggle diff (206 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index d808f61ac2..d52a4a72c5 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -18,11 +18,14 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu packages raspberry-pi)
+  #:use-module (gnu bootloader)
+  #:use-module (gnu bootloader grub)
   #:use-module (gnu packages)
   #:use-module (gnu packages admin)
   #:use-module (gnu packages algebra)
   #:use-module (gnu packages base)
   #:use-module (gnu packages bash)
+  #:use-module (gnu packages bootloaders)
   #:use-module (gnu packages commencement)
   #:use-module (gnu packages cross-base)
   #:use-module (gnu packages documentation)
@@ -312,6 +315,22 @@ (define-public (make-raspi-bcm28-dtbs linux)
      (simple-format #f "The device-tree files for Raspberry Pi models from ~a."
              (package-name linux)))))
 
+(define-public grub-efi-bootloader-chain-raspi-64
+  ;; A bootloader capable to boot a Raspberry Pi over network via TFTP or from
+  ;; a local storage like a micro SD card.
+  ;; It neither installs firmware nor device-tree files for the Raspberry Pi.
+  ;; It just assumes them to be existing in boot/efi in the same way that some
+  ;; UEFI firmware with ACPI data is usually assumed to be existing on PCs.
+  ;; It creates firmware configuration files and a bootloader-chain with U-Boot
+  ;; to provide an EFI API for the final GRUB bootloader.
+  ;; It also serves as a blue-print to create an own bootloader-chain with
+  ;; firmwre and device-tree packages or files.
+  (efi-bootloader-chain grub-efi-netboot-removable-bootloader
+                        #:packages (list u-boot-rpi-efi-64)
+                        #:files (list %raspi-config-txt
+                                      %raspi-bcm27-dtb-txt
+                                      %raspi-u-boot-bootloader-txt)))
+
 (define (make-raspi-defconfig arch defconfig sha256-as-base32)
   "Make for the architecture ARCH a file-like object from the DEFCONFIG file
 with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
diff --git a/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl b/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
new file mode 100644
index 0000000000..c006a287fb
--- /dev/null
+++ b/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
@@ -0,0 +1,73 @@
+;; This is an operating-system configuration template of a
+;; 64-bit minimal system for a Raspberry Pi with an NFS root file-system.
+
+;; It neither installs firmware nor device-tree files for the Raspberry Pi.
+;; It just assumes them to be existing in boot/efi in the same way that some
+;; UEFI firmware with ACPI data is usually assumed to be existing on PCs.
+
+;; It expects the boot/efi directory to be served via TFTP and the root
+;; file-system to be served via NFS. See the grub-efi-netboot-bootloader
+;; description in the manual for more details.
+
+(use-modules (gnu)
+             (gnu artwork)
+             (gnu system nss))
+(use-service-modules admin
+                     avahi
+                     networking
+                     ssh)
+(use-package-modules certs
+                     linux
+                     raspberry-pi
+                     ssh)
+
+(define %my-public-key
+  (local-file (string-append (getenv "HOME") "/.ssh/id_ecdsa.pub")))
+
+(define-public raspberry-pi-64-nfs-root
+  (operating-system
+   (host-name "raspberrypi-guix")
+   (timezone "Europe/Berlin")
+   (bootloader (bootloader-configuration
+                (bootloader grub-efi-bootloader-chain-raspi-64)
+                (targets '("/boot/efi"))
+                (theme (grub-theme (resolution '(1920 . 1080))
+                       (image (file-append
+                               %artwork-repository
+                               "/grub/GuixSD-fully-black-16-9.svg"))))))
+   (kernel-arguments '("ip=dhcp"))
+   (kernel (modify-linux #:linux linux-libre-arm64-generic
+                         #:extra-version "arm64-generic-netboot"
+                         #:configs '("CONFIG_NFS_SWAP=y"
+                                     "CONFIG_USB_USBNET=y"
+                                     "CONFIG_USB_LAN78XX=y"
+                                     "CONFIG_USB_NET_SMSC95XX=y")))
+   (initrd-modules '())
+   (file-systems (cons* (file-system
+                         (mount-point "/")
+                         (type "nfs")
+                         (device ":/export/raspberrypi/guix")
+                         (options "addr=10.20.30.40,vers=4.1"))
+                        %base-file-systems))
+   (swap-devices (list (swap-space (target "/run/swapfile"))))
+   (users (cons* (user-account
+                  (name "pi")
+                  (group "users")
+                  (supplementary-groups '("wheel" "netdev" "audio" "video"))
+                  (home-directory "/home/pi"))
+                 %base-user-accounts))
+   (packages (cons* nss-certs
+                    openssh
+                    %base-packages))
+   (services (cons* (service avahi-service-type)
+                    (service dhcp-client-service-type)
+                    (service ntp-service-type)
+                    (service openssh-service-type
+                             (openssh-configuration
+                              (x11-forwarding? #t)
+                              (authorized-keys
+                              `(("pi" ,%my-public-key)))))
+                    %base-services))
+   (name-service-switch %mdns-host-lookup-nss)))
+
+raspberry-pi-64-nfs-root
diff --git a/gnu/system/examples/raspberry-pi-64.tmpl b/gnu/system/examples/raspberry-pi-64.tmpl
new file mode 100644
index 0000000000..6b0178c861
--- /dev/null
+++ b/gnu/system/examples/raspberry-pi-64.tmpl
@@ -0,0 +1,77 @@
+;; This is an operating-system configuration template of a
+;; 64-bit minimal system for a Raspberry Pi with local storage.
+
+;; It neither installs firmware nor device-tree files for the Raspberry Pi.
+;; It just assumes them to be existing in boot/efi in the same way that some
+;; UEFI firmware with ACPI data is usually assumed to be existing on PCs.
+
+;; It expects the boot-partition to be mounted as boot/efi in the same way
+;; as it is usually expeted on PCs with UEFI firmware.
+
+(use-modules (gnu)
+             (gnu artwork)
+             (gnu system nss))
+(use-service-modules admin
+                     avahi
+                     networking
+                     ssh)
+(use-package-modules certs
+                     linux
+                     raspberry-pi
+                     ssh)
+
+(define %my-public-key
+  (local-file (string-append (getenv "HOME") "/.ssh/id_ecdsa.pub")))
+
+(define-public raspberry-pi-64
+  (operating-system
+   (host-name "raspberrypi-guix")
+   (timezone "Europe/Berlin")
+   (bootloader (bootloader-configuration
+                (bootloader grub-efi-bootloader-chain-raspi-64)
+                (targets '("/boot/efi"))
+                (theme (grub-theme (resolution '(1920 . 1080))
+                       (image (file-append
+                               %artwork-repository
+                               "/grub/GuixSD-fully-black-16-9.svg"))))))
+   (kernel (modify-linux #:linux linux-libre-arm64-generic
+                         #| It is possible to use a specific defconfig file,
+                            for example the "bcmrpi3_defconfig" with the
+                            variable shown below.  Unfortunately the kernel
+                            build from the linux-libre sources with this
+                            defconfig file does not boot.
+                            #:extra-version "gnu-bcmrpi3"
+                            #:defconfig %bcmrpi3-defconfig
+                         |#))
+   (initrd-modules '())
+   (file-systems (cons* (file-system
+                         (mount-point "/")
+                         (type "ext4")
+                         (device (file-system-label "Guix")))
+                        (file-system
+                         (mount-point "/boot/efi")
+                         (type "vfat")
+                         (device (file-system-label "EFI")))
+                        %base-file-systems))
+   (swap-devices (list (swap-space (target "/run/swapfile"))))
+   (users (cons* (user-account
+                  (name "pi")
+                  (group "users")
+                  (supplementary-groups '("wheel" "netdev" "audio" "video"))
+                  (home-directory "/home/pi"))
+                 %base-user-accounts))
+   (packages (cons* nss-certs
+                    openssh
+                    %base-packages))
+   (services (cons* (service avahi-service-type)
+                    (service dhcp-client-service-type)
+                    (service ntp-service-type)
+                    (service openssh-service-type
+                             (openssh-configuration
+                              (x11-forwarding? #t)
+                              (authorized-keys
+                              `(("pi" ,%my-public-key)))))
+                    %base-services))
+   (name-service-switch %mdns-host-lookup-nss)))
+
+raspberry-pi-64
-- 
2.35.1
From 4bcedf553998e4c413b572395679d2d881fb7318 Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:36 +0200
Subject: [PATCH v3 7/8] gnu: raspberry-pi: New function to make a package with
device-tree files.

* gnu/packages/raspberry-pi.scm (make-raspi-bcm28-dtbs): New function to make
a package with device-tree files for Raspberry Pi models from the kernel given
as argument.

Toggle diff (41 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 0707516f72..d808f61ac2 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -30,6 +30,7 @@ (define-module (gnu packages raspberry-pi)
   #:use-module (gnu packages file)
   #:use-module (gnu packages gcc)
   #:use-module (gnu packages linux)
+  #:use-module (guix build-system copy)
   #:use-module (guix build-system gnu)
   #:use-module (guix download)
   #:use-module (guix git-download)
@@ -291,6 +292,26 @@ (define-public (raspi-custom-txt content)
 character.  Alternatively CONTENT can be a string with the full file content."
   (raspi-config-file "custom.txt" content))
 
+(define-public (make-raspi-bcm28-dtbs linux)
+  "Make a package with the device-tree files for Raspberry Pi models from the
+kernel LINUX."
+  (package
+    (inherit linux)
+    (name "raspi-bcm28-dtbs")
+    (source #f)
+    (build-system copy-build-system)
+    (arguments
+     `(#:phases (modify-phases %standard-phases (delete 'unpack))
+       #:install-plan
+       (list (list (string-append (assoc-ref %build-inputs "linux")
+                                  "/lib/dtbs/broadcom/")
+                   "." #:include-regexp '("/bcm....-rpi.*\\.dtb")))))
+    (inputs `(("linux" ,linux)))
+    (synopsis "Device-tree files for a Raspberry Pi")
+    (description
+     (simple-format #f "The device-tree files for Raspberry Pi models from ~a."
+             (package-name linux)))))
+
 (define (make-raspi-defconfig arch defconfig sha256-as-base32)
   "Make for the architecture ARCH a file-like object from the DEFCONFIG file
 with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
-- 
2.35.1
From a235d7564715cca1cec774d9d515caf1bccb4856 Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Wed, 13 Apr 2022 21:10:19 +0200
Subject: [PATCH v3 2/8] build: kconfig: Add new module to modify a defconfig
file.

From: Stefan <stefan-guix@vodafonemail.de>

* guix/build/kconfig.scm (modify-defconfig): New file with a new function.
* gnu/packages/bootloaders.scm (make-u-boot-package,
make-u-boot-sunxi64-package): Adding new key arguments to pass and/or modify
a defconfig file.
(u-boot-am335x-boneblack, u-boot-pinebook, u-boot-novena): Simplify functions
by using the new key arguments of the former functions.
* Makefile.am: Adding guix/build/kconfig.scm to MODULES.

Toggle diff (326 lines)
diff --git a/Makefile.am b/Makefile.am
index fecce7c6f7..7f69aacbd1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -223,6 +223,7 @@ MODULES =					\
   guix/build/waf-build-system.scm		\
   guix/build/haskell-build-system.scm		\
   guix/build/julia-build-system.scm		\
+  guix/build/kconfig.scm                        \
   guix/build/linux-module-build-system.scm	\
   guix/build/store-copy.scm			\
   guix/build/json.scm				\
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 6876ab17b9..10f2dd5fad 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -16,6 +16,7 @@
 ;;; Copyright © 2021 Vincent Legoll <vincent.legoll@gmail.com>
 ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
 ;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
+;;; Copyright © 2022 Petr Hodina <phodina@protonmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -747,8 +748,9 @@ (define-public u-boot-tools
 also initializes the boards (RAM etc).  This package provides its
 board-independent tools.")))
 
-(define-public (make-u-boot-package board triplet)
-  "Returns a u-boot package for BOARD cross-compiled for TRIPLET."
+(define*-public (make-u-boot-package board triplet #:key defconfig configs)
+  "Returns a u-boot package for BOARD cross-compiled for TRIPLET with the
+optional DEFCONFIG file and optional configuration changes from CONFIGS."
   (let ((same-arch? (lambda ()
                       (string=? (%current-system)
                                 (gnu-triplet->nix-system triplet)))))
@@ -766,8 +768,11 @@ (define-public (make-u-boot-package board triplet)
       (arguments
        `(#:modules ((ice-9 ftw)
                     (srfi srfi-1)
-                    (guix build utils)
-                    (guix build gnu-build-system))
+                    (guix build gnu-build-system)
+                    (guix build kconfig)
+                    (guix build utils))
+         #:imported-modules (,@%gnu-build-system-modules
+                             (guix build kconfig))
          #:test-target "test"
          #:make-flags
          (list "HOSTCC=gcc"
@@ -778,9 +783,18 @@ (define-public (make-u-boot-package board triplet)
          (modify-phases %standard-phases
            (replace 'configure
              (lambda* (#:key outputs make-flags #:allow-other-keys)
-               (let ((config-name (string-append ,board "_defconfig")))
-                 (if (file-exists? (string-append "configs/" config-name))
-                     (apply invoke "make" `(,@make-flags ,config-name))
+               (let* ((config-name (string-append ,board "_defconfig"))
+                      (config-file (string-append "configs/" config-name))
+                      (defconfig ,defconfig)
+                      (configs ',configs))
+                 (when defconfig
+                   ;; Replace the board-specific defconfig with the given one.
+                   (copy-file defconfig config-file))
+                 (if (file-exists? config-file)
+                     (begin
+                       (when configs
+                         (modify-defconfig config-file configs))
+                       (apply invoke "make" `(,@make-flags ,config-name)))
                      (begin
                        (display "Invalid board name. Valid board names are:"
                                 (current-error-port))
@@ -834,7 +848,11 @@ (define-public u-boot-malta
   (make-u-boot-package "malta" "mips64el-linux-gnuabi64"))
 
 (define-public u-boot-am335x-boneblack
-  (let ((base (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf")))
+  (let ((base (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"
+               ;; Patch out other device trees to build image small enough to
+               ;; fit within typical partitioning schemes where the first
+               ;; partition begins at sector 2048.
+               #:configs '("CONFIG_OF_LIST=\"am335x-evm am335x-boneblack\""))))
     (package
       (inherit base)
       (name "u-boot-am335x-boneblack")
@@ -843,25 +861,13 @@ (define-public u-boot-am335x-boneblack
 
 This U-Boot is built for the BeagleBone Black, which was removed upstream,
 adjusted from the am335x_evm build with several device trees removed so that
-it fits within common partitioning schemes.")
-      (arguments
-       (substitute-keyword-arguments (package-arguments base)
-         ((#:phases phases)
-          `(modify-phases ,phases
-             (add-after 'unpack 'patch-defconfig
-               ;; Patch out other devicetrees to build image small enough to
-               ;; fit within typical partitioning schemes where the first
-               ;; partition begins at sector 2048.
-               (lambda _
-                 (substitute* "configs/am335x_evm_defconfig"
-                   (("CONFIG_OF_LIST=.*$") "CONFIG_OF_LIST=\"am335x-evm am335x-boneblack\"\n"))
-                 #t)))))))))
+it fits within common partitioning schemes."))))
 
 (define-public u-boot-am335x-evm
   (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"))
 
-(define-public (make-u-boot-sunxi64-package board triplet)
-  (let ((base (make-u-boot-package board triplet)))
+(define*-public (make-u-boot-sunxi64-package board triplet #:key defconfig configs)
+  (let ((base (make-u-boot-package board triplet #:defconfig defconfig #:configs configs)))
     (package
       (inherit base)
       (arguments
@@ -891,20 +897,10 @@ (define-public u-boot-pine64-lts
   (make-u-boot-sunxi64-package "pine64-lts" "aarch64-linux-gnu"))
 
 (define-public u-boot-pinebook
-  (let ((base (make-u-boot-sunxi64-package "pinebook" "aarch64-linux-gnu")))
-    (package
-      (inherit base)
-      (arguments
-       (substitute-keyword-arguments (package-arguments base)
-         ((#:phases phases)
-          `(modify-phases ,phases
-             (add-after 'unpack 'patch-pinebook-config
-               ;; Fix regression with LCD video output introduced in 2020.01
-               ;; https://patchwork.ozlabs.org/patch/1225130/
-               (lambda _
-                 (substitute* "configs/pinebook_defconfig"
-                   (("CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y") "CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y\nCONFIG_VIDEO_BPP32=y"))
-                 #t)))))))))
+  (make-u-boot-sunxi64-package "pinebook" "aarch64-linux-gnu"
+   ;; Fix regression with LCD video output introduced in 2020.01
+   ;; https://patchwork.ozlabs.org/patch/1225130/
+   #:configs '("CONFIG_VIDEO_BPP32=y")))
 
 (define-public u-boot-bananapi-m2-ultra
   (make-u-boot-package "Bananapi_M2_Ultra" "arm-linux-gnueabihf"))
@@ -955,25 +951,17 @@ (define-public u-boot-mx6cuboxi
   (make-u-boot-package "mx6cuboxi" "arm-linux-gnueabihf"))
 
 (define-public u-boot-novena
-  (let ((base (make-u-boot-package "novena" "arm-linux-gnueabihf")))
+  (let ((base (make-u-boot-package "novena" "arm-linux-gnueabihf"
+               ;; Patch configuration to disable loading u-boot.img from FAT
+               ;; partition, allowing it to be installed at a device offset.
+               #:configs '("CONFIG_SPL_FS_FAT="))))
     (package
       (inherit base)
       (description "U-Boot is a bootloader used mostly for ARM boards.  It
 also initializes the boards (RAM etc).
 
 This U-Boot is built for Novena.  Be advised that this version, contrary
-to Novena upstream, does not load u-boot.img from the first partition.")
-      (arguments
-       (substitute-keyword-arguments (package-arguments base)
-         ((#:phases phases)
-          `(modify-phases ,phases
-             (add-after 'unpack 'patch-novena-defconfig
-               ;; Patch configuration to disable loading u-boot.img from FAT partition,
-               ;; allowing it to be installed at a device offset.
-               (lambda _
-                 (substitute* "configs/novena_defconfig"
-                   (("CONFIG_SPL_FS_FAT=y") "# CONFIG_SPL_FS_FAT is not set"))
-                 #t)))))))))
+to Novena upstream, does not load u-boot.img from the first partition."))))
 
 (define-public u-boot-cubieboard
   (make-u-boot-package "Cubieboard" "arm-linux-gnueabihf"))
diff --git a/guix/build/kconfig.scm b/guix/build/kconfig.scm
new file mode 100644
index 0000000000..09ddf59dd0
--- /dev/null
+++ b/guix/build/kconfig.scm
@@ -0,0 +1,148 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2020 Stefan <stefan-guix@vodafonemail.de>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (guix build kconfig)
+  #:use-module  (ice-9 rdelim)
+  #:use-module  (ice-9 regex)
+  #:use-module  (srfi srfi-1)
+  #:use-module  (srfi srfi-26)
+  #:export (modify-defconfig))
+
+;; Commentary:
+;;
+;; Builder-side code to modify configurations for the Kconfig build system as
+;; used by Linux and U-Boot.
+;;
+;; Code:
+
+(define (modify-defconfig defconfig configs)
+  "This function can modify a given DEFCONFIG file by adding, changing or
+removing the list of strings in CONFIGS.  This allows an easy customization of
+Kconfig based projects like the kernel Linux or the bootloader 'Das U-Boot'.
+
+These are examples for CONFIGS to add or change or remove
+configurations to/from DEFCONFIG:
+
+'(\"CONFIG_A=\\\"a\\\"\"
+  \"CONFIG_B=0\"
+  \"CONFIG_C=y\"
+  \"CONFIG_D=m\"
+  \"CONFIG_E=\"
+  \"CONFIG_F\"
+  \"# CONFIG_G is not set\")
+
+Instead of a list, CONFGIS can be a string with one configuration per line."
+  (define config-rx
+    (make-regexp
+     ;; (match:substring (string-match "=(.*)" "=") 1) returns "", but the
+     ;; pattern "=(.+)?" makes it return #f instead.  For a "CONFIG_A=" we like
+     ;; to get #f, which as a value emits "# … is not set".
+     "^(#[\\t ]*)?(CONFIG_[A-Z0-9_]+)([\\t ]*=[\\t ]*(.+)?|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
+
+  (define (config-string->pair config-string)
+    "Parse a config-string like \"CONFIG_EXAMPLE=y\" into a key-value pair.
+Spaces get trimmed.
+\"CONFIG_A=y\"            -> '(\"CONFIG_A\" . \"y\")
+\"CONFIG_B=\\\"\\\"\"         -> '(\"CONFIG_B\" . \"\\\"\\\"\")
+\"CONFIG_C=\"             -> '(\"CONFIG_C\" . #f)
+\"CONFIG_D\"              -> '(\"CONFIG_D\" . #f)
+\"# CONFIG_E is not set\" -> '(\"CONFIG_E\" . #f)
+\"# Anything else\"       -> '(\"# Anything else\" . \"\")"
+    (let ((match (regexp-exec config-rx (string-trim-both config-string))))
+      (if (not match)
+          ;; This is some unparsable config-string.
+          ;; We keep it as it is.
+          (cons config-string "")
+          (let* ((comment (match:substring match 1))
+                 (key (match:substring match 2))
+                 (unset (match:substring match 5))
+                 (value (and (not comment)
+                             (not unset)
+                             (match:substring match 4))))
+            (if (or (and comment (not unset))
+                    (and (not comment) unset))
+                ;; This is just some comment or strange line, which we keep as is.
+                (cons config-string "")
+                (cons key value))))))
+
+  (define (pair->config-string pair)
+    "Convert a PAIR back to a config-string."
+    (let* ((key (car pair))
+           (value (cdr pair)))
+      (if (string? value)
+          (if (string-null? value)
+              key
+              (string-append key "=" value))
+          (string-append "# " key " is not set"))))
+
+  (define (remove-pair pair blacklist)
+    "Turn a key-value PAIR into '("" . ""), if its key is listed in BLACKLIST."
+    (let* ((key (first pair)))
+      (if (member key blacklist)
+          '("" . "")
+          pair)))
+
+  (define (remove-config-string config-string blacklist)
+    "Remove the CONFIG-STRING, if its key is listed in BLACKLIST."
+    (pair->config-string (remove-pair (config-string->pair config-string)
+                                       blacklist)))
+
+  (define* (write-lines input #:key (line-modifier identity))
+    "Write all lines from the INPUT after applying the LINE-MODIFIER to the
+ current-output-port."
+    (let loop ((line (read-line input)))
+      (when (not (eof-object? line))
+        (display (line-modifier line))
+        (newline)
+        (loop (read-line input)))))
+
+  (let* ((modified-defconfig (string-append defconfig ".mod"))
+         ;; Split the configs into a list of single configuations.
+         ;; To minimize mistakes, we support a string and a list of strings,
+         ;; each with newlines to separate configurations.
+         (config-list (fold-right append '()
+                                  (map (lambda (s)
+                                         (string-split s #\newline))
+                                       (if (string? configs)
+                                           (list configs)
+                                           configs))))
+         ;; Generate key-value pairs from the config-list.
+         (pairs (map (lambda (config-string)
+                       (config-string->pair config-string))
+                     config-list))
+         ;; Generate a blacklist of config keys from pairs.
+         (blacklist (map (lambda (config-pair)
+                           (first config-pair))
+                         pairs))
+         (remove-config-string (cut remove-config-string <> blacklist)))
+    ;; Write to the modified-defconfig file first the content of the defconfig
+    ;; file with removed lines, and afterwards the configs.
+    (call-with-output-file modified-defconfig
+      (lambda (output)
+        (with-output-to-port output
+          (lambda ()
+            (call-with-input-file defconfig
+              (lambda (input)
+                (write-lines input #: line-modifier remove-config-string)))
+            (call-with-input-string
+              (string-join (map pair->config-string pairs) "\n")
+              (lambda (input)
+                (write-lines input)))))))
+    ;; Ensure the modified-defconfig file is used.
+    (delete-file defconfig)
+    (rename-file modified-defconfig defconfig)))
-- 
2.35.1
From 753f08b87878508da768891fa7371094401bea88 Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:25 +0200
Subject: [PATCH v3 5/8] gnu: raspberry-pi: Add defconfig objects to build
customized Linux kernels.

gnu/packages/raspberry-pi.scm (make-raspi-defconig): New function to make
downloaded defconfig objects from the Linux repository of the Raspberry Pi
Foundation.
(%bcm2709-defconfig, %bcm2710-defconfig, %bcm2711-defconfig,
%bcm2835-defconfig, %bcmrpi-defconfig, %bcm2711-defconfig-64,
%bcmrpi3-defconfig): New variables containing defconfig objects to build
Linux kernels customized for Raspberry Pi single board computers.

Toggle diff (69 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index bb38b8b218..a2ab300531 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -25,9 +26,10 @@ (define-module (gnu packages raspberry-pi)
   #:use-module (gnu packages commencement)
   #:use-module (gnu packages cross-base)
   #:use-module (gnu packages documentation)
+  #:use-module (gnu packages embedded)
   #:use-module (gnu packages file)
   #:use-module (gnu packages gcc)
-  #:use-module (gnu packages embedded)
+  #:use-module (gnu packages linux)
   #:use-module (guix build-system gnu)
   #:use-module (guix download)
   #:use-module (guix git-download)
@@ -235,3 +237,43 @@ (define-public raspi-arm64-chainloader
                (install-file "arm64.bin" libexec)
                #t))))))))
     (supported-systems '("aarch64-linux"))))
+
+(define (make-raspi-defconfig arch defconfig sha256-as-base32)
+  "Make for the architecture ARCH a file-like object from the DEFCONFIG file
+with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
+argument of the function (modify-linux)."
+  (make-defconfig
+   (string-append
+    "https://raw.githubusercontent.com/raspberrypi/linux/raspberrypi-kernel_1.20210430-1/arch/"
+    arch "/configs/" defconfig)
+   sha256-as-base32))
+
+(define-public %bcm2709-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2709_defconfig"
+   "0yvrmid2jakl929d1mv00gidnqbf91ffhj61c9gl75f7km48811c"))
+
+(define-public %bcm2711-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2711_defconfig"
+   "19hb6nwna7sk3b4rn5yjfhldrs3c1lv24q08w4gpa4xzh1byv7jj"))
+
+(define-public %bcm2835-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2835_defconfig"
+   "17dmvabqvxwqn6lgv1x8rfh2wqf1r2xmm10nkdnrgwkmgv8bh2d5"))
+
+(define-public %bcmrpi-defconfig
+  (make-raspi-defconfig
+   "arm" "bcmrpi_defconfig"
+   "0lcmr6nxdd53m3k8hqb5k6c5b7vbdgmfvcliqyl95snp45rxjjkw"))
+
+(define-public %bcm2711-defconfig-64
+  (make-raspi-defconfig
+   "arm64" "bcm2711_defconfig"
+   "0xf38nczwinr0j8vhsn8nd8h4ysjn77xphg7xnssz04gclb7fndr"))
+
+(define-public %bcmrpi3-defconfig
+  (make-raspi-defconfig
+   "arm64" "bcmrpi3_defconfig"
+   "01k098snd7kbmhz68j93mj2fwp39c56g9r8rgaw17js5r0w0zbhy"))
-- 
2.35.1
From 1b05398ed9e7adb1fa8822c5d22ebff66bf4f8d8 Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Wed, 13 Apr 2022 21:18:37 +0200
Subject: [PATCH v3 4/8] gnu: linux: New function to modify the configuration
of a Linux kernel.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

From: Stefan <stefan-guix@vodafonemail.de>

* gnu/packages/linux.scm (system->linux-srcarch): New function to return the
relevent folder name below arch/ in the Linux source code.
(make-linux-libre*) ['set-environment]: Splitted this new phase out of and
adding it before …
['configure]: … to allow a replacement and reuse from (modify-linux).
(modify-linux): New function to make a customized Linux package inherited
from another Linux package, which will be build with an own defconfig or
configuration changes.
(make-defconfig): Function to get a defconfig from an uri.

Toggle diff (179 lines)
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index a405837bb1..48c7797095 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -59,7 +59,8 @@
 ;;; Copyright © 2021 Josselin Poiret <josselin.poiret@protonmail.ch>
 ;;; Copyright © 2021 Olivier Dion <olivier.dion@polymtl.ca>
 ;;; Copyright © 2021 Solene Rapenne <solene@perso.pw>
-;;; Copyright © 2021 Petr Hodina <phodina@protonmail.com>
+;;; Copyright © 2021, 2022 Petr Hodina <phodina@protonmail.com>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;; Copyright © 2022 Artyom V. Poptsov <poptsov.artyom@gmail.com>
 
 ;;;
@@ -179,6 +180,7 @@ (define-module (gnu packages linux)
   #:use-module (srfi srfi-2)
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
+  #:use-module (ice-9 optargs)
   #:use-module (ice-9 regex))
 
 (define-public (system->linux-architecture arch)
@@ -195,6 +197,21 @@ (define-public (system->linux-architecture arch)
           ((string-prefix? "riscv" arch) "riscv")
           (else arch))))
 
+(define-public (system->linux-srcarch arch)
+  "Return for a Guix system ARCH name the SRCARCH name, which is set in the
+toplevel Makefile of Linux and denotes the architecture specific directory name
+below arch/ in its source code.  Some few architectures share a common folder.
+It resembles the definition of SRCARCH based on ARCH in the Makefile and may
+be used to place a defconfig file in the proper path."
+  (let ((linux-arch (system->linux-architecture arch)))
+    (match linux-arch
+      ("i386"    "x86")
+      ("x86_64"  "x86")
+      ("sparc32" "sparc")
+      ("sparc64" "sparc")
+      ("sh64"    "sh")
+      (_         linux-arch))))
+
 (define-public (system->defconfig system)
   "Some systems (notably powerpc-linux) require a special target for kernel
 defconfig.  Return the appropriate make target if applicable, otherwise return
@@ -852,7 +869,7 @@ (define* (make-linux-libre* version gnu-revision source supported-systems
                  (lambda _
                    (substitute* (find-files "." "^Makefile(\\.include)?$")
                      (("/bin/pwd") "pwd"))))
-               (replace 'configure
+               (add-before 'configure 'set-environment
                  (lambda* (#:key inputs target #:allow-other-keys)
                    ;; Avoid introducing timestamps.
                    (setenv "KCONFIG_NOTIMESTAMP" "1")
@@ -877,8 +894,10 @@ (define* (make-linux-libre* version gnu-revision source supported-systems
 
                    (setenv "EXTRAVERSION"
                            #$(and extra-version
-                                  (string-append "-" extra-version)))
+                                  (string-append "-" extra-version)))))
 
+               (replace 'configure
+                 (lambda* (#:key inputs native-inputs #:allow-other-keys)
                    (let ((build  (assoc-ref %standard-phases 'build))
                          (config (assoc-ref inputs "kconfig")))
 
@@ -1210,6 +1229,111 @@ (define-public linux-libre-with-bpf
       (inputs (modify-inputs (package-inputs base-linux-libre)
                 (prepend cpio))))))
 
+
+;;;
+;;; Linux kernel customization functions.
+;;;
+
+(define*-public (modify-linux #:key name
+                                    (linux linux-libre)
+                                    source
+                                    defconfig
+                                    (configs "")
+                                    extra-version)
+  "Make a Linux package NAME as a modification of another LINUX package.
+
+If NAME is not given, then it defaults to the same name as the LINUX package.
+
+Unless SOURCE is given the source of LINUX is used.
+
+A DEFCONFIG file to be used can be given as a package, as a file like object
+(file-append, local-file etc.), or as a string with the name of a defconfig file
+available in the Linux sources.  If DEFCONFIG is not given, then a defconfig
+file will be saved from the LINUX package configuration.
+
+Additional CONFIGS will be used to modify the given or saved defconfig, which
+will finally be used to build Linux.
+
+CONFIGS can be a list of strings, with one configuration per line.  The usual
+defconfig syntax has to be used, but there is a special extension to ease the
+removal of configurations.  Comment lines are supported as well.
+
+Here is an explaining usage example:
+
+  '(;; This string defines the version tail in 'uname -r'.
+    \"CONFIG_LOCALVERSION=\\\"-handcrafted\\\"
+    ;; This '# CONFIG_… is not set' syntax has to match exactly!
+    \"# CONFIG_BOOT_CONFIG is not set\"
+    \"CONFIG_NFS_SWAP=y\"
+    ;; This is a multiline configuration:
+    \"CONFIG_E1000=y
+# This is a comment, below follow two special removal extensions:
+CONFIG_CMDLINE_EXTEND
+CONFIG_CMDLINE_FORCE=\")
+
+A string of configurations instead of a list of configuration strings is also
+possible.
+
+EXTRA-VERSION can be a string overwriting the EXTRAVERSION setting of the LINUX
+package, after being prepended by a hyphen.  It will be visible in the output
+of 'uname -r' behind the Linux version numbers."
+  (package
+    (inherit linux)
+    (name (or name (package-name linux)))
+    (source (or source (package-source linux)))
+    (arguments
+     (substitute-keyword-arguments
+         (package-arguments linux)
+       ((#:imported-modules imported-modules %gnu-build-system-modules)
+        `((guix build kconfig) ,@imported-modules))
+       ((#:modules modules)
+        `((guix build kconfig) ,@modules))
+       ((#:phases phases)
+        `(modify-phases ,phases
+           (replace 'configure
+             (lambda* (#:key inputs #:allow-other-keys #:rest arguments)
+               (let* ((srcarch
+                       ,(system->linux-srcarch (or (%current-target-system)
+                                                   (%current-system))))
+                      (configs (string-append "arch/" srcarch "/configs/"))
+                      (guix_defconfig (string-append configs "guix_defconfig")))
+                 ,(cond
+                   ((not defconfig)
+                    `(begin
+                       ;; Call the original 'configure phase.
+                       (apply (assoc-ref ,phases 'configure) arguments)
+                       ;; Save a defconfig file.
+                       (invoke "make" "savedefconfig")
+                       ;; Move the saved defconfig to the proper location.
+                       (rename-file "defconfig"
+                                    guix_defconfig)))
+                   ((string? defconfig)
+                    ;; Use another existing defconfig from the Linux sources.
+                    `(rename-file (string-append configs ,defconfig)
+                                  guix_defconfig))
+                   (else
+                    ;; Copy the defconfig input to the proper location.
+                    '(copy-file (assoc-ref inputs "guix_defconfig")
+                                guix_defconfig)))
+                 (modify-defconfig guix_defconfig ',configs)
+                 ,@(if extra-version
+                       `((setenv "EXTRAVERSION"
+                                 ,(string-append "-" extra-version)))
+                       '())
+                 (invoke "make" "guix_defconfig"))
+               #t))))))
+    (native-inputs
+     (append (if (or (not defconfig)
+                     (string? defconfig))
+                 '()
+                 ;; The defconfig should be a package or file-like object.
+                 `(("guix_defconfig" ,defconfig)))
+             (package-native-inputs linux)))))
+
+(define-public (make-defconfig uri sha256-as-base32)
+  (origin (method url-fetch)
+          (uri uri)
+          (sha256 (base32 sha256-as-base32))))
 
 
 ;;;
-- 
2.35.1
P
P
phodina wrote on 14 Apr 10:17 +0200
(name . 48314@debbugs.gnu.org)(address . 48314@debbugs.gnu.org)(name . Mathieu Othacehe)(address . othacehe@gnu.org)
kzaSyP3anBK_UepIv1m2HCrjWqwFsOMMpqDr6IQM78N1aXE830WieMzsKig_2_uAv62__6979fCV1u4sP89z_QemjSZcti_ObfUXtYh1i6I=@protonmail.com
The issue about guile-fibers has already been reported by Mathieu in https://issues.guix.gnu.org/54793.
Attachment: file
M
M
Maxime Devos wrote on 14 Apr 10:32 +0200
b661d9b6c7b44262285f544110b335ef02e6a402.camel@telenet.be
phodina via Guix-patches via schreef op do 14-04-2022 om 07:38 [+0000]:
Toggle quote (3 lines)
> +        `(modify-phases ,phases
> +           (replace 'configure

To get rid of the #< error, replace this by

#~(modify-phases #$phases [...])

(and replace the , by #$ etc).

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYlfcBhccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7i0LAQDHNIkMs5ghMgBdkexsD667Vw2d
EAfoulacRDM/f9sdlAD9EPPBL/frt5P44zoPs+9vNLyVvWbhrxupPbxRwvUldwM=
=h5dT
-----END PGP SIGNATURE-----


P
P
phodina wrote on 14 Apr 11:25 +0200
[PATCH v4] Install guix system on Raspberry Pi
(name . 48314@debbugs.gnu.org)(address . 48314@debbugs.gnu.org)
zMqJOXxxdBE_tlTtNY-q9vjI2_uBFY36RprO1tJWhHBh9S6NO4l46DHNOjHgM5GXf3SxAbC4tR27tN3sUZWS9Y69U70BGtc47McF0TE5Gaw=@protonmail.com
Toggle quote (14 lines)
>
> > +        `(modify-phases ,phases
> > +           (replace 'configure
>
>
> To get rid of the #< error, replace this by
>
> #~(modify-phases #$phases [...])
>
> (and replace the , by #$ etc).
>
> Greetings,
> Maxime.

Thanks for the suggestion Maxime. Here's patch with fixes where I attempt to rewrite the section of the code using Gexps.

Still it ends in error as there is some mistake in the Gexps I made.

$ ./pre-inst-env guix system build gnu/system/examples/raspberry-pi-64.tmpl
;;; note: source file /home/cpethod/guix/gnu/packages/linux.scm
;;; newer than compiled /home/pethod/guix/gnu/packages/linux.go
substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0%
substitute: updating substitutes from 'https://bordeaux.guix.gnu.org'... 100.0%
The following derivation will be built:
/gnu/store/zvy703ldgicckqgnggsnz0a21394hb9f-linux-libre-arm64-generic-5.16.19.drv
building /gnu/store/zvy703ldgicckqgnggsnz0a21394hb9f-linux-libre-arm64-generic-5.16.19.drv...
ice-9/psyntax.scm:2794:12: In procedure syntax-violation:
Syntax error:
/gnu/store/2xjp40qfmrdjg28zqsd919cjg00n9wrv-linux-libre-arm64-generic-5.16.19-builder:1:3387: source expression failed to match any pattern in form (let* ((srcarch #{$#}# (system->linux-srcarch (or (%current-target-system) (%current-system)))) (configs (string-append "arch/" srcarch "/configs/")) (guix_defconfig (string-append configs "guix_defconfig"))) #{$#}# (cond ((not defconfig) $~ (begin (apply (assoc-ref #{$#phases}# (quote configure)) arguments) (invoke "make" "savedefconfig") (rename-file "defconfig" guix_defconfig))) ((string? defconfig) $~ (rename-file (string-append configs #{$#defconfig}#) guix_defconfig)) (else (quote (copy-file (assoc-ref inputs "guix_defconfig") guix_defconfig)))) (modify-defconfig guix_defconfig (quote #{$#configs}#)) #{$#@}# (if extra-version $~ ((setenv "EXTRAVERSION" #{$#}# (string-append "-" extra-version))) (quote ())) (invoke "make" "guix_defconfig"))
builder for `/gnu/store/zvy703ldgicckqgnggsnz0a21394hb9f-linux-libre-arm64-generic-5.16.19.drv' failed with exit code 1
build of /gnu/store/zvy703ldgicckqgnggsnz0a21394hb9f-linux-libre-arm64-generic-5.16.19.drv failed
View build log at '/var/log/guix/drvs/zv/y703ldgicckqgnggsnz0a21394hb9f-linux-libre-arm64-generic-5.16.19.drv.gz'.
guix system: error: build of `/gnu/store/zvy703ldgicckqgnggsnz0a21394hb9f-linux-libre-arm64-generic-5.16.19.drv' failed


----
Petr
From 57643003418f13d49e45582ef2a6d25de6b36595 Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Thu, 14 Apr 2022 11:18:27 +0200
Subject: [PATCH v4] Attempt to fix modify-linux procedure using Gexp.


Toggle diff (52 lines)
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 61dac905f8..e1ad6069f8 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -1293,15 +1293,15 @@ (define*-public (modify-linux #:key name
            (replace 'configure
              (lambda* (#:key inputs #:allow-other-keys #:rest arguments)
                (let* ((srcarch
-                       ,(system->linux-srcarch (or (%current-target-system)
+                       $#(system->linux-srcarch (or (%current-target-system)
                                                    (%current-system))))
                       (configs (string-append "arch/" srcarch "/configs/"))
                       (guix_defconfig (string-append configs "guix_defconfig")))
-                 ,(cond
+                 $#(cond
                    ((not defconfig)
-                    `(begin
+                    $~(begin
                        ;; Call the original 'configure phase.
-                       (apply (assoc-ref ,phases 'configure) arguments)
+                       (apply (assoc-ref $#phases 'configure) arguments)
                        ;; Save a defconfig file.
                        (invoke "make" "savedefconfig")
                        ;; Move the saved defconfig to the proper location.
@@ -1309,19 +1309,18 @@ (define*-public (modify-linux #:key name
                                     guix_defconfig)))
                    ((string? defconfig)
                     ;; Use another existing defconfig from the Linux sources.
-                    `(rename-file (string-append configs ,defconfig)
+                    $~(rename-file (string-append configs $#defconfig)
                                   guix_defconfig))
                    (else
                     ;; Copy the defconfig input to the proper location.
                     '(copy-file (assoc-ref inputs "guix_defconfig")
                                 guix_defconfig)))
-                 (modify-defconfig guix_defconfig ',configs)
-                 ,@(if extra-version
-                       `((setenv "EXTRAVERSION"
-                                 ,(string-append "-" extra-version)))
+                 (modify-defconfig guix_defconfig '$#configs)
+                 $#@(if extra-version
+                       $~((setenv "EXTRAVERSION"
+                                 $#(string-append "-" extra-version)))
                        '())
-                 (invoke "make" "guix_defconfig"))
-               #t))))))
+                 (invoke "make" "guix_defconfig"))))))))
     (native-inputs
      (append (if (or (not defconfig)
                      (string? defconfig))
-- 
2.34.0
M
M
Maxime Devos wrote on 14 Apr 13:00 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
86d36088dc4c81112e1529ef9e5e46d6629912c1.camel@telenet.be
phodina schreef op do 14-04-2022 om 09:25 [+0000]:
Toggle quote (5 lines)
>                 (let* ((srcarch
> -                       ,(system->linux-srcarch (or (%current-target-
> system)
> +                       $#(system->linux-srcarch (or (%current-

it's #$, not $#

Toggle quote (10 lines)
> target-system)
>                                                     (%current-
> system))))
>                        (configs (string-append "arch/" srcarch
> "/configs/"))
>                        (guix_defconfig (string-append configs
> "guix_defconfig")))
> -                 ,(cond
> +                 $#(cond

likewise

Toggle quote (4 lines)
>                     ((not defconfig)
> -                    `(begin
> +                    $~(begin

in this case #~

Toggle quote (6 lines)
>                         ;; Call the original 'configure phase.
> -                       (apply (assoc-ref ,phases 'configure)
> arguments)
> +                       (apply (assoc-ref $#phases 'configure)
> arguments)

#$

Toggle quote (12 lines)
>                         ;; Save a defconfig file.
>                         (invoke "make" "savedefconfig")
>                         ;; Move the saved defconfig to the proper
> location.
> @@ -1309,19 +1309,18 @@ (define*-public (modify-linux #:key name
>                                      guix_defconfig)))
>                     ((string? defconfig)
>                      ;; Use another existing defconfig from the Linux
> sources.
> -                    `(rename-file (string-append configs ,defconfig)
> +                    $~(rename-file (string-append configs
> $#defconfig)
#~ and #$
Toggle quote (14 lines)
>                                    guix_defconfig))
>                     (else
>                      ;; Copy the defconfig input to the proper
> location.
>                      '(copy-file (assoc-ref inputs "guix_defconfig")
>                                  guix_defconfig)))
> -                 (modify-defconfig guix_defconfig ',configs)
> -                 ,@(if extra-version
> -                       `((setenv "EXTRAVERSION"
> -                                 ,(string-append "-" extra-
> version)))
> +                 (modify-defconfig guix_defconfig '$#configs)
> +                 $#@(if extra-version

#$@

Toggle quote (1 lines)
> +                       $~((setenv "EXTRAVERSION"
#~
Toggle quote (2 lines)
> +                                 $#(string-append "-" extra-
> version)))
#$
Toggle quote (5 lines)
>                         '())
> -                 (invoke "make" "guix_defconfig"))
> -               #t))))))
> +                 (invoke "make" "guix_defconfig"))))))))

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iIwEABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYlf+yRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7vjOAPiLQIbSbZWQ4u8TsroNzUGmygNb
38PfdrlyJInZzsouAP448hA1mAdb1vFTcIu/QZClOHmYmxdnJ5ZhTiNk+jwKBA==
=oobI
-----END PGP SIGNATURE-----


P
P
phodina wrote on 14 Apr 14:23 +0200
[PATCH v5] Install guix system on Raspberry Pi
(name . Maxime Devos)(address . maximedevos@telenet.be)
j-6Mh97olCgYy-HTnXD1Wddae1w06eUlRPTw9m2QCxidzQeWs7nIp9EBjGrtgSdImIddGLbRv6mI9cwKeFr5Y9KiaOQfVsMVmFy1DXbQ3I4=@protonmail.com
Thanks Maxime,

sorry for silly mistake.

Here are the updated patches. The last changes are part of the 4th patch in the patch set.

After build I installed it to the SD card using following command:

sudo -E ./pre-inst-env guix system init gnu/system/examples/raspberry-pi-64.tmpl /mnt

However, I experience an issue when login into the system. I can get there using my SSH key, but it seems the passwd set-uid binary is missing from the profile:

$ ssh pi@192.168.1.181
You are required to change your password immediately (administrator enforced).
WARNING: Your password has expired.
passwd: no such file or directory

I understand that the password is not set and the account is accessed through SSH so it asks after login to change it. How come it's possible to change it? I tried to add shadow into the packages, but the error said, it's already part of the system, so my guess is that it's just missing in the PATH variable. Could it be due to the fact it's present in /run/setuid-programs?

----
Petr
From 7b9aa4a57404d39f2aed940aef2026667bfca34e Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:02:07 +0200
Subject: [PATCH v5 1/8] gnu: bootloader: Rework chaining, add
grub-efi-netboot-removable-bootloader.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* doc/guix.texi (Bootloader Configuration): Describe the new
‘grub-efi-netboot-removable-bootloader’. Mention used sub-directories and
that the UEFI Boot Manager is not modified. Advice to disable write-access
over TFTP.
* gnu/bootloader.scm (efi-bootloader-profile): Allow a list of packages and
collect everything directly in the profile, avoiding a separate collection
directory. Renamed the profile from "bootloader-profile" to
"efi-bootloader-profile".
[bootloader-collection]: Renamed to …
[efi-bootloader-profile-hook]: … this and removed unused modules and the
creation of the now unneeded collection directory.
(efi-bootloader-chain): Added packages and disk-image-installer arguments.
Removed handling of the collection directory, now only calling the given
installer procedure.
* gnu/bootloader/grub.scm (make-grub-efi-netboot-installer): New helper.
(make-grub-configuration): New helper based on (grub-configuration-file).
Adding grub argument, fixed indentation, removend code to get grub.
(grub-configuration-file): Now using (make-grub-configuration).
(grub-efi-configuration-file): New function using (make-grub-configuration).
Instead of getting the grub-efi package from the bootloader-configuration
this function refers to the grub-efi package directly.
(grub-cfg): New variable to replace "/boot/grub/grub.cfg".
(install-grub-efi-netboot): Removed, the functionality got moved.
(make-grub-efi-netboot-installer): New helper function to return a customized
installer for a certain efi-sub-directory. The installer basically copies
a pre-installed efi-bootloader-profile, and adds needed symlinks for booting
over network, or – on an ESP – an intermediate grub-cfg to load the final
grub-cfg file.
(grub-bootloader): Now using the grub-cfg variable.
(grub-efi-bootloader): Now using the grub-cfg variable. Removed inheritance,
giving complete set of fields.
(make-grub-efi-netboot-bootloader): New helper function.
(grub-efi-netboot-bootloader): Now using the helper.
(grub-efi-netboot-removable-bootloader): New bootloader using the helper.
It uses the efi-sub-directory "efi/boot" for removable media.
* gnu/packages/bootloaders.scm (make-grub-efi-netboot): New function to return
a grub-efi package pre-installed via grub-mknetdir, customized for an
efi-sub-directory and able to boot via network and local storage.

The rework allows to use an (efi-bootloader-chain) like this, which is able
to boot over network or local storage, depending on the symlink-support at
the bootloader-target:

(operating-system
(bootloader
(bootloader-configuration
(bootloader
(efi-bootloader-chain
grub-efi-netboot-removable-bootloader
#:packages (list my-firmware-package
my-u-boot-package)
#:files (list (plain-file "config.txt"
"kernel=u-boot.bin"))
#:hooks my-special-bootloader-profile-manipulator))
(target "/booti/efi")
…))
…)
)

Toggle diff (688 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index a865b2e2e4..4b35142e95 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -35710,8 +35710,9 @@ The type of a bootloader configuration declaration.
 @cindex BIOS, bootloader
 The bootloader to use, as a @code{bootloader} object.  For now
 @code{grub-bootloader}, @code{grub-efi-bootloader},
-@code{grub-efi-netboot-bootloader}, @code{extlinux-bootloader} and
-@code{u-boot-bootloader} are supported.
+@code{grub-efi-netboot-bootloader},
+@code{grub-efi-netboot-removable-bootloader},
+@code{extlinux-bootloader} and @code{u-boot-bootloader} are supported.
 
 @cindex ARM, bootloaders
 @cindex AArch64, bootloaders
@@ -35737,9 +35738,10 @@ build a diskless Guix system.
 
 The installation of the @code{grub-efi-netboot-bootloader} generates the
 content of the TFTP root directory at @code{targets} (@pxref{Bootloader
-Configuration, @code{targets}}), to be served by a TFTP server.  You may
-want to mount your TFTP server directories onto the @code{targets} to
-move the required files to the TFTP server automatically.
+Configuration, @code{targets}}) below the sub-directory @file{efi/Guix}, to be
+served by a TFTP server.  You may want to mount your TFTP server directories
+onto the @code{targets} to move the required files to the TFTP server
+automatically during installation.
 
 If you plan to use an NFS root file system as well (actually if you mount the
 store from an NFS share), then the TFTP server needs to serve the file
@@ -35773,13 +35775,23 @@ directory to your @code{targets}.
 It is important to note that symlinks pointing outside the TFTP root directory
 may need to be allowed in the configuration of your TFTP server.  Further the
 store link exposes the whole store through TFTP@.  Both points need to be
-considered carefully for security aspects.
+considered carefully for security aspects.  It is advised to disable any TFTP
+write access!
+
+Please note, that this bootloader will not modify the ‘UEFI Boot Manager’ of
+the system.
 
 Beside the @code{grub-efi-netboot-bootloader}, the already mentioned TFTP and
 NFS servers, you also need a properly configured DHCP server to make the booting
 over netboot possible.  For all this we can currently only recommend you to look
 for instructions about @acronym{PXE, Preboot eXecution Environment}.
 
+@vindex grub-efi-netboot-removable-bootloader
+@code{grub-efi-netboot-removable-bootloader} is identical to
+@code{grub-efi-netboot-bootloader} with the exception that the sub-directory
+@file{efi/boot} will be used instead of @file{efi/Guix} to comply to the UEFI
+specification for removable media.
+
 @item @code{targets}
 This is a list of strings denoting the targets onto which to install the
 bootloader.
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index 9cf5457873..797908e24a 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -259,26 +259,22 @@ (define (lookup-bootloader-by-name name)
             (force %bootloaders))
       (leave (G_ "~a: no such bootloader~%") name)))
 
-(define (efi-bootloader-profile files bootloader-package hooks)
-  "Creates a profile with BOOTLOADER-PACKAGE and a directory collection/ with
-links to additional FILES from the store.  This collection is meant to be used
-by the bootloader installer.
+(define (efi-bootloader-profile packages files hooks)
+  "Creates a profile from the lists of PACKAGES and FILES from the store.
+This profile is meant to be used by the bootloader-installer.
 
 FILES is a list of file or directory names from the store, which will be
-symlinked into the collection/ directory.  If a directory name ends with '/',
-then the directory content instead of the directory itself will be symlinked
-into the collection/ directory.
+symlinked into the profile.  If a directory name ends with '/', then the
+directory content instead of the directory itself will be symlinked into the
+profile.
 
-FILES may contain file like objects produced by functions like plain-file,
+FILES may contain file like objects produced by procedures like plain-file,
 local-file, etc., or package contents produced with file-append.
 
 HOOKS lists additional hook functions to modify the profile."
-  (define (bootloader-collection manifest)
+  (define (efi-bootloader-profile-hook manifest)
     (define build
-        (with-imported-modules '((guix build utils)
-                                 (ice-9 ftw)
-                                 (srfi srfi-1)
-                                 (srfi srfi-26))
+        (with-imported-modules '((guix build utils))
           #~(begin
             (use-modules ((guix build utils)
                           #:select (mkdir-p strip-store-file-name))
@@ -302,7 +298,7 @@ (define name-ends-with-/? (cut string-suffix? "/" <>))
             (define (name-is-store-entry? name)
               "Return #t if NAME is a direct store entry and nothing inside."
               (not (string-index (strip-store-file-name name) #\/)))
-            (let* ((collection (string-append #$output "/collection"))
+            (let* ((output #$output)
                    (files '#$files)
                    (directories (filter name-ends-with-/? files))
                    (names-from-directories
@@ -311,11 +307,11 @@ (define (name-is-store-entry? name)
                                 directories))
                    (names (append names-from-directories
                                   (remove name-ends-with-/? files))))
-              (mkdir-p collection)
+              (mkdir-p output)
               (if (every file-exists? names)
                   (begin
                     (for-each (lambda (name)
-                               (symlink-to name collection
+                               (symlink-to name output
                                             (if (name-is-store-entry? name)
                                                 strip-store-file-name
                                                 basename)))
@@ -323,57 +319,63 @@ (define (name-is-store-entry? name)
                     #t)
                   #f)))))
 
-    (gexp->derivation "bootloader-collection"
+    (gexp->derivation "efi-bootloader-profile"
                       build
                       #:local-build? #t
                       #:substitutable? #f
                       #:properties
                       `((type . profile-hook)
-                        (hook . bootloader-collection))))
+                        (hook . efi-bootloader-profile-hook))))
 
-  (profile (content (packages->manifest (list bootloader-package)))
-           (name "bootloader-profile")
-           (hooks (append (list bootloader-collection) hooks))
+  (profile (content (packages->manifest packages))
+           (name "efi-bootloader-profile")
+           (hooks (cons efi-bootloader-profile-hook hooks))
            (locales? #f)
            (allow-collisions? #f)
            (relative-symlinks? #f)))
 
-(define* (efi-bootloader-chain files
-                               final-bootloader
+(define* (efi-bootloader-chain final-bootloader
                                #:key
+                               (packages '())
+                               (files '())
                                (hooks '())
-                               installer)
-  "Define a bootloader chain with FINAL-BOOTLOADER as the final bootloader and
-certain directories and files from the store given in the list of FILES.
+                               installer
+                               disk-image-installer)
+  "Define a chain of bootloaders with the FINAL-BOOTLOADER, optional PACKAGES,
+and optional directories and files from the store given in the list of FILES.
 
-FILES may contain file like objects produced by functions like plain-file,
-local-file, etc., or package contents produced with file-append.  They will be
-collected inside a directory collection/ inside a generated bootloader profile,
-which will be passed to the INSTALLER.
+The package of the FINAL-BOOTLOADER and all PACKAGES and FILES will be placed
+in an efi-bootloader-profile, which will be passed to the INSTALLER.
+
+FILES may contain file like objects produced by procedures like plain-file,
+local-file, etc., or package contents produced with file-append.
 
 If a directory name in FILES ends with '/', then the directory content instead
-of the directory itself will be symlinked into the collection/ directory.
+of the directory itself will be symlinked into the efi-bootloader-profile.
 
 The procedures in the HOOKS list can be used to further modify the bootloader
 profile.  It is possible to pass a single function instead of a list.
 
-If the INSTALLER argument is used, then this function will be called to install
-the bootloader.  Otherwise the installer of the FINAL-BOOTLOADER will be called."
-  (let* ((final-installer (or installer
-                              (bootloader-installer final-bootloader)))
-         (profile (efi-bootloader-profile files
-                                          (bootloader-package final-bootloader)
-                                          (if (list? hooks)
-                                              hooks
-                                              (list hooks)))))
-    (bootloader
-     (inherit final-bootloader)
-     (package profile)
-     (installer
-      #~(lambda (bootloader target mount-point)
-          (#$final-installer bootloader target mount-point)
-          (copy-recursively
-           (string-append bootloader "/collection")
-           (string-append mount-point target)
-           #:follow-symlinks? #t
-           #:log (%make-void-port "w")))))))
+If the INSTALLER argument is used, then this gexp procedure will be called to
+install the efi-bootloader-profile.  Otherwise the installer of the
+FINAL-BOOTLOADER will be called.
+
+If the DISK-IMAGE-INSTALLER is used, then this gexp procedure will be called
+to install the efi-bootloader-profile into a disk-image.  Otherwise the
+disk-image-installer of the FINAL-BOOTLOADER will be called."
+  (bootloader
+    (inherit final-bootloader)
+    (name "efi-bootloader-chain")
+    (package
+     (efi-bootloader-profile (cons (bootloader-package final-bootloader)
+                                   packages)
+                             files
+                             (if (list? hooks)
+                                 hooks
+                                 (list hooks))))
+    (installer
+     (or installer
+         (bootloader-installer final-bootloader)))
+    (disk-image-installer
+     (or disk-image-installer
+         (bootloader-disk-image-installer final-bootloader)))))
diff --git a/gnu/bootloader/grub.scm b/gnu/bootloader/grub.scm
index 120cd55012..0ba6aa4dad 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -50,11 +50,12 @@ (define-module (gnu bootloader grub)
             grub-theme-color-highlight
             grub-theme-gfxmode
 
-            install-grub-efi-netboot
+            make-grub-efi-netboot-installer
 
             grub-bootloader
             grub-efi-bootloader
             grub-efi-netboot-bootloader
+            grub-efi-netboot-removable-bootloader
             grub-mkrescue-bootloader
             grub-minimal-bootloader
 
@@ -348,7 +349,7 @@ (define (grub-root-search device file)
         ((or #f (? string?))
          #~(format #f "search --file --set ~a" #$file)))))
 
-(define* (grub-configuration-file config entries
+(define* (make-grub-configuration grub config entries
                                   #:key
                                   (locale #f)
                                   (system (%current-system))
@@ -378,27 +379,27 @@ (define (menu-entry->gexp entry)
                 (initrd (normalize-file (menu-entry-initrd entry)
                                         device-mount-point
                                         store-directory-prefix)))
-         ;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
-         ;; Use the right file names for LINUX and INITRD in case
-         ;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
-         ;; separate partition.
-
-         ;; When BTRFS-SUBVOLUME-FILE-NAME is defined, prepend it the linux and
-         ;; initrd paths, to allow booting from a Btrfs subvolume.
-         #~(format port "menuentry ~s {
+            ;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
+            ;; Use the right file names for LINUX and INITRD in case
+            ;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
+            ;; separate partition.
+
+            ;; When BTRFS-SUBVOLUME-FILE-NAME is defined, prepend it the linux and
+            ;; initrd paths, to allow booting from a Btrfs subvolume.
+            #~(format port "menuentry ~s {
   ~a
   linux ~a ~a
   initrd ~a
 }~%"
-                   #$label
-                   #$(grub-root-search device linux)
-                   #$linux (string-join (list #$@arguments))
-                   #$initrd))
+                      #$label
+                      #$(grub-root-search device linux)
+                      #$linux (string-join (list #$@arguments))
+                      #$initrd))
           (let ((kernel (menu-entry-multiboot-kernel entry))
                 (arguments (menu-entry-multiboot-arguments entry))
                 (modules (menu-entry-multiboot-modules entry))
                 (root-index 1))            ; XXX EFI will need root-index 2
-        #~(format port "
+            #~(format port "
 menuentry ~s {
   multiboot ~a root=device:hd0s~a~a~a
 }~%"
@@ -435,9 +436,7 @@ (define (sugar)
   (define locale-config
     (let* ((entry (first all-entries))
            (device (menu-entry-device entry))
-           (mount-point (menu-entry-device-mount-point entry))
-           (bootloader (bootloader-configuration-bootloader config))
-           (grub (bootloader-package bootloader)))
+           (mount-point (menu-entry-device-mount-point entry)))
       #~(let ((locale #$(and locale
                              (locale-definition-source
                               (locale-name->definition locale))))
@@ -463,8 +462,6 @@ (define locale-config
 
   (define keyboard-layout-config
     (let* ((layout (bootloader-configuration-keyboard-layout config))
-           (grub   (bootloader-package
-                    (bootloader-configuration-bootloader config)))
            (keymap* (and layout
                          (keyboard-layout-file layout #:grub grub)))
            (entry (first all-entries))
@@ -515,6 +512,16 @@ (define builder
                  #:options '(#:local-build? #t
                              #:substitutable? #f)))
 
+(define (grub-configuration-file config . args)
+  (let* ((bootloader (bootloader-configuration-bootloader config))
+         (grub (bootloader-package bootloader)))
+    (apply make-grub-configuration grub config args)))
+
+(define (grub-efi-configuration-file . args)
+  (apply make-grub-configuration grub-efi args))
+
+(define grub-cfg "/boot/grub/grub.cfg")
+
 
 
 ;;;
@@ -608,42 +615,31 @@ (define install-grub-efi
                         "--bootloader-id=Guix"
                         "--efi-directory" target-esp)))))
 
-(define (install-grub-efi-netboot subdir)
-  "Define a grub-efi-netboot bootloader installer for installation in SUBDIR,
-which is usually efi/Guix or efi/boot."
-  (let* ((system (string-split (nix-system->gnu-triplet
-                                (or (%current-target-system)
-                                    (%current-system)))
-                               #\-))
-         (arch (first system))
-         (boot-efi-link (match system
-                          ;; These are the supportend systems and the names
-                          ;; defined by the UEFI standard for removable media.
-                          (("i686" _ ...)        "/bootia32.efi")
-                          (("x86_64" _ ...)      "/bootx64.efi")
-                          (("arm" _ ...)         "/bootarm.efi")
-                          (("aarch64" _ ...)     "/bootaa64.efi")
-                          (("riscv" _ ...)       "/bootriscv32.efi")
-                          (("riscv64" _ ...)     "/bootriscv64.efi")
-                          ;; Other systems are not supported, although defined.
-                          ;; (("riscv128" _ ...) "/bootriscv128.efi")
-                          ;; (("ia64" _ ...)     "/bootia64.efi")
-                          ((_ ...)               #f)))
-         (core-efi (string-append
-                    ;; This is the arch dependent file name of GRUB, e.g.
-                    ;; i368-efi/core.efi or arm64-efi/core.efi.
-                    (match arch
-                      ("i686"    "i386")
-                      ("aarch64" "arm64")
-                      ("riscv"   "riscv32")
-                      (_         arch))
-                    "-efi/core.efi")))
-    (with-imported-modules
-     '((guix build union))
-     #~(lambda (bootloader target mount-point)
-         "Install the BOOTLOADER, which must be the package grub, as e.g.
-bootx64.efi or bootaa64.efi into SUBDIR, which is usually efi/Guix or efi/boot,
-below the directory TARGET for the system whose root is mounted at MOUNT-POINT.
+(define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
+  "Make a bootloader-installer for a grub-efi-netboot bootloader, which expects
+its files in SUBDIR and its configuration file in GRUB-CFG.
+
+As a grub-efi-netboot package is already preinstalled by 'grub-mknetdir', the
+installer basically copies all files from the bootloader-package (or profile)
+into the bootloader-target directory.
+
+Additionally for network booting over TFTP, two relative symlinks to the store
+and to the GRUB-CFG file are necessary.  Due to this a TFTP root directory must
+not be located on a FAT file-system.
+
+If the bootloader-target does not support symlinks, then it is assumed to be a
+kind of EFI System Partition (ESP).  In this case an intermediate configuration
+file is created with the help of GRUB-EFI to load the GRUB-CFG.
+
+The installer is usable for any efi-bootloader-chain, which prepares the
+bootloader-profile in a way ready for copying.
+
+The installer does not manipulate the system's 'UEFI Boot Manager'."
+  (with-imported-modules '((guix build union))
+    #~(lambda (bootloader target mount-point)
+        "Copy the BOOTLOADER, which must be a preinstalled grub-efi-netboot
+package with a SUBDIR like efi/boot or efi/Guix, below the directory
+TARGET for the system whose root is mounted at MOUNT-POINT.
 
 MOUNT-POINT is the last argument in 'guix system init /etc/config.scm mnt/point'
 or '/' for other 'guix system' commands.
@@ -653,17 +649,18 @@ (define (install-grub-efi-netboot subdir)
 
 (operating-system
  (bootloader (bootloader-configuration
-              (targets '(\"/boot\"))
+              (targets '(\"/boot/efi\"))
               …))
  …)
 
 TARGET is required to be an absolute directory name, usually mounted via NFS,
 and finally needs to be provided by a TFTP server as the TFTP root directory.
 
+Usually the installer will be used to prepare network booting over TFTP.  Then
 GRUB will load tftp://server/SUBDIR/grub.cfg and this file will instruct it to
 load more files from the store like tftp://server/gnu/store/…-linux…/Image.
 
-To make this possible two symlinks will be created. The first symlink points
+To make this possible two symlinks will be created.  The first symlink points
 relatively form MOUNT-POINT/TARGET/SUBDIR/grub.cfg to
 MOUNT-POINT/boot/grub/grub.cfg, and the second symlink points relatively from
 MOUNT-POINT/TARGET/%store-prefix to MOUNT-POINT/%store-prefix.
@@ -673,34 +670,78 @@ (define (install-grub-efi-netboot subdir)
 
 It is also important to note that both symlinks will point outside the TFTP root
 directory and that the TARGET/%store-prefix symlink makes the whole store
-accessible via TFTP. Possibly the TFTP server must be configured
-to allow accesses outside its TFTP root directory. This may need to be
-considered for security aspects."
-         (use-modules ((guix build union) #:select (symlink-relative)))
-         (let* ((net-dir (string-append mount-point target "/"))
-                (sub-dir (string-append net-dir #$subdir "/"))
-                (store (string-append mount-point (%store-prefix)))
-                (store-link (string-append net-dir (%store-prefix)))
-                (grub-cfg (string-append mount-point "/boot/grub/grub.cfg"))
-                (grub-cfg-link (string-append sub-dir (basename grub-cfg)))
-                (boot-efi-link (string-append sub-dir #$boot-efi-link)))
-           ;; Prepare the symlink to the store.
-           (mkdir-p (dirname store-link))
-           (false-if-exception (delete-file store-link))
-           (symlink-relative store store-link)
-           ;; Prepare the symlink to the grub.cfg, which points into the store.
-           (mkdir-p (dirname grub-cfg-link))
-           (false-if-exception (delete-file grub-cfg-link))
-           (symlink-relative grub-cfg grub-cfg-link)
-           ;; Install GRUB, which refers to the grub.cfg, with support for
-           ;; encrypted partitions,
-           (setenv "GRUB_ENABLE_CRYPTODISK" "y")
-           (invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
-                         (string-append "--net-directory=" net-dir)
-                         (string-append "--subdir=" #$subdir))
-           ;; Prepare the bootloader symlink, which points to core.efi of GRUB.
-           (false-if-exception (delete-file boot-efi-link))
-           (symlink #$core-efi boot-efi-link))))))
+accessible via TFTP.  Possibly the TFTP server must be configured to allow
+accesses outside its TFTP root directory.  This all may need to be considered
+for security aspects.  It is advised to disable any TFTP write access!
+
+The installer can also be used to prepare booting from local storages, if the
+underlying file-system, like FAT on an EFI System Partition (ESP), does not
+support symlinks.  In this case the MOUNT-POINT/TARGET/SUBDIR/grub.cfg will be
+created with the help of GRUB-EFI to load the /boot/grub/grub.cfg file.  A
+symlink to the store is not needed in this case."
+        ;; In context of a disk image creation TARGET will be #f and an
+        ;; installer is expected to do necessary installations on MOUNT-POINT,
+        ;; which will become the root file system.
+        ;; If TARGET is #f, this installer has nothing to do, as it only cares
+        ;; about the EFI System Partition (ESP).
+        (when target
+          (use-modules ((guix build union) #:select (symlink-relative))
+                       (ice-9 popen)
+                       (ice-9 rdelim))
+          (let* ((mount-point/target (string-append mount-point target "/"))
+                 ;; When installing Guix, it is common to mount TARGET below
+                 ;; MOUNT-POINT rather than the root directory.
+                 (bootloader-target (if (file-exists? mount-point/target)
+                                        mount-point/target
+                                        target))
+                 (store (string-append mount-point (%store-prefix)))
+                 (store-link (string-append bootloader-target (%store-prefix)))
+                 (grub-cfg (string-append mount-point #$grub-cfg))
+                 (grub-cfg-link (string-append bootloader-target
+                                               #$subdir "/"
+                                               (basename grub-cfg))))
+            ;; Copy the bootloader into the bootloader-target directory.
+            ;; Should we beforehand recursively delete any existing file?
+            (copy-recursively bootloader bootloader-target
+                              #:follow-symlinks? #t
+                              #:log (%make-void-port "w"))
+            ;; For TFTP we need to install additional relative symlinks.
+            ;; If we install on an EFI System Partition (ESP) or some other FAT
+            ;; file-system, then symlinks cannot be created and are not needed.
+            ;; Therefore we ignore exceptions when trying.
+            ;; Prepare the symlink to the grub.cfg.
+            (mkdir-p (dirname grub-cfg-link))
+            (false-if-exception (delete-file grub-cfg-link))
+            (if (unspecified?
+                (false-if-exception (symlink-relative grub-cfg grub-cfg-link)))
+              ;; Symlinks are supported.
+              (begin
+                ;; Prepare the symlink to the store.
+                (mkdir-p (dirname store-link))
+                (false-if-exception (delete-file store-link))
+                (symlink-relative store store-link))
+              ;; Creating symlinks does not seem to be supported.
+              ;; Probably an ESP is used.
+              ;; Instead we can script to search and load the actual grub.cfg.
+              (let* ((probe #$(file-append grub-efi "/sbin/grub-probe"))
+                     (port
+                       (open-pipe* OPEN_READ probe "--target=fs_uuid" grub-cfg))
+                     (search-root
+                       (match (read-line port)
+                         ((? eof-object?)
+                           ;; There is no UUID available. As a fallback search
+                           ;; everywhere for the grub.cfg.
+                           (string-append "search --file --set " #$grub-cfg))
+                         (fs-uuid
+                           ;; The UUID to load the grub.cfg from is known.
+                           (string-append "search --fs-uuid --set " fs-uuid))))
+                     (load-grub-cfg (string-append "configfile " #$grub-cfg)))
+                (close-pipe port)
+                (with-output-to-file grub-cfg-link
+                  (lambda ()
+                    (display (string-join (list search-root
+                                                load-grub-cfg)
+                                          "\n")))))))))))
 
 
 
@@ -718,7 +759,7 @@ (define grub-bootloader
    (package grub)
    (installer install-grub)
    (disk-image-installer install-grub-disk-image)
-   (configuration-file "/boot/grub/grub.cfg")
+   (configuration-file grub-cfg)
    (configuration-file-generator grub-configuration-file)))
 
 (define grub-minimal-bootloader
@@ -728,17 +769,29 @@ (define grub-minimal-bootloader
 
 (define grub-efi-bootloader
   (bootloader
-   (inherit grub-bootloader)
+   (name 'grub-efi)
+   (package grub-efi)
    (installer install-grub-efi)
    (disk-image-installer #f)
-   (name 'grub-efi)
-   (package grub-efi)))
+   (configuration-file grub-cfg)
+   (configuration-file-generator grub-configuration-file)))
 
-(define grub-efi-netboot-bootloader
+(define (make-grub-efi-netboot-bootloader name subdir)
   (bootloader
-   (inherit grub-efi-bootloader)
-   (name 'grub-efi-netboot-bootloader)
-   (installer (install-grub-efi-netboot "efi/Guix"))))
+   (name name)
+   (package (make-grub-efi-netboot (symbol->string name) subdir))
+   (installer (make-grub-efi-netboot-installer grub-efi grub-cfg subdir))
+   (disk-image-installer #f)
+   (configuration-file grub-cfg)
+   (configuration-file-generator grub-efi-configuration-file)))
+
+(define grub-efi-netboot-bootloader
+  (make-grub-efi-netboot-bootloader 'grub-efi-netboot-bootloader
+                                    "efi/Guix"))
+
+(define grub-efi-netboot-removable-bootloader
+  (make-grub-efi-netboot-bootloader 'grub-efi-netboot-removable-bootloader
+                                    "efi/boot"))
 
 (define grub-mkrescue-bootloader
   (bootloader
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 7ea6f5a647..6876ab17b9 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -15,6 +15,7 @@
 ;;; Copyright © 2020, 2021 Pierre Langlois <pierre.langlois@gmx.com>
 ;;; Copyright © 2021 Vincent Legoll <vincent.legoll@gmail.com>
 ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -66,13 +67,17 @@ (define-module (gnu packages bootloaders)
   #:use-module (gnu packages virtualization)
   #:use-module (gnu packages xorg)
   #:use-module (guix build-system gnu)
+  #:use-module (guix build-system trivial)
   #:use-module (guix download)
+  #:use-module (guix gexp)
   #:use-module (guix git-download)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix packages)
   #:use-module (guix utils)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26)
+  #:use-module (ice-9 match)
+  #:use-module (ice-9 optargs)
   #:use-module (ice-9 regex))
 
 (define unifont
@@ -366,6 +371,91 @@ (define-public grub-hybrid
                   (scandir input-dir))
                  #t)))))))))
 
+(define-public (make-grub-efi-netboot name subdir)
+  "Make a grub-efi-netboot package named NAME, which will be able to boot over
+network via TFTP by accessing its files in the SUBDIR of a TFTP root directory.
+This package is also able to boot from local storage devices.
+
+A bootloader-installer basically needs to copy the package content into the
+bootloader-target directory, which will usually be the TFTP root, as
+'grub-mknetdir' will be invoked already during the package creation.
+
+Alternatively the bootloader-target directory can be a mounted EFI System
+Partition (ESP), or a similar partition with a FAT file system, for booting
+from local storage devices.
+
+The name of the GRUB EFI binary will conform to the UEFI specification for
+removable media.  Depending on the system it will be e.g. bootx64.efi or
+bootaa64.efi below SUBDIR.
+
+The SUBDIR argument needs to be set to \"efi/boot\" to create a package which
+conforms to the UEFI specification for removable media.
+
+The SUBDIR argument defaults to \"efi/Guix\", as it is also the case for
+'grub-efi-bootloader'."
+  (package
+    (name name)
+    (version (package-version grub-efi))
+    ;; Source is not needed, but it cannot be omitted.
+    (source #f)
+    (build-system trivial-build-system)
+    (arguments
+     (let* ((system (string-split (nix-system->gnu-triplet
+                                  (or (%current-target-system)
+                                      (%current-system)))
+                                  #\-))
+            (arch (first system))
+            (boot-efi
+             (match system
+               ;; These are the supportend systems and the names defined by
+               ;; the UEFI standard for removable media.
+               (("i686" _ ...)        "/bootia32.efi")
+               (("x86_64" _ ...)      "/bootx64.efi")
+               (("arm" _ ...)         "/bootarm.efi")
+               (("aarch64" _ ...)     "/bootaa64.efi")
+               (("riscv" _ ...)       "/bootriscv32.efi")
+               (("riscv64" _ ...)     "/bootriscv64.efi")
+               ;; Other systems are not supported, although defined.
+               ;; (("riscv128" _ ...) "/bootriscv128.efi")
+               ;; (("ia64" _ ...)     "/bootia64.efi")
+               ((_ ...)               #f)))
+            (core-efi (string-append
+                       ;; This is the arch dependent file name of GRUB, e.g.
+                       ;; i368-efi/core.efi or arm64-efi/core.efi.
+                       (match arch
+                         ("i686"    "i386")
+                         ("aarch64" "arm64")
+                         ("riscv"   "riscv32")
+                         (_         arch))
+                       "-efi/core.efi")))
+       `(#:modules ((guix build utils))
+         #:builder
+         (begin
+           (use-modules (guix build utils))
+           (let* ((bootloader (assoc-ref %build-inputs "grub-efi"))
+                  (net-dir (assoc-ref %outputs "out"))
+                  (sub-dir (string-append net-dir "/" ,subdir "/"))
+                  (boot-efi (string-append sub-dir ,boot-efi))
+                  (core-efi (string-append sub-dir ,core-efi)))
+             ;; Install GRUB, which refers to the grub.cfg, with support for
+             ;; encrypted partitions,
+             (setenv "GRUB_ENABLE_CRYPTODISK" "y")
+             (invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
+                           (string-append "--net-directory=" net-dir)
+                           (string-append "--subdir=" ,subdir)
+                           ;; These modules must be preloaded to allow booting
+                           ;; from an ESP or a similar partition with a FAT
+                           ;; file system.
+                           (string-append "--modules=part_msdos part_gpt fat"))
+             ;; Move GRUB's core.efi to the removable media name.
+             (false-if-exception (delete-file boot-efi))
+             (rename-file core-efi boot-efi))))))
+    (inputs `(("grub-efi" ,grub-efi)))
+    (synopsis (package-synopsis grub-efi))
+    (description (package-description grub-efi))
+    (home-page (package-home-page grub-efi))
+    (license (package-license grub-efi))))
+
 (define-public syslinux
   (let ((commit "bb41e935cc83c6242de24d2271e067d76af3585c"))
     (package
-- 
2.34.0
From f6e01db0581ad7c291a20f5a8b15bd5925ba70af Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:11:20 +0200
Subject: [PATCH v5 3/8] gnu: bootloader: Add U-Boot packages for Raspberry Pi
models.

* gnu/packages/bootloader.scm (make-u-boot-package): Add keyword
parameters 'name' and 'description'.
(make-preinstalled-u-boot-package): New function to make minimal packages.
(%u-boot-rpi-efi-configs): New helper list with config strings.
(%u-boot-rpi-description-32-bit, %u-boot-rpi-description-64-bit,
%u-boot-rpi-efi-description, %u-boot-rpi-efi-description-32-bit): New helper
strings.
(u-boot-rpi-0-w, u-boot-rpi, u-boot-rpi-2, u-boot-rpi-3, u-boot-rpi-4,
u-boot-rpi-64, u-boot-rpi-0-w-efi, u-boot-rpi-efi, u-boot-rpi-2-efi,
u-boot-rpi-3-efi, u-boot-rpi-4-efi, u-boot-rpi-efi-64): New packages.

Toggle diff (199 lines)
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 10f2dd5fad..84d65c94cd 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -748,17 +748,30 @@ (define-public u-boot-tools
 also initializes the boards (RAM etc).  This package provides its
 board-independent tools.")))
 
-(define*-public (make-u-boot-package board triplet #:key defconfig configs)
+(define*-public (make-u-boot-package board
+                                     triplet
+                                     #:key
+                                     defconfig
+                                     configs
+                                     name
+                                     description)
   "Returns a u-boot package for BOARD cross-compiled for TRIPLET with the
-optional DEFCONFIG file and optional configuration changes from CONFIGS."
+optional DEFCONFIG file and optional configuration changes from CONFIGS.
+Either NAME, if used, or otherwise BOARD will be part of the package name.
+DESCRIPTION will be appended to the package description."
   (let ((same-arch? (lambda ()
                       (string=? (%current-system)
                                 (gnu-triplet->nix-system triplet)))))
     (package
       (inherit u-boot)
       (name (string-append "u-boot-"
-                           (string-replace-substring (string-downcase board)
-                                                     "_" "-")))
+                           (string-replace-substring
+                            (string-downcase (or name board))
+                            "_" "-")))
+      (description (if description
+                       (string-append (package-description u-boot)
+                                      "\n" description)
+                       (package-description u-boot)))
       (native-inputs
        `(,@(if (not (same-arch?))
              `(("cross-gcc" ,(cross-gcc triplet))
@@ -1117,6 +1130,157 @@ (define-public u-boot-pinebook-pro-rk3399
        `(("firmware" ,arm-trusted-firmware-rk3399)
          ,@(package-native-inputs base))))))
 
+(define*-public (make-preinstalled-u-boot-package board
+                                                  triplet
+                                                  #:key
+                                                  defconfig
+                                                  configs
+                                                  name
+                                                  description
+                                                  (u-boot-file "u-boot.bin"))
+  "Returns a package with a single U-BOOT-FILE for BOARD cross-compiled for
+TRIPLET with the optional DEFCONFIG file and optional configuration changes
+from CONFIGS.  Either NAME, if used, or otherwise BOARD will be part of the
+package name.  DESCRIPTION will be appended to the package description."
+  (let* ((name-suffix "-complete")
+         (u-boot-package (make-u-boot-package board
+                                              triplet
+                                              #:defconfig defconfig
+                                              #:configs configs
+                                              #:name (string-append
+                                                      (or name board)
+                                                      name-suffix)
+                                              #:description description)))
+    (package
+      (name (string-drop-right (package-name u-boot-package)
+                               (string-length name-suffix)))
+      (version (package-version u-boot-package))
+      (source #f)
+      (build-system trivial-build-system)
+      (arguments
+       `(#:builder
+         (begin
+           (let ((out (assoc-ref %outputs "out")))
+             (mkdir out)
+             (symlink (string-append (assoc-ref %build-inputs "u-boot")
+                                   "/libexec/"
+                                   ,u-boot-file)
+                      (string-append out "/" ,u-boot-file))))))
+      (inputs `(("u-boot" ,u-boot-package)))
+      (home-page (package-home-page u-boot-package))
+      (synopsis (package-synopsis u-boot-package))
+      (description (package-description u-boot-package))
+      (license (package-license u-boot-package)))))
+
+(define-public %u-boot-rpi-efi-configs
+  '("CONFIG_OF_EMBED="
+    "CONFIG_OF_BOARD=y"
+    "CONFIG_BOOTDELAY=0"))
+
+(define %u-boot-rpi-description-32-bit
+  "This is a 32-bit build of U-Boot.")
+
+(define %u-boot-rpi-description-64-bit
+  "This is a common 64-bit build of U-Boot for all 64-bit capable Raspberry Pi
+variants.")
+
+(define %u-boot-rpi-efi-description
+  "It allows network booting and uses the device-tree from the firmware,
+allowing the usage of overlays.  It can act as an EFI firmware for the
+grub-efi-netboot-removable-bootloader.")
+
+(define %u-boot-rpi-efi-description-32-bit
+  (string-append %u-boot-rpi-efi-description "  "
+                 %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-0-w
+  (make-preinstalled-u-boot-package
+   "rpi_0_w"
+   "arm-linux-gnueabihf"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi
+  (make-preinstalled-u-boot-package
+   "rpi"
+   "arm-linux-gnueabihf"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-2
+  (make-preinstalled-u-boot-package
+   "rpi_2"
+   "arm-linux-gnueabihf"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-3
+  (make-preinstalled-u-boot-package
+   "rpi_3_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-3"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-4
+  (make-preinstalled-u-boot-package
+   "rpi_4_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-4"
+   #:description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-64
+  (make-preinstalled-u-boot-package
+   "rpi_arm64"
+   "aarch64-linux-gnu"
+   #:name "rpi-64"
+   #:description %u-boot-rpi-description-64-bit))
+
+(define-public u-boot-rpi-0-w-efi
+  (make-preinstalled-u-boot-package
+   "rpi_0_w"
+   "arm-linux-gnueabihf"
+   #:name "rpi-0-w-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-efi
+  (make-preinstalled-u-boot-package
+   "rpi"
+   "arm-linux-gnueabihf"
+   #:name "rpi-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-2-efi
+  (make-preinstalled-u-boot-package
+   "rpi_2"
+   "arm-linux-gnueabihf"
+   #:name "rpi-2-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-3-efi
+  (make-preinstalled-u-boot-package
+   "rpi_3_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-3-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-4-efi
+  (make-preinstalled-u-boot-package
+   "rpi_4_32b"
+   "arm-linux-gnueabihf"
+   #:name "rpi-4-efi"
+   #:configs %u-boot-rpi-efi-configs
+   #:description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-efi-64
+  (make-preinstalled-u-boot-package
+   "rpi_arm64"
+   "aarch64-linux-gnu"
+   #:name "rpi-efi-64"
+   #:configs %u-boot-rpi-efi-configs
+   #:description (string-append %u-boot-rpi-efi-description "  "
+                                %u-boot-rpi-description-64-bit)))
+
 (define-public vboot-utils
   (package
     (name "vboot-utils")
-- 
2.34.0
From 436b4544f526b96e3d60036016d131f13e439841 Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:36 +0200
Subject: [PATCH v5 7/8] gnu: raspberry-pi: New function to make a package with
device-tree files.

* gnu/packages/raspberry-pi.scm (make-raspi-bcm28-dtbs): New function to make
a package with device-tree files for Raspberry Pi models from the kernel given
as argument.

Toggle diff (41 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 0707516f72..d808f61ac2 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -30,6 +30,7 @@ (define-module (gnu packages raspberry-pi)
   #:use-module (gnu packages file)
   #:use-module (gnu packages gcc)
   #:use-module (gnu packages linux)
+  #:use-module (guix build-system copy)
   #:use-module (guix build-system gnu)
   #:use-module (guix download)
   #:use-module (guix git-download)
@@ -291,6 +292,26 @@ (define-public (raspi-custom-txt content)
 character.  Alternatively CONTENT can be a string with the full file content."
   (raspi-config-file "custom.txt" content))
 
+(define-public (make-raspi-bcm28-dtbs linux)
+  "Make a package with the device-tree files for Raspberry Pi models from the
+kernel LINUX."
+  (package
+    (inherit linux)
+    (name "raspi-bcm28-dtbs")
+    (source #f)
+    (build-system copy-build-system)
+    (arguments
+     `(#:phases (modify-phases %standard-phases (delete 'unpack))
+       #:install-plan
+       (list (list (string-append (assoc-ref %build-inputs "linux")
+                                  "/lib/dtbs/broadcom/")
+                   "." #:include-regexp '("/bcm....-rpi.*\\.dtb")))))
+    (inputs `(("linux" ,linux)))
+    (synopsis "Device-tree files for a Raspberry Pi")
+    (description
+     (simple-format #f "The device-tree files for Raspberry Pi models from ~a."
+             (package-name linux)))))
+
 (define (make-raspi-defconfig arch defconfig sha256-as-base32)
   "Make for the architecture ARCH a file-like object from the DEFCONFIG file
 with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
-- 
2.34.0
From a235d7564715cca1cec774d9d515caf1bccb4856 Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Wed, 13 Apr 2022 21:10:19 +0200
Subject: [PATCH v5 2/8] build: kconfig: Add new module to modify a defconfig
file.

From: Stefan <stefan-guix@vodafonemail.de>

* guix/build/kconfig.scm (modify-defconfig): New file with a new function.
* gnu/packages/bootloaders.scm (make-u-boot-package,
make-u-boot-sunxi64-package): Adding new key arguments to pass and/or modify
a defconfig file.
(u-boot-am335x-boneblack, u-boot-pinebook, u-boot-novena): Simplify functions
by using the new key arguments of the former functions.
* Makefile.am: Adding guix/build/kconfig.scm to MODULES.

Toggle diff (326 lines)
diff --git a/Makefile.am b/Makefile.am
index fecce7c6f7..7f69aacbd1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -223,6 +223,7 @@ MODULES =					\
   guix/build/waf-build-system.scm		\
   guix/build/haskell-build-system.scm		\
   guix/build/julia-build-system.scm		\
+  guix/build/kconfig.scm                        \
   guix/build/linux-module-build-system.scm	\
   guix/build/store-copy.scm			\
   guix/build/json.scm				\
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 6876ab17b9..10f2dd5fad 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -16,6 +16,7 @@
 ;;; Copyright © 2021 Vincent Legoll <vincent.legoll@gmail.com>
 ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
 ;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
+;;; Copyright © 2022 Petr Hodina <phodina@protonmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -747,8 +748,9 @@ (define-public u-boot-tools
 also initializes the boards (RAM etc).  This package provides its
 board-independent tools.")))
 
-(define-public (make-u-boot-package board triplet)
-  "Returns a u-boot package for BOARD cross-compiled for TRIPLET."
+(define*-public (make-u-boot-package board triplet #:key defconfig configs)
+  "Returns a u-boot package for BOARD cross-compiled for TRIPLET with the
+optional DEFCONFIG file and optional configuration changes from CONFIGS."
   (let ((same-arch? (lambda ()
                       (string=? (%current-system)
                                 (gnu-triplet->nix-system triplet)))))
@@ -766,8 +768,11 @@ (define-public (make-u-boot-package board triplet)
       (arguments
        `(#:modules ((ice-9 ftw)
                     (srfi srfi-1)
-                    (guix build utils)
-                    (guix build gnu-build-system))
+                    (guix build gnu-build-system)
+                    (guix build kconfig)
+                    (guix build utils))
+         #:imported-modules (,@%gnu-build-system-modules
+                             (guix build kconfig))
          #:test-target "test"
          #:make-flags
          (list "HOSTCC=gcc"
@@ -778,9 +783,18 @@ (define-public (make-u-boot-package board triplet)
          (modify-phases %standard-phases
            (replace 'configure
              (lambda* (#:key outputs make-flags #:allow-other-keys)
-               (let ((config-name (string-append ,board "_defconfig")))
-                 (if (file-exists? (string-append "configs/" config-name))
-                     (apply invoke "make" `(,@make-flags ,config-name))
+               (let* ((config-name (string-append ,board "_defconfig"))
+                      (config-file (string-append "configs/" config-name))
+                      (defconfig ,defconfig)
+                      (configs ',configs))
+                 (when defconfig
+                   ;; Replace the board-specific defconfig with the given one.
+                   (copy-file defconfig config-file))
+                 (if (file-exists? config-file)
+                     (begin
+                       (when configs
+                         (modify-defconfig config-file configs))
+                       (apply invoke "make" `(,@make-flags ,config-name)))
                      (begin
                        (display "Invalid board name. Valid board names are:"
                                 (current-error-port))
@@ -834,7 +848,11 @@ (define-public u-boot-malta
   (make-u-boot-package "malta" "mips64el-linux-gnuabi64"))
 
 (define-public u-boot-am335x-boneblack
-  (let ((base (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf")))
+  (let ((base (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"
+               ;; Patch out other device trees to build image small enough to
+               ;; fit within typical partitioning schemes where the first
+               ;; partition begins at sector 2048.
+               #:configs '("CONFIG_OF_LIST=\"am335x-evm am335x-boneblack\""))))
     (package
       (inherit base)
       (name "u-boot-am335x-boneblack")
@@ -843,25 +861,13 @@ (define-public u-boot-am335x-boneblack
 
 This U-Boot is built for the BeagleBone Black, which was removed upstream,
 adjusted from the am335x_evm build with several device trees removed so that
-it fits within common partitioning schemes.")
-      (arguments
-       (substitute-keyword-arguments (package-arguments base)
-         ((#:phases phases)
-          `(modify-phases ,phases
-             (add-after 'unpack 'patch-defconfig
-               ;; Patch out other devicetrees to build image small enough to
-               ;; fit within typical partitioning schemes where the first
-               ;; partition begins at sector 2048.
-               (lambda _
-                 (substitute* "configs/am335x_evm_defconfig"
-                   (("CONFIG_OF_LIST=.*$") "CONFIG_OF_LIST=\"am335x-evm am335x-boneblack\"\n"))
-                 #t)))))))))
+it fits within common partitioning schemes."))))
 
 (define-public u-boot-am335x-evm
   (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"))
 
-(define-public (make-u-boot-sunxi64-package board triplet)
-  (let ((base (make-u-boot-package board triplet)))
+(define*-public (make-u-boot-sunxi64-package board triplet #:key defconfig configs)
+  (let ((base (make-u-boot-package board triplet #:defconfig defconfig #:configs configs)))
     (package
       (inherit base)
       (arguments
@@ -891,20 +897,10 @@ (define-public u-boot-pine64-lts
   (make-u-boot-sunxi64-package "pine64-lts" "aarch64-linux-gnu"))
 
 (define-public u-boot-pinebook
-  (let ((base (make-u-boot-sunxi64-package "pinebook" "aarch64-linux-gnu")))
-    (package
-      (inherit base)
-      (arguments
-       (substitute-keyword-arguments (package-arguments base)
-         ((#:phases phases)
-          `(modify-phases ,phases
-             (add-after 'unpack 'patch-pinebook-config
-               ;; Fix regression with LCD video output introduced in 2020.01
-               ;; https://patchwork.ozlabs.org/patch/1225130/
-               (lambda _
-                 (substitute* "configs/pinebook_defconfig"
-                   (("CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y") "CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y\nCONFIG_VIDEO_BPP32=y"))
-                 #t)))))))))
+  (make-u-boot-sunxi64-package "pinebook" "aarch64-linux-gnu"
+   ;; Fix regression with LCD video output introduced in 2020.01
+   ;; https://patchwork.ozlabs.org/patch/1225130/
+   #:configs '("CONFIG_VIDEO_BPP32=y")))
 
 (define-public u-boot-bananapi-m2-ultra
   (make-u-boot-package "Bananapi_M2_Ultra" "arm-linux-gnueabihf"))
@@ -955,25 +951,17 @@ (define-public u-boot-mx6cuboxi
   (make-u-boot-package "mx6cuboxi" "arm-linux-gnueabihf"))
 
 (define-public u-boot-novena
-  (let ((base (make-u-boot-package "novena" "arm-linux-gnueabihf")))
+  (let ((base (make-u-boot-package "novena" "arm-linux-gnueabihf"
+               ;; Patch configuration to disable loading u-boot.img from FAT
+               ;; partition, allowing it to be installed at a device offset.
+               #:configs '("CONFIG_SPL_FS_FAT="))))
     (package
       (inherit base)
       (description "U-Boot is a bootloader used mostly for ARM boards.  It
 also initializes the boards (RAM etc).
 
 This U-Boot is built for Novena.  Be advised that this version, contrary
-to Novena upstream, does not load u-boot.img from the first partition.")
-      (arguments
-       (substitute-keyword-arguments (package-arguments base)
-         ((#:phases phases)
-          `(modify-phases ,phases
-             (add-after 'unpack 'patch-novena-defconfig
-               ;; Patch configuration to disable loading u-boot.img from FAT partition,
-               ;; allowing it to be installed at a device offset.
-               (lambda _
-                 (substitute* "configs/novena_defconfig"
-                   (("CONFIG_SPL_FS_FAT=y") "# CONFIG_SPL_FS_FAT is not set"))
-                 #t)))))))))
+to Novena upstream, does not load u-boot.img from the first partition."))))
 
 (define-public u-boot-cubieboard
   (make-u-boot-package "Cubieboard" "arm-linux-gnueabihf"))
diff --git a/guix/build/kconfig.scm b/guix/build/kconfig.scm
new file mode 100644
index 0000000000..09ddf59dd0
--- /dev/null
+++ b/guix/build/kconfig.scm
@@ -0,0 +1,148 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2020 Stefan <stefan-guix@vodafonemail.de>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (guix build kconfig)
+  #:use-module  (ice-9 rdelim)
+  #:use-module  (ice-9 regex)
+  #:use-module  (srfi srfi-1)
+  #:use-module  (srfi srfi-26)
+  #:export (modify-defconfig))
+
+;; Commentary:
+;;
+;; Builder-side code to modify configurations for the Kconfig build system as
+;; used by Linux and U-Boot.
+;;
+;; Code:
+
+(define (modify-defconfig defconfig configs)
+  "This function can modify a given DEFCONFIG file by adding, changing or
+removing the list of strings in CONFIGS.  This allows an easy customization of
+Kconfig based projects like the kernel Linux or the bootloader 'Das U-Boot'.
+
+These are examples for CONFIGS to add or change or remove
+configurations to/from DEFCONFIG:
+
+'(\"CONFIG_A=\\\"a\\\"\"
+  \"CONFIG_B=0\"
+  \"CONFIG_C=y\"
+  \"CONFIG_D=m\"
+  \"CONFIG_E=\"
+  \"CONFIG_F\"
+  \"# CONFIG_G is not set\")
+
+Instead of a list, CONFGIS can be a string with one configuration per line."
+  (define config-rx
+    (make-regexp
+     ;; (match:substring (string-match "=(.*)" "=") 1) returns "", but the
+     ;; pattern "=(.+)?" makes it return #f instead.  For a "CONFIG_A=" we like
+     ;; to get #f, which as a value emits "# … is not set".
+     "^(#[\\t ]*)?(CONFIG_[A-Z0-9_]+)([\\t ]*=[\\t ]*(.+)?|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
+
+  (define (config-string->pair config-string)
+    "Parse a config-string like \"CONFIG_EXAMPLE=y\" into a key-value pair.
+Spaces get trimmed.
+\"CONFIG_A=y\"            -> '(\"CONFIG_A\" . \"y\")
+\"CONFIG_B=\\\"\\\"\"         -> '(\"CONFIG_B\" . \"\\\"\\\"\")
+\"CONFIG_C=\"             -> '(\"CONFIG_C\" . #f)
+\"CONFIG_D\"              -> '(\"CONFIG_D\" . #f)
+\"# CONFIG_E is not set\" -> '(\"CONFIG_E\" . #f)
+\"# Anything else\"       -> '(\"# Anything else\" . \"\")"
+    (let ((match (regexp-exec config-rx (string-trim-both config-string))))
+      (if (not match)
+          ;; This is some unparsable config-string.
+          ;; We keep it as it is.
+          (cons config-string "")
+          (let* ((comment (match:substring match 1))
+                 (key (match:substring match 2))
+                 (unset (match:substring match 5))
+                 (value (and (not comment)
+                             (not unset)
+                             (match:substring match 4))))
+            (if (or (and comment (not unset))
+                    (and (not comment) unset))
+                ;; This is just some comment or strange line, which we keep as is.
+                (cons config-string "")
+                (cons key value))))))
+
+  (define (pair->config-string pair)
+    "Convert a PAIR back to a config-string."
+    (let* ((key (car pair))
+           (value (cdr pair)))
+      (if (string? value)
+          (if (string-null? value)
+              key
+              (string-append key "=" value))
+          (string-append "# " key " is not set"))))
+
+  (define (remove-pair pair blacklist)
+    "Turn a key-value PAIR into '("" . ""), if its key is listed in BLACKLIST."
+    (let* ((key (first pair)))
+      (if (member key blacklist)
+          '("" . "")
+          pair)))
+
+  (define (remove-config-string config-string blacklist)
+    "Remove the CONFIG-STRING, if its key is listed in BLACKLIST."
+    (pair->config-string (remove-pair (config-string->pair config-string)
+                                       blacklist)))
+
+  (define* (write-lines input #:key (line-modifier identity))
+    "Write all lines from the INPUT after applying the LINE-MODIFIER to the
+ current-output-port."
+    (let loop ((line (read-line input)))
+      (when (not (eof-object? line))
+        (display (line-modifier line))
+        (newline)
+        (loop (read-line input)))))
+
+  (let* ((modified-defconfig (string-append defconfig ".mod"))
+         ;; Split the configs into a list of single configuations.
+         ;; To minimize mistakes, we support a string and a list of strings,
+         ;; each with newlines to separate configurations.
+         (config-list (fold-right append '()
+                                  (map (lambda (s)
+                                         (string-split s #\newline))
+                                       (if (string? configs)
+                                           (list configs)
+                                           configs))))
+         ;; Generate key-value pairs from the config-list.
+         (pairs (map (lambda (config-string)
+                       (config-string->pair config-string))
+                     config-list))
+         ;; Generate a blacklist of config keys from pairs.
+         (blacklist (map (lambda (config-pair)
+                           (first config-pair))
+                         pairs))
+         (remove-config-string (cut remove-config-string <> blacklist)))
+    ;; Write to the modified-defconfig file first the content of the defconfig
+    ;; file with removed lines, and afterwards the configs.
+    (call-with-output-file modified-defconfig
+      (lambda (output)
+        (with-output-to-port output
+          (lambda ()
+            (call-with-input-file defconfig
+              (lambda (input)
+                (write-lines input #: line-modifier remove-config-string)))
+            (call-with-input-string
+              (string-join (map pair->config-string pairs) "\n")
+              (lambda (input)
+                (write-lines input)))))))
+    ;; Ensure the modified-defconfig file is used.
+    (delete-file defconfig)
+    (rename-file modified-defconfig defconfig)))
-- 
2.34.0
From 56814914d86da8ef5b321e7827de86237b7accdc Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Wed, 13 Apr 2022 21:18:37 +0200
Subject: [PATCH v5 4/8] gnu: linux: New function to modify the configuration
of a Linux kernel.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

From: Stefan <stefan-guix@vodafonemail.de>

* gnu/packages/linux.scm (system->linux-srcarch): New function to return the
relevent folder name below arch/ in the Linux source code.
(make-linux-libre*) ['set-environment]: Splitted this new phase out of and
adding it before …
['configure]: … to allow a replacement and reuse from (modify-linux).
(modify-linux): New function to make a customized Linux package inherited
from another Linux package, which will be build with an own defconfig or
configuration changes.
(make-defconfig): Function to get a defconfig from an uri.

Toggle diff (178 lines)
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index a405837bb1..f802de9666 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -59,7 +59,8 @@
 ;;; Copyright © 2021 Josselin Poiret <josselin.poiret@protonmail.ch>
 ;;; Copyright © 2021 Olivier Dion <olivier.dion@polymtl.ca>
 ;;; Copyright © 2021 Solene Rapenne <solene@perso.pw>
-;;; Copyright © 2021 Petr Hodina <phodina@protonmail.com>
+;;; Copyright © 2021, 2022 Petr Hodina <phodina@protonmail.com>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;; Copyright © 2022 Artyom V. Poptsov <poptsov.artyom@gmail.com>
 
 ;;;
@@ -179,6 +180,7 @@ (define-module (gnu packages linux)
   #:use-module (srfi srfi-2)
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
+  #:use-module (ice-9 optargs)
   #:use-module (ice-9 regex))
 
 (define-public (system->linux-architecture arch)
@@ -195,6 +197,21 @@ (define-public (system->linux-architecture arch)
           ((string-prefix? "riscv" arch) "riscv")
           (else arch))))
 
+(define-public (system->linux-srcarch arch)
+  "Return for a Guix system ARCH name the SRCARCH name, which is set in the
+toplevel Makefile of Linux and denotes the architecture specific directory name
+below arch/ in its source code.  Some few architectures share a common folder.
+It resembles the definition of SRCARCH based on ARCH in the Makefile and may
+be used to place a defconfig file in the proper path."
+  (let ((linux-arch (system->linux-architecture arch)))
+    (match linux-arch
+      ("i386"    "x86")
+      ("x86_64"  "x86")
+      ("sparc32" "sparc")
+      ("sparc64" "sparc")
+      ("sh64"    "sh")
+      (_         linux-arch))))
+
 (define-public (system->defconfig system)
   "Some systems (notably powerpc-linux) require a special target for kernel
 defconfig.  Return the appropriate make target if applicable, otherwise return
@@ -852,7 +869,7 @@ (define* (make-linux-libre* version gnu-revision source supported-systems
                  (lambda _
                    (substitute* (find-files "." "^Makefile(\\.include)?$")
                      (("/bin/pwd") "pwd"))))
-               (replace 'configure
+               (add-before 'configure 'set-environment
                  (lambda* (#:key inputs target #:allow-other-keys)
                    ;; Avoid introducing timestamps.
                    (setenv "KCONFIG_NOTIMESTAMP" "1")
@@ -877,8 +894,10 @@ (define* (make-linux-libre* version gnu-revision source supported-systems
 
                    (setenv "EXTRAVERSION"
                            #$(and extra-version
-                                  (string-append "-" extra-version)))
+                                  (string-append "-" extra-version)))))
 
+               (replace 'configure
+                 (lambda* (#:key inputs native-inputs #:allow-other-keys)
                    (let ((build  (assoc-ref %standard-phases 'build))
                          (config (assoc-ref inputs "kconfig")))
 
@@ -1210,6 +1229,110 @@ (define-public linux-libre-with-bpf
       (inputs (modify-inputs (package-inputs base-linux-libre)
                 (prepend cpio))))))
 
+
+;;;
+;;; Linux kernel customization functions.
+;;;
+
+(define*-public (modify-linux #:key name
+                                    (linux linux-libre)
+                                    source
+                                    defconfig
+                                    (configs "")
+                                    extra-version)
+  "Make a Linux package NAME as a modification of another LINUX package.
+
+If NAME is not given, then it defaults to the same name as the LINUX package.
+
+Unless SOURCE is given the source of LINUX is used.
+
+A DEFCONFIG file to be used can be given as a package, as a file like object
+(file-append, local-file etc.), or as a string with the name of a defconfig file
+available in the Linux sources.  If DEFCONFIG is not given, then a defconfig
+file will be saved from the LINUX package configuration.
+
+Additional CONFIGS will be used to modify the given or saved defconfig, which
+will finally be used to build Linux.
+
+CONFIGS can be a list of strings, with one configuration per line.  The usual
+defconfig syntax has to be used, but there is a special extension to ease the
+removal of configurations.  Comment lines are supported as well.
+
+Here is an explaining usage example:
+
+  '(;; This string defines the version tail in 'uname -r'.
+    \"CONFIG_LOCALVERSION=\\\"-handcrafted\\\"
+    ;; This '# CONFIG_… is not set' syntax has to match exactly!
+    \"# CONFIG_BOOT_CONFIG is not set\"
+    \"CONFIG_NFS_SWAP=y\"
+    ;; This is a multiline configuration:
+    \"CONFIG_E1000=y
+# This is a comment, below follow two special removal extensions:
+CONFIG_CMDLINE_EXTEND
+CONFIG_CMDLINE_FORCE=\")
+
+A string of configurations instead of a list of configuration strings is also
+possible.
+
+EXTRA-VERSION can be a string overwriting the EXTRAVERSION setting of the LINUX
+package, after being prepended by a hyphen.  It will be visible in the output
+of 'uname -r' behind the Linux version numbers."
+  (package
+    (inherit linux)
+    (name (or name (package-name linux)))
+    (source (or source (package-source linux)))
+    (arguments
+     (substitute-keyword-arguments
+         (package-arguments linux)
+       ((#:imported-modules imported-modules %gnu-build-system-modules)
+        `((guix build kconfig) ,@imported-modules))
+       ((#:modules modules)
+        `((guix build kconfig) ,@modules))
+       ((#:phases phases)
+        #~(modify-phases #$phases
+           (replace 'configure
+             (lambda* (#:key inputs #:allow-other-keys #:rest arguments)
+               (let* ((srcarch
+                       #$(system->linux-srcarch (or (%current-target-system)
+                                                   (%current-system))))
+                      (configs (string-append "arch/" srcarch "/configs/"))
+                      (guix_defconfig (string-append configs "guix_defconfig")))
+                 #$(cond
+                   ((not defconfig)
+                    #~(begin
+                       ;; Call the original 'configure phase.
+                       (apply (assoc-ref #$phases 'configure) arguments)
+                       ;; Save a defconfig file.
+                       (invoke "make" "savedefconfig")
+                       ;; Move the saved defconfig to the proper location.
+                       (rename-file "defconfig"
+                                    guix_defconfig)))
+                   ((string? defconfig)
+                    ;; Use another existing defconfig from the Linux sources.
+                    $~(rename-file (string-append configs #$defconfig)
+                                  guix_defconfig))
+                   (else
+                    ;; Copy the defconfig input to the proper location.
+                    '(copy-file (assoc-ref inputs "guix_defconfig")
+                                guix_defconfig)))
+                 (modify-defconfig guix_defconfig '#$configs)
+                 #$@(if extra-version
+                       `((setenv "EXTRAVERSION"
+                                 ,(string-append "-" extra-version)))
+                       '())
+                 (invoke "make" "guix_defconfig"))))))))
+    (native-inputs
+     (append (if (or (not defconfig)
+                     (string? defconfig))
+                 '()
+                 ;; The defconfig should be a package or file-like object.
+                 `(("guix_defconfig" ,defconfig)))
+             (package-native-inputs linux)))))
+
+(define-public (make-defconfig uri sha256-as-base32)
+  (origin (method url-fetch)
+          (uri uri)
+          (sha256 (base32 sha256-as-base32))))
 
 
 ;;;
-- 
2.34.0
From 95da83f1159ab280b2313b816ce7841f5fbdb06f Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:32 +0200
Subject: [PATCH v5 6/8] gnu: raspberry-pi: Add helpers for config.txt file
generation.

* gnu/packages/raspberry-pi.scm (raspi-config-file, raspi-custom-txt):
New functions.
(%raspi-config-txt, %raspi-bcm27-dtb-txt, %raspi-bcm28-dtb-txt
%raspi-u-boot-bootloader-txt): New variables.

Toggle diff (66 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index a2ab300531..0707516f72 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -238,6 +238,59 @@ (define-public raspi-arm64-chainloader
                #t))))))))
     (supported-systems '("aarch64-linux"))))
 
+(define-public (raspi-config-file name content)
+  "Make a configuration file like config.txt for the Raspberry Pi firmware.
+CONTENT can be a list of strings, which are concatenated with a newline
+character.  Alternatively CONTENT can be a string with the full file content."
+  (plain-file
+   name
+   (if (list? content)
+       (string-join content "\n" 'suffix)
+       content)))
+
+(define-public %raspi-config-txt
+  ;; A config.txt file to start the ARM cores up in 64-bit mode if necessary
+  ;; and to include a dtb.txt, bootloader.txt, and a custom.txt, each with
+  ;; separated configurations for the Raspberry Pi firmware.
+  (raspi-config-file
+   "config.txt"
+   `("# See https://www.raspberrypi.org/documentation/configuration/config-txt/README.md for details."
+     ""
+     ,(string-append "arm_64bit=" (if (target-aarch64?) "1" "0"))
+     "include dtb.txt"
+     "include bootloader.txt"
+     "include custom.txt")))
+
+(define-public %raspi-bcm27-dtb-txt
+  ;; A dtb.txt file to be included by the config.txt to ensure that the
+  ;; downstream device tree files bcm27*.dtb will be used.
+  (raspi-config-file
+   "dtb.txt"
+   "upstream_kernel=0"))
+
+(define-public %raspi-bcm28-dtb-txt
+  ;; A dtb.txt file to be included by the config.txt to ensure that the
+  ;; upstream device tree files bcm28*.dtb will be used.
+  ;; This also implies the use of the dtoverlay=upstream.
+  (raspi-config-file
+   "dtb.txt"
+   "upstream_kernel=1"))
+
+(define-public %raspi-u-boot-bootloader-txt
+  ;; A bootloader.txt file to be included by the config.txt to load the
+  ;; U-Boot bootloader.
+  (raspi-config-file
+   "bootloader.txt"
+   '("dtoverlay=upstream"
+     "enable_uart=1"
+     "kernel=u-boot.bin")))
+
+(define-public (raspi-custom-txt content)
+  "Make a custom.txt file for the Raspberry Pi firmware.
+CONTENT can be a list of strings, which are concatenated with a newline
+character.  Alternatively CONTENT can be a string with the full file content."
+  (raspi-config-file "custom.txt" content))
+
 (define (make-raspi-defconfig arch defconfig sha256-as-base32)
   "Make for the architecture ARCH a file-like object from the DEFCONFIG file
 with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
-- 
2.34.0
From 428de0cbfb9f03c14f88b9db5e56181ef759d7eb Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:25 +0200
Subject: [PATCH v5 5/8] gnu: raspberry-pi: Add defconfig objects to build
customized Linux kernels.

gnu/packages/raspberry-pi.scm (make-raspi-defconig): New function to make
downloaded defconfig objects from the Linux repository of the Raspberry Pi
Foundation.
(%bcm2709-defconfig, %bcm2710-defconfig, %bcm2711-defconfig,
%bcm2835-defconfig, %bcmrpi-defconfig, %bcm2711-defconfig-64,
%bcmrpi3-defconfig): New variables containing defconfig objects to build
Linux kernels customized for Raspberry Pi single board computers.

Toggle diff (69 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index bb38b8b218..a2ab300531 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -25,9 +26,10 @@ (define-module (gnu packages raspberry-pi)
   #:use-module (gnu packages commencement)
   #:use-module (gnu packages cross-base)
   #:use-module (gnu packages documentation)
+  #:use-module (gnu packages embedded)
   #:use-module (gnu packages file)
   #:use-module (gnu packages gcc)
-  #:use-module (gnu packages embedded)
+  #:use-module (gnu packages linux)
   #:use-module (guix build-system gnu)
   #:use-module (guix download)
   #:use-module (guix git-download)
@@ -235,3 +237,43 @@ (define-public raspi-arm64-chainloader
                (install-file "arm64.bin" libexec)
                #t))))))))
     (supported-systems '("aarch64-linux"))))
+
+(define (make-raspi-defconfig arch defconfig sha256-as-base32)
+  "Make for the architecture ARCH a file-like object from the DEFCONFIG file
+with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
+argument of the function (modify-linux)."
+  (make-defconfig
+   (string-append
+    "https://raw.githubusercontent.com/raspberrypi/linux/raspberrypi-kernel_1.20210430-1/arch/"
+    arch "/configs/" defconfig)
+   sha256-as-base32))
+
+(define-public %bcm2709-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2709_defconfig"
+   "0yvrmid2jakl929d1mv00gidnqbf91ffhj61c9gl75f7km48811c"))
+
+(define-public %bcm2711-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2711_defconfig"
+   "19hb6nwna7sk3b4rn5yjfhldrs3c1lv24q08w4gpa4xzh1byv7jj"))
+
+(define-public %bcm2835-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2835_defconfig"
+   "17dmvabqvxwqn6lgv1x8rfh2wqf1r2xmm10nkdnrgwkmgv8bh2d5"))
+
+(define-public %bcmrpi-defconfig
+  (make-raspi-defconfig
+   "arm" "bcmrpi_defconfig"
+   "0lcmr6nxdd53m3k8hqb5k6c5b7vbdgmfvcliqyl95snp45rxjjkw"))
+
+(define-public %bcm2711-defconfig-64
+  (make-raspi-defconfig
+   "arm64" "bcm2711_defconfig"
+   "0xf38nczwinr0j8vhsn8nd8h4ysjn77xphg7xnssz04gclb7fndr"))
+
+(define-public %bcmrpi3-defconfig
+  (make-raspi-defconfig
+   "arm64" "bcmrpi3_defconfig"
+   "01k098snd7kbmhz68j93mj2fwp39c56g9r8rgaw17js5r0w0zbhy"))
-- 
2.34.0
From 7e13ab0bb33e0f90b094ad4e2759e6e8bc1e8e9c Mon Sep 17 00:00:00 2001
From: Stefan <stefan-guix@vodafonemail.de>
Date: Wed, 13 Apr 2022 21:19:41 +0200
Subject: [PATCH v5 8/8] gnu: raspberry-pi: Add a bootloader-chain for the
Raspberry Pi and os examples.

* gnu/packages/raspberry-pi.scm (grub-efi-bootloader-chain-raspi-64): New
bootloader variable, capable to boot a Raspberry Pi over network or from a
local storage.
* gnu/system/examples/raspberry-pi-64.tmpl: New operating-system example.
* gnu/system/examples/raspberry-pi-64-nfs-root.tmpl: New operating-system
example for booting over network.

Toggle diff (206 lines)
diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index d808f61ac2..d52a4a72c5 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -18,11 +18,14 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu packages raspberry-pi)
+  #:use-module (gnu bootloader)
+  #:use-module (gnu bootloader grub)
   #:use-module (gnu packages)
   #:use-module (gnu packages admin)
   #:use-module (gnu packages algebra)
   #:use-module (gnu packages base)
   #:use-module (gnu packages bash)
+  #:use-module (gnu packages bootloaders)
   #:use-module (gnu packages commencement)
   #:use-module (gnu packages cross-base)
   #:use-module (gnu packages documentation)
@@ -312,6 +315,22 @@ (define-public (make-raspi-bcm28-dtbs linux)
      (simple-format #f "The device-tree files for Raspberry Pi models from ~a."
              (package-name linux)))))
 
+(define-public grub-efi-bootloader-chain-raspi-64
+  ;; A bootloader capable to boot a Raspberry Pi over network via TFTP or from
+  ;; a local storage like a micro SD card.
+  ;; It neither installs firmware nor device-tree files for the Raspberry Pi.
+  ;; It just assumes them to be existing in boot/efi in the same way that some
+  ;; UEFI firmware with ACPI data is usually assumed to be existing on PCs.
+  ;; It creates firmware configuration files and a bootloader-chain with U-Boot
+  ;; to provide an EFI API for the final GRUB bootloader.
+  ;; It also serves as a blue-print to create an own bootloader-chain with
+  ;; firmwre and device-tree packages or files.
+  (efi-bootloader-chain grub-efi-netboot-removable-bootloader
+                        #:packages (list u-boot-rpi-efi-64)
+                        #:files (list %raspi-config-txt
+                                      %raspi-bcm27-dtb-txt
+                                      %raspi-u-boot-bootloader-txt)))
+
 (define (make-raspi-defconfig arch defconfig sha256-as-base32)
   "Make for the architecture ARCH a file-like object from the DEFCONFIG file
 with the hash SHA256-AS-BASE32.  This object can be used as the #:defconfig
diff --git a/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl b/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
new file mode 100644
index 0000000000..c006a287fb
--- /dev/null
+++ b/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
@@ -0,0 +1,73 @@
+;; This is an operating-system configuration template of a
+;; 64-bit minimal system for a Raspberry Pi with an NFS root file-system.
+
+;; It neither installs firmware nor device-tree files for the Raspberry Pi.
+;; It just assumes them to be existing in boot/efi in the same way that some
+;; UEFI firmware with ACPI data is usually assumed to be existing on PCs.
+
+;; It expects the boot/efi directory to be served via TFTP and the root
+;; file-system to be served via NFS. See the grub-efi-netboot-bootloader
+;; description in the manual for more details.
+
+(use-modules (gnu)
+             (gnu artwork)
+             (gnu system nss))
+(use-service-modules admin
+                     avahi
+                     networking
+                     ssh)
+(use-package-modules certs
+                     linux
+                     raspberry-pi
+                     ssh)
+
+(define %my-public-key
+  (local-file (string-append (getenv "HOME") "/.ssh/id_ecdsa.pub")))
+
+(define-public raspberry-pi-64-nfs-root
+  (operating-system
+   (host-name "raspberrypi-guix")
+   (timezone "Europe/Berlin")
+   (bootloader (bootloader-configuration
+                (bootloader grub-efi-bootloader-chain-raspi-64)
+                (targets '("/boot/efi"))
+                (theme (grub-theme (resolution '(1920 . 1080))
+                       (image (file-append
+                               %artwork-repository
+                               "/grub/GuixSD-fully-black-16-9.svg"))))))
+   (kernel-arguments '("ip=dhcp"))
+   (kernel (modify-linux #:linux linux-libre-arm64-generic
+                         #:extra-version "arm64-generic-netboot"
+                         #:configs '("CONFIG_NFS_SWAP=y"
+                                     "CONFIG_USB_USBNET=y"
+                                     "CONFIG_USB_LAN78XX=y"
+                                     "CONFIG_USB_NET_SMSC95XX=y")))
+   (initrd-modules '())
+   (file-systems (cons* (file-system
+                         (mount-point "/")
+                         (type "nfs")
+                         (device ":/export/raspberrypi/guix")
+                         (options "addr=10.20.30.40,vers=4.1"))
+                        %base-file-systems))
+   (swap-devices (list (swap-space (target "/run/swapfile"))))
+   (users (cons* (user-account
+                  (name "pi")
+                  (group "users")
+                  (supplementary-groups '("wheel" "netdev" "audio" "video"))
+                  (home-directory "/home/pi"))
+                 %base-user-accounts))
+   (packages (cons* nss-certs
+                    openssh
+                    %base-packages))
+   (services (cons* (service avahi-service-type)
+                    (service dhcp-client-service-type)
+                    (service ntp-service-type)
+                    (service openssh-service-type
+                             (openssh-configuration
+                              (x11-forwarding? #t)
+                              (authorized-keys
+                              `(("pi" ,%my-public-key)))))
+                    %base-services))
+   (name-service-switch %mdns-host-lookup-nss)))
+
+raspberry-pi-64-nfs-root
diff --git a/gnu/system/examples/raspberry-pi-64.tmpl b/gnu/system/examples/raspberry-pi-64.tmpl
new file mode 100644
index 0000000000..6b0178c861
--- /dev/null
+++ b/gnu/system/examples/raspberry-pi-64.tmpl
@@ -0,0 +1,77 @@
+;; This is an operating-system configuration template of a
+;; 64-bit minimal system for a Raspberry Pi with local storage.
+
+;; It neither installs firmware nor device-tree files for the Raspberry Pi.
+;; It just assumes them to be existing in boot/efi in the same way that some
+;; UEFI firmware with ACPI data is usually assumed to be existing on PCs.
+
+;; It expects the boot-partition to be mounted as boot/efi in the same way
+;; as it is usually expeted on PCs with UEFI firmware.
+
+(use-modules (gnu)
+             (gnu artwork)
+             (gnu system nss))
+(use-service-modules admin
+                     avahi
+                     networking
+                     ssh)
+(use-package-modules certs
+                     linux
+                     raspberry-pi
+                     ssh)
+
+(define %my-public-key
+  (local-file (string-append (getenv "HOME") "/.ssh/id_ecdsa.pub")))
+
+(define-public raspberry-pi-64
+  (operating-system
+   (host-name "raspberrypi-guix")
+   (timezone "Europe/Berlin")
+   (bootloader (bootloader-configuration
+                (bootloader grub-efi-bootloader-chain-raspi-64)
+                (targets '("/boot/efi"))
+                (theme (grub-theme (resolution '(1920 . 1080))
+                       (image (file-append
+                               %artwork-repository
+                               "/grub/GuixSD-fully-black-16-9.svg"))))))
+   (kernel (modify-linux #:linux linux-libre-arm64-generic
+                         #| It is possible to use a specific defconfig file,
+                            for example the "bcmrpi3_defconfig" with the
+                            variable shown below.  Unfortunately the kernel
+                            build from the linux-libre sources with this
+                            defconfig file does not boot.
+                            #:extra-version "gnu-bcmrpi3"
+                            #:defconfig %bcmrpi3-defconfig
+                         |#))
+   (initrd-modules '())
+   (file-systems (cons* (file-system
+                         (mount-point "/")
+                         (type "ext4")
+                         (device (file-system-label "Guix")))
+                        (file-system
+                         (mount-point "/boot/efi")
+                         (type "vfat")
+                         (device (file-system-label "EFI")))
+                        %base-file-systems))
+   (swap-devices (list (swap-space (target "/run/swapfile"))))
+   (users (cons* (user-account
+                  (name "pi")
+                  (group "users")
+                  (supplementary-groups '("wheel" "netdev" "audio" "video"))
+                  (home-directory "/home/pi"))
+                 %base-user-accounts))
+   (packages (cons* nss-certs
+                    openssh
+                    %base-packages))
+   (services (cons* (service avahi-service-type)
+                    (service dhcp-client-service-type)
+                    (service ntp-service-type)
+                    (service openssh-service-type
+                             (openssh-configuration
+                              (x11-forwarding? #t)
+                              (authorized-keys
+                              `(("pi" ,%my-public-key)))))
+                    %base-services))
+   (name-service-switch %mdns-host-lookup-nss)))
+
+raspberry-pi-64
-- 
2.34.0
P
P
phodina wrote on 14 Apr 15:03 +0200
(name . Maxime Devos)(address . maximedevos@telenet.be)
_G8Wp0VvUVQwRBwRglLXwBugZu8x_4_D739HjTzIFUqEBlHTehUq9JkCc0pSXhvZC1bJZTlFicZBHYs5ZROL_4LVIPQs34I2b7OymZM0FNU=@protonmail.com
Here's more details about the login issue.

I've chrooted into the SDcard and setup the password for the pi user manually.

Then booted the board and login:

~$ ssh pi@192.168.1.181
Last login: Thu Apr 14 14:52:56 2022 from 192.168.1.224
Could not chdir to home directory /home/pi: Permission denied
-bash: /home/pi/.bash_profile: Permission denied
-bash-5.1$ id -u
1002
-bash-5.1$ id -gn
users
-bash-5.1$ sudo -E /gnu/store/ja92d7xpmyh94gm6n83bajx9dy4h6pbl-bash-5.1.8/bin/bash
root@raspberrypi-guix /# ls -al /home/pi
total 40
drwx------ 4 1000 users 4096 Nov 24 08:16 ./
drwxr-xr-x 4 root root 4096 Jan 1 1970 ../
-rw-r--r-- 1 1000 users 85 Jan 1 1970 .bash_profile
-rw-r--r-- 1 1000 users 834 Jan 1 1970 .bashrc
drwxr-xr-x 3 1000 users 4096 Jan 1 1970 .config/
-rw-r--r-- 1 1000 users 235 Jan 1 1970 .gdbinit
-rw-r--r-- 1 1000 users 789 Jan 1 1970 .guile
drwxr-xr-x 2 root root 4096 Nov 24 08:16 .ssh/
-rw-r--r-- 1 1000 users 47 Jan 1 1970 .Xdefaults
-rw-r--r-- 1 1000 users 62 Jan 1 1970 .zprofile


As you can see the execute bit is missing. Therefore running

chmod +x /home/pi/

fixed the problem. But I'm unsure why the home dir was created without the those flags.

Is it a side effect of using the following declaration?

(home-directory "/home/pi")

----
Petr
M
M
Maxime Devos wrote on 14 Apr 15:57 +0200
(name . phodina)(address . phodina@protonmail.com)
80407def8662e15c9a6ab7ffcfaaa89137641747.camel@telenet.be
phodina schreef op do 14-04-2022 om 13:03 [+0000]:
Toggle quote (13 lines)
> ~$ ssh pi@192.168.1.181
> Last login: Thu Apr 14 14:52:56 2022 from 192.168.1.224
> Could not chdir to home directory /home/pi: Permission denied
> -bash: /home/pi/.bash_profile: Permission denied
> -bash-5.1$ id -u
> 1002
> -bash-5.1$ id -gn
> users
> -bash-5.1$ sudo -E /gnu/store/ja92d7xpmyh94gm6n83bajx9dy4h6pbl-bash-5.1.8/bin/bash
> root@raspberrypi-guix /# ls -al /home/pi
> total 40
> drwx------ 4 1000 users 4096 Nov 24 08:16 ./

You are logging in as 1002. /home/pi is owned by ‘1000’.  Is this
difference intentional?

Maybe you have added two users, but with the home directory?
(guesswork).

Toggle quote (2 lines)
> As you can see the execute bit is missing. Therefore running

The user has the read-write-execute bits, the group and other don't.

Toggle quote (5 lines)
> chmod +x /home/pi/
>
> fixed the problem. But I'm unsure why the home dir was created
> without the those flags.

I'm not on Guix System at the moment, so I cannot tell what the usual
behaviour is, but why wouldn't the home directory be non-group-
executable and non-other executable? 

Unless you want to share the contents of your home to other users on
the system, or if you have a web server that looks for
http://.../~pi/index.html in /home/pi/web/index.html or the like,
restricting readability, writability and executability to the actual
‘owner’ of the directory seems good security practice to me.

Usually, AFAICT, all that's needed is for $HOME to be user-readable,
writable and executable.

(/me quickly does "chmod go-rwx $HOME")

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYlgoTxccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7ofTAP4m9v+xx+ODX/ys/yU5lzerybnC
tIxqzeIQNpw5I/3HNwEAyeDw2MPo0n0NpfAhS+maT1nRfpD+Qgv1MpADGo8rdA4=
=gFe5
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 14 Apr 16:00 +0200
(name . phodina)(address . phodina@protonmail.com)
5d9ba4b6fcbeb602c9d187611fd65606622549cf.camel@telenet.be
phodina schreef op do 14-04-2022 om 12:23 [+0000]:
Toggle quote (11 lines)
> However, I experience an issue when login into the system. I can get
> there using my SSH key, but it seems the passwd set-uid binary is
> missing from the profile:
>
> $ ssh pi@192.168.1.181
> You are required to change your password immediately (administrator
> enforced).
> WARNING: Your password has expired.
> passwd: no such file or directory
> [...]

I don't know what's going in here, though the ‘passwd not in $PATH’
seems a plausible hypothesis to me.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYlgpCxccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7lSOAQCyLEiyKCA7oChvitNIJYOK8qaF
ItmKymjIfR/qUz5H6QEAtCl/6bD5kS8F2A+fsfHGzNouFVncYczyvXLRtVuBEgg=
=7eTr
-----END PGP SIGNATURE-----


M
M
Maxime Devos wrote on 14 Apr 16:06 +0200
Re: [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
08d2e5f4167486be4be7ef0dc024f1e2137b4bdf.camel@telenet.be
phodina via Guix-patches via schreef op do 14-04-2022 om 07:38 [+0000]:
Toggle quote (4 lines)
> I've also attempted to cross-compile the system (from x86_64) but
> there is at least one package that can't be build - guile-fibers-
> 1.1.0. I've attached the build log as well.

This one should now be fixed by

1f82602153 gnu: guile-fibers@1.1: Support cross-compilation.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYlgqexccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7rT5AP9dGOLYZ984EsaZMRXS87uTZPKq
axF1JfaT5vtWh01rZgD+NSt5pjJa3b/9Vx2mZ5EPqggr9G/1ilndgLuXNeqBJgc=
=PC2/
-----END PGP SIGNATURE-----


P
P
phodina wrote on 14 Apr 17:53 +0200
[bug#48314] [PATCH v3] Install guix system on Raspberry Pi
(name . Maxime Devos)(address . maximedevos@telenet.be)
NahlaZknYPJe6yty_Ivn-Wj6I65H9wNMtiD8-4pz5q6e8lten7MrpPxpotIlQ2u0QgVf3V-gAHOHYw3H-ZzRmU2NN5em5vSOruAT8Dc7uxc=@protonmail.com
Toggle quote (13 lines)
>
> > I've also attempted to cross-compile the system (from x86_64) but
> > there is at least one package that can't be build - guile-fibers-
> > 1.1.0. I've attached the build log as well.
>
>
> This one should now be fixed by
>
> 1f82602153 gnu: guile-fibers@1.1: Support cross-compilation.
>
> Greetings,
> Maxime.

Yes,

guile-fibers are now fixed, but the cross compile build fails now on shepherd-0.9 due to guile-fibers not being available.

Also the NTP requires this configure flag.

Toggle diff (17 lines)
diff --git a/gnu/packages/ntp.scm b/gnu/packages/ntp.scm
index 7a3c033b2e..cb90432730 100644
--- a/gnu/packages/ntp.scm
+++ b/gnu/packages/ntp.scm
@@ -153,7 +153,8 @@ (define-public ntp
             `(("libcap" ,libcap))
             '())))
    (arguments
-    `(#:phases
+    `(#:configure-flags (list "--with-yielding-select=yes")
+      #:phases
       (modify-phases %standard-phases
         (add-after 'unpack 'disable-network-test
                    (lambda _

----
Petr
V
V
Vagrant Cascadian wrote on 14 Apr 17:56 +0200
Re: [PATCH v3] Install guix system on Raspberry Pi
87a6cnvetx.fsf@contorta
On 2022-04-14, phodina@protonmail.com wrote:
Toggle quote (4 lines)
> (u-boot-rpi-0-w, u-boot-rpi, u-boot-rpi-2, u-boot-rpi-3, u-boot-rpi-4,
> u-boot-rpi-64, u-boot-rpi-0-w-efi, u-boot-rpi-efi, u-boot-rpi-2-efi,
> u-boot-rpi-3-efi, u-boot-rpi-4-efi, u-boot-rpi-efi-64): New packages.

Comments from November are still relevent:


(e.g. drop drop u-boot-rpi-0-w*, u-boot-rpi, u-boot-rpi-efi, maybe
consider droping u-boot-rpi-2* and the 32-bit variants for rpi3 and
rpi4, as armhf is not well maintained at the moment).

Basically, ARMv6 is not supportable by guix, ARMv7 is poorly supported
in the armhf architecture, and ARMv8 is capable of running aarch64
(a.k.a. arm64):



Only proposing aarch64 variants would pretty much leave you with
rpi-arm64. The EFI variants and 32-bit variants supported on armhf could
be easily added later once the other patches land.


Toggle quote (5 lines)
> +(define-public %u-boot-rpi-efi-configs
> + '("CONFIG_OF_EMBED="
> + "CONFIG_OF_BOARD=y"
> + "CONFIG_BOOTDELAY=0"))

See comment:


e.g. Please do not set BOOTDELAY=0. It makes it nearly impossible to
debug. For people who want to live on the edge, they could build custom
variants and set it to 0.


Toggle quote (7 lines)
> +(define-public u-boot-rpi-64
> + (make-preinstalled-u-boot-package
> + "rpi_arm64"
> + "aarch64-linux-gnu"
> + #:name "rpi-64"
> + #:description %u-boot-rpi-description-64-bit))

Please keep package names consistent with defconfig
name. (e.g. u-boot-rpi-arm64). It's confusing enough without extra newly
invented names! :)


Toggle quote (8 lines)
> +(define-public u-boot-rpi-3-efi
> + (make-preinstalled-u-boot-package
> + "rpi_3_32b"
> + "arm-linux-gnueabihf"
> + #:name "rpi-3-efi"
> + #:configs %u-boot-rpi-efi-configs
> + #:description %u-boot-rpi-efi-description-32-bit))

Ditto, or drop this variant; same for the 32-bit rpi-4 variants.


Toggle quote (2 lines)
> Subject: [PATCH v3 2/8] build: kconfig: Add new module to modify a defconfig
> file.
...
Toggle quote (20 lines)
> (define-public u-boot-pinebook
> - (let ((base (make-u-boot-sunxi64-package "pinebook" "aarch64-linux-gnu")))
> - (package
> - (inherit base)
> - (arguments
> - (substitute-keyword-arguments (package-arguments base)
> - ((#:phases phases)
> - `(modify-phases ,phases
> - (add-after 'unpack 'patch-pinebook-config
> - ;; Fix regression with LCD video output introduced in 2020.01
> - ;; https://patchwork.ozlabs.org/patch/1225130/
> - (lambda _
> - (substitute* "configs/pinebook_defconfig"
> - (("CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y") "CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y\nCONFIG_VIDEO_BPP32=y"))
> - #t)))))))))
> + (make-u-boot-sunxi64-package "pinebook" "aarch64-linux-gnu"
> + ;; Fix regression with LCD video output introduced in 2020.01
> + ;; https://patchwork.ozlabs.org/patch/1225130/
> + #:configs '("CONFIG_VIDEO_BPP32=y")))

I like how this simplifies the package definitions where you need to
adjust the defconfig!

This particular workaround for u-boot-pinebook may no longer be needed,
thanks for the reminder to check.


Toggle quote (7 lines)
> (define-public u-boot-novena
> - (let ((base (make-u-boot-package "novena" "arm-linux-gnueabihf")))
> + (let ((base (make-u-boot-package "novena" "arm-linux-gnueabihf"
> + ;; Patch configuration to disable loading u-boot.img from FAT
> + ;; partition, allowing it to be installed at a device offset.
> + #:configs '("CONFIG_SPL_FS_FAT="))))

Maybe this is different in upstream u-boot, but in the past setting it
to an empty value could result in the default value, which is why:

Toggle quote (4 lines)
> - (substitute* "configs/novena_defconfig"
> - (("CONFIG_SPL_FS_FAT=y") "# CONFIG_SPL_FS_FAT is not set"))
> - #t)))))))))

... was used previously.


Toggle quote (11 lines)
> Subject: [PATCH v3 5/8] gnu: raspberry-pi: Add defconfig objects to build
> customized Linux kernels.
>
> gnu/packages/raspberry-pi.scm (make-raspi-defconig): New function to make
> downloaded defconfig objects from the Linux repository of the Raspberry Pi
> Foundation.
> (%bcm2709-defconfig, %bcm2710-defconfig, %bcm2711-defconfig,
> %bcm2835-defconfig, %bcmrpi-defconfig, %bcm2711-defconfig-64,
> %bcmrpi3-defconfig): New variables containing defconfig objects to build
> Linux kernels customized for Raspberry Pi single board computers.

Similar to my comments on u-boot variants, some of these are for models
that are not supportable on guix (rpi, rpi-0), so probably best to leave
out entirely, and the 32-bit variants for armhf are debatable at this
point.


live well,
vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYlhEKwAKCRDcUY/If5cW
qtkeAP0c+M3oO8eUcFKXVFHoY5Kr8nwQTvh3udPDYOmaNMj7dAEA9f69eAL8ydg4
T05WR5yUZNqKRMmBCjkkGnGgSe+fmw0=
=tQLe
-----END PGP SIGNATURE-----

M
M
Maxime Devos wrote on 14 Apr 19:33 +0200
Re: [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
(name . phodina)(address . phodina@protonmail.com)
751092aecc38c221e13af71417e1ccace8c875eb.camel@telenet.be
phodina schreef op do 14-04-2022 om 15:53 [+0000]:
Toggle quote (5 lines)
> Yes,
>
> guile-fibers are now fixed, but the cross compile build fails now on
> shepherd-0.9 due to guile-fibers not being available.

Possibly the problem is just that guile-fibers is only in 'inputs' and
not 'native-inputs' -- due to how compilation and the module system
works in Guile, they need to be in both.

Greetings,
Maxime.
-----BEGIN PGP SIGNATURE-----

iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYlhazRccbWF4aW1lZGV2
b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7r/ZAQCnEfmywGkenWDS3A2JNh9qQdtu
jRpOnoQsgg99DbyIFQD8C002b/XUYvQ/edQSMYmNGDyivkxp+z4WG4DLi8sJBw0=
=S//B
-----END PGP SIGNATURE-----


L
L
Ludovic Courtès wrote on 15 Apr 19:17 +0200
(name . phodina)(address . phodina@protonmail.com)
8735ie2rmk.fsf@gnu.org
Hi,

phodina <phodina@protonmail.com> skribis:

Toggle quote (2 lines)
> guile-fibers are now fixed, but the cross compile build fails now on shepherd-0.9 due to guile-fibers not being available.

Fixed as suggested by Maxime in commit
6e174c4edd4786d93c1e424c45052f70b2bb3fb0.

Let us know what the next issue is. :-)

Ludo’.
P
P
phodina wrote on 16 Apr 10:53 +0200
[bug#48314] [PATCH v3] Install guix system on Raspberry Pi
(name . Ludovic Courtès)(address . ludo@gnu.org)
jkij6oekyUn8DqK6_m4EywMRdoo9AgSm7gR2Sz4yXlZHoqzdbwZCvVTndCprkwFoQV-6VeH3ZV52aNIeB9fRQVK4FnIeFG0FJi9dCbMDeCk=@protonmail.com
Toggle quote (10 lines)
> > guile-fibers are now fixed, but the cross compile build fails now on shepherd-0.9 due to guile-fibers not being available.
>
>
> Fixed as suggested by Maxime in commit
> 6e174c4edd4786d93c1e424c45052f70b2bb3fb0.
>
> Let us know what the next issue is. :-)
>
> Ludo’.

Thanks Maxime for the advice and for Ludo' for applying the change!

I've rebased the patches from Stefan and there are only two packages that don't cross-compile - nss-certs and ntp.

I attempted to do guix pull on Raspberry Pi 3, but it failed due to running of memory - I'll attempt to test it with a swap file/partition.

Or is it possible to do guix pull using a substitute so that the computation wouldn't be done locally? This offloading would be really great for these embedded platforms.


----
Petr
From deab687c2b0540a944b48c68fa00cac4bac99b80 Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Sat, 16 Apr 2022 10:22:14 +0200
Subject: [PATCH 1/2] gnu: nss-certs: Support cross-compilation.

* gnu/packages/certs.scm (nss-certs)[arguments]: Fix unresolved
variable - output.

Toggle diff (25 lines)
diff --git a/gnu/packages/certs.scm b/gnu/packages/certs.scm
index 28c2f84f98..63486b596c 100644
--- a/gnu/packages/certs.scm
+++ b/gnu/packages/certs.scm
@@ -7,6 +7,7 @@
 ;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;; Copyright © 2021 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2021 Raghav Gururajan <rg@raghavgururajan.name>
+;;; Copyright © 2022 Petr Hodina <phodina@protonmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -168,8 +169,8 @@ (define-public nss-certs
            (map (cut assq <> %standard-phases)
                 '(set-paths install-locale unpack))
          (add-after 'unpack 'install
-           (lambda _
-             (let ((certsdir (string-append %output "/etc/ssl/certs/")))
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((certsdir (string-append (assoc-ref outputs "out") "/etc/ssl/certs/")))
                (with-directory-excursion "nss/lib/ckfw/builtins/"
                  (unless (file-exists? "blacklist.txt")
                    (call-with-output-file "blacklist.txt" (const #t)))
-- 
2.35.1
From 98ad94f6282d8ff3a244181ecc32946ea281aa03 Mon Sep 17 00:00:00 2001
From: Petr Hodina <phodina@protonmail.com>
Date: Sat, 16 Apr 2022 10:24:46 +0200
Subject: [PATCH 2/2] gnu: ntp: Support cross-compilation.

* gnu/packages/ntp.scm (ntp)[arguments]: Add configuration flag.

Toggle diff (24 lines)
diff --git a/gnu/packages/ntp.scm b/gnu/packages/ntp.scm
index 7a3c033b2e..a64861d7fd 100644
--- a/gnu/packages/ntp.scm
+++ b/gnu/packages/ntp.scm
@@ -8,6 +8,7 @@
 ;;; Copyright © 2019 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;; Copyright © 2021 Marius Bakke <marius@gnu.org>
 ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
+;;; Copyright © 2022 Petr Hodina <phodina@protonmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -153,7 +154,8 @@ (define-public ntp
             `(("libcap" ,libcap))
             '())))
    (arguments
-    `(#:phases
+    `(#:configure-flags (list "--with-yielding-select=yes")
+      #:phases
       (modify-phases %standard-phases
         (add-after 'unpack 'disable-network-test
                    (lambda _
-- 
2.35.1
L
L
Ludovic Courtès wrote on 18 Apr 23:00 +0200
(name . phodina)(address . phodina@protonmail.com)
87lew2umwt.fsf@gnu.org
Hi,

phodina <phodina@protonmail.com> skribis:

Toggle quote (6 lines)
> I've rebased the patches from Stefan and there are only two packages that don't cross-compile - nss-certs and ntp.
>
> I attempted to do guix pull on Raspberry Pi 3, but it failed due to running of memory - I'll attempt to test it with a swap file/partition.
>
> Or is it possible to do guix pull using a substitute so that the computation wouldn't be done locally? This offloading would be really great for these embedded platforms.

Normally you should be able to get substitutes, making ‘guix pull’
actually usable on these platforms. But I’m not sure what the status is
on armhf-linux. This platform needs love!

Toggle quote (8 lines)
> From deab687c2b0540a944b48c68fa00cac4bac99b80 Mon Sep 17 00:00:00 2001
> From: Petr Hodina <phodina@protonmail.com>
> Date: Sat, 16 Apr 2022 10:22:14 +0200
> Subject: [PATCH 1/2] gnu: nss-certs: Support cross-compilation.
>
> * gnu/packages/certs.scm (nss-certs)[arguments]: Fix unresolved
> variable - output.

I addressed this one differently to avoid rebuilding the 600+ packages
that depends on nss-certs.

Toggle quote (7 lines)
> From 98ad94f6282d8ff3a244181ecc32946ea281aa03 Mon Sep 17 00:00:00 2001
> From: Petr Hodina <phodina@protonmail.com>
> Date: Sat, 16 Apr 2022 10:24:46 +0200
> Subject: [PATCH 2/2] gnu: ntp: Support cross-compilation.
>
> * gnu/packages/ntp.scm (ntp)[arguments]: Add configuration flag.

I added a comment explaining why this flag is needed and committed.

Should we close this issue now?

Thanks!

Ludo’.
P
P
phodina wrote on 21 Apr 12:52 +0200
(name . Ludovic Courtès)(address . ludo@gnu.org)
d3ZYuSQwiQvASa1af25ttEUEsH7M323cKXlUrR4uSB2lHD1QZkqxtFdCRAagPmpaJZPO8adacXggdUu2HivzyyC3qBSGS1sRnyxyB2nL4vE=@protonmail.com
Toggle quote (43 lines)
> Hi,
>
> phodina phodina@protonmail.com skribis:
>
> > I've rebased the patches from Stefan and there are only two packages that don't cross-compile - nss-certs and ntp.
> >
> > I attempted to do guix pull on Raspberry Pi 3, but it failed due to running of memory - I'll attempt to test it with a swap file/partition.
> >
> > Or is it possible to do guix pull using a substitute so that the computation wouldn't be done locally? This offloading would be really great for these embedded platforms.
>
>
> Normally you should be able to get substitutes, making ‘guix pull’
> actually usable on these platforms. But I’m not sure what the status is
> on armhf-linux. This platform needs love!
>
> > From deab687c2b0540a944b48c68fa00cac4bac99b80 Mon Sep 17 00:00:00 2001
> > From: Petr Hodina phodina@protonmail.com
> > Date: Sat, 16 Apr 2022 10:22:14 +0200
> > Subject: [PATCH 1/2] gnu: nss-certs: Support cross-compilation.
> >
> > * gnu/packages/certs.scm (nss-certs)[arguments]: Fix unresolved
> > variable - output.
>
>
> I addressed this one differently to avoid rebuilding the 600+ packages
> that depends on nss-certs.
>
> > From 98ad94f6282d8ff3a244181ecc32946ea281aa03 Mon Sep 17 00:00:00 2001
> > From: Petr Hodina phodina@protonmail.com
> > Date: Sat, 16 Apr 2022 10:24:46 +0200
> > Subject: [PATCH 2/2] gnu: ntp: Support cross-compilation.
> >
> > * gnu/packages/ntp.scm (ntp)[arguments]: Add configuration flag.
>
>
> I added a comment explaining why this flag is needed and committed.
>
> Should we close this issue now?
>
> Thanks!
>
> Ludo’.

Thanks Ludo'!


Vagrant has valid points about the patches.

Stefan do you want to address them or shall I?

I can confirm the Raspberry Pi 3 can run Guix, but when I attempt to do simple `guix pull` it fails due to running out of memory (has just 1 GiB) therefore there is probably no point to run on less powerful boards.

Not sure if the computation can be offloaded by using substitutes.

It runs fine on Raspberry Pi 4 where there is 4GiB of memory (at least in my case :) - the variant with just one 1GiB would have probably same result as RPi3.

----
Petr
S
S
Stefan wrote on 21 Apr 21:32 +0200
(name . phodina)(address . phodina@protonmail.com)
AA43CB88-2461-4864-BB49-0FAD2A766B7D@vodafonemail.de
Hi Petr!

Toggle quote (4 lines)
> Vagrant has valid points about the patches.
>
> Stefan do you want to address them or shall I?

I have already patches to address the review comments from Vagrant, actually for months; also including improvements (e.g. checking that defconfig changes are successfully applied, which is not guaranteed).

Beside a lack of time, it is as you said: Building with 1 GB RAM is very problematic. Swap space is a requirement. Building takes days, using make with sub-targets helps a bit. In recent Linux kernels the virtual memory handling is badly broken; the build process gets killed, although there is empty swap space. Only version 5.4 is still fine. Without other hardware offloading or cross-building is not an option. Substitutes of guix, Linux, which needs special config settings, U-Boot and I think GRUB, are not – can’t be – available. Last time I tried at least qemu – an input of GRUB – had build issues on aarch64 and was missing a substitute. For Linux I meanwhile need to remove the deblob-check, as it even exhausts my swap space.

I’m hesitant to submit my untestet patches. I hope to find some time on the weekend – and that I don’t make mistakes, as my turn-around-time is close to a week. ;-)

By the way: I have the feeling that a garbage-collector may be a real bottle-neck, if most of a process’ memory is swapped out. I was surprised to not find papers about this. And once I was looking for options to limit the Guile heap, but didn’t find anything helpful.

Toggle quote (2 lines)
> It runs fine on Raspberry Pi 4 where there is 4GiB of memory

This is good to know, thanks!

Would you mind, if I send untested patches, which you could pick up? Is there a possibility to offload to ci.guix.gnu.org?


Bye

Stefan
V
V
Vagrant Cascadian wrote on 28 Apr 04:57 +0200
Re: [PATCH v3] Install guix system on Raspberry Pi
87tuadhq3d.fsf@contorta
On 2022-04-14, Vagrant Cascadian wrote:
Toggle quote (15 lines)
> On 2022-04-14, phodina@protonmail.com wrote:
> (e.g. drop drop u-boot-rpi-0-w*, u-boot-rpi, u-boot-rpi-efi, maybe
> consider droping u-boot-rpi-2* and the 32-bit variants for rpi3 and
> rpi4, as armhf is not well maintained at the moment).
>
> Basically, ARMv6 is not supportable by guix, ARMv7 is poorly supported
> in the armhf architecture, and ARMv8 is capable of running aarch64
> (a.k.a. arm64):
>
> https://en.wikipedia.org/wiki/Raspberry_Pi#Specifications
>
>
> Only proposing aarch64 variants would pretty much leave you with
> rpi-arm64.

Just tested this on an rpi3b+ and sometime between u-boot 2021.01 and
2021.04 rpi-arm64 fails to boot on rpi3b+ ... but does work with the
rpi_3 and rpi_3_b_plus defconfigs... so I guess that makes a case for
having multiple variants, even if rpi_arm64 theoretically supports all
the arm64 boards... hrm.

That said, now that I've been able to test it; I feel confident at least
adding a simple u-boot-rpi-3 and/or u-boot-rpi-3-b-plus package (without
most of the proposed changes). Even though I haven't been able to test
u-boot-rpi-arm64, might be worth adding just to get it out of the way.


I could also test booting the rpi2 variants, though as mentioned
earlier, I'm skeptical about adding more support until things improve
for armhf on guix.


live well,
vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYmoCpwAKCRDcUY/If5cW
qoDsAP9afw8hzCAE4v3A5hDThqmuVjJc6QY8GzcVXL6NfEf7vwEA77E5S47d/cPP
DkSqZtZiEAknwSKor+q2kfrru0GZ5QE=
=z51b
-----END PGP SIGNATURE-----

S
S
Stefan wrote on 28 Apr 08:05 +0200
(name . Vagrant Cascadian)(address . vagrant@debian.org)
81366405-13FD-4F0E-8180-4DFCB16A6C1A@vodafonemail.de
Hi Vagrant!

Toggle quote (3 lines)
> Just tested this on an rpi3b+ and sometime between u-boot 2021.01 and
> 2021.04 rpi-arm64 fails to boot on rpi3b+ ...

IWithin my patch series there is one patch to modify a defconfig file. I enhanced that patch meanwhile to check, that lines in the modified defconfig show up in the final .config file. Last weekend I found out that several settings differ. I also updated the raspberry specific defconfigs, but the mismatches still remain.

My guess is, that the kernel has problems booting. Did GRUB show up?

Toggle quote (4 lines)
> I feel confident at least
> adding a simple u-boot-rpi-3 and/or u-boot-rpi-3-b-plus package (without
> most of the proposed changes)

Please wait a bit longer, I addressed all your comments to U-Boot already.


Bye

Stefan
V
V
Vagrant Cascadian wrote on 28 Apr 17:25 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
87zgk5b56p.fsf@contorta
On 2022-04-28, Stefan wrote:
Toggle quote (9 lines)
>> Just tested this on an rpi3b+ and sometime between u-boot 2021.01 and
>> 2021.04 rpi-arm64 fails to boot on rpi3b+ ...
>
> IWithin my patch series there is one patch to modify a defconfig
> file. I enhanced that patch meanwhile to check, that lines in the
> modified defconfig show up in the final .config file. Last weekend I
> found out that several settings differ. I also updated the raspberry
> specific defconfigs, but the mismatches still remain.

Look forward to seeing an updated patch series!


Toggle quote (2 lines)
> My guess is, that the kernel has problems booting. Did GRUB show up?

I didn't test with grub, just the syslinux-style menus, but it didn't
even get as far as u-boot on the serial console with
rpi_arm64_defconfig. With either rpi_3_defconfig or
rpi_3_b_plus_defconfig, it worked just fine.

I had to set gpu_freq=250 in config.txt, which is a bit of a known
issue:



Toggle quote (6 lines)
>> I feel confident at least
>> adding a simple u-boot-rpi-3 and/or u-boot-rpi-3-b-plus package (without
>> most of the proposed changes)
>
> Please wait a bit longer, I addressed all your comments to U-Boot already.

I really don't see the harm in it, and actually see considerable benefit
to making a smaller diff for review as it is a huge patch series, but
I'm not planning on actually using guix on any rpi hardware anytime
soon, so... ok.


live well,
vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYmqx/wAKCRDcUY/If5cW
qjkKAP9vc2+oukmzm3VHNTCP0xSP8eDLjTUOb2ieoZijcBjvQgEAtRn2AaYgXMAo
FGdsy2yMy8eKCnw2aV7zFutax5qzmw4=
=6bDk
-----END PGP SIGNATURE-----

P
P
phodina wrote on 2 Jul 08:40 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
mPtBIj5SjqPth3NiS5EX4gEUUIO-Esboo3GtsDmm2YXjyuGmt_nFuyUf4ud-LbamW1JfMqWjOUkrLMnzZjWbcnZjpqRgHiu7X5cS2C3PY0g=@protonmail.com
Hi Stefan,

do you need help with the patches?

Also should we provide some patches to the upstream kernel in Guix? [1]

----
Petr
S
S
Stefan wrote on 17 Jul 18:47 +0200
Re: [bug#48314] Patches to install guix system on Raspberry Pi
(name . Vagrant Cascadian)(address . vagrant@debian.org)
E001BE99-09CF-4C11-85BD-1BE9D3E0DD80@vodafonemail.de
Hi Vagrant!


Toggle quote (2 lines)
> The u-boot-rpi-0-w and u-boot-rpi variants are ARMv6 boards, and Guix's armhf baseline is ARMv7, so those won't work with guix system.

Uups. I will remove them.

Toggle quote (2 lines)
> In other words, keep names consistent with the upstream defconfig they are based on.

OK

Toggle quote (2 lines)
> I presume you didn't add the aarch64 rpi_3 and rpi_4 variants because they are supported by rpi_arm64?

Yes.

Toggle quote (9 lines)
> I think without addressing the rest of the patch series, adding to guix master the following packages could make the remaining diff smaller:
>
> u-boot-rpi-2 (rpi_2_defconfig)
> u-boot-rpi-3-32b (rpi_3_32b_defconfig)
> u-boot-rpi-4-32b (rpi_4_32b_defconfig)
> u-boot-rpi-arm64 (rpi_arm64_defconfig)
>
> We wouldn't have a relevent installation configuration, but at least it would allow building them and manually copying u-boot.bin to the firmware partition…

Well, in the past I tried to get one patch into master before sending the next for review. Doing so I got the comment that it would be hard to test the changes, as they are not complete and don’t build a system. :-)

Toggle quote (2 lines)
> Which leads me to wonder, why have the name and description argument at all, when you could just inherit and set the name, like done with the boneblack?

For the same board name there will be two packages, the “normal” and an EFI variant. Having name-suffix and additional-description fields eases appending. I will change the parameters accordingly. Having these parameters also avoids to copy the U-Boot description, like done for the boneblack. A while back you fixed that description three times. :-)


Bye

Stefan
S
S
Stefan wrote on 17 Jul 18:47 +0200
(name . Vagrant Cascadian)(address . vagrant@debian.org)
86D908EE-955D-4EA1-AE2A-4072BB40468D@vodafonemail.de
Hi Vagrant!

Toggle quote (2 lines)
> u-boot-file appears to be hard-coded; there may be other boards which use a different u-boot artifact.

If you build U-Boot, there is also u-boot-nodtb.bin. Therefore the u-boot-file is a function argument to the public make-preinstalled-u-boot-package to allow a selection.

Toggle quote (2 lines)
> Also, why return a single file, rather than just building a package and then allowing other functions to pick the appropriate file out of the resulting package?

The reason is in the patch set 1: There is (already in master) a bootloader-profile which is able to collect a chain of bootloaders. The version in master allows a collection of files from packages, but requires a special installer. I figured out that the usage of the bootloader-profile gets much easier if the packages to chain only contain preselected files. From a user perspective the content of a complete bootloader-package is kind of a blackbox. When writing an operating-system configuration it is easy to figure out the right U-Boot package name, but no one expects to be required to install U-Boot in his profile to figure out that the u-boot.bin is below the libexec directory and that he is even required to care about moving the file around in directory hierarchies.

However, you are right that the make-preinstalled-u-boot-package could take another U-Boot package as argument, being that other function to pick the appropriate file. Then it might be useful for other boards, too. The only trouble to solve then is a proper package name. Currently using make-preinstalled-u-boot-package the result of make-u-boot-package is only an intermediate package prefixed with “-complete”. Then a preinstalled package needs a suffix like “-bin”. I think this makes sense, I will change it.

Toggle quote (2 lines)
> I wondered "why does it have to be cross-compiled" but then realized that came from the existing make-u-boot-package function.

Yes, that’s right, it is a copy from the other function. It will be gone with the re-work.

Toggle quote (2 lines)
> I've mostly been building u-boot natively these days. :)

Me too, exclusively. :-)


Bye

Stefan
S
S
Stefan wrote on 17 Jul 18:47 +0200
(name . Vagrant Cascadian)(address . vagrant@debian.org)
3FFD5D1E-3FB9-4EB9-907A-8502519FF7FE@vodafonemail.de
Hi Vagrant!

Toggle quote (16 lines)
>> +(define-public %u-boot-rpi-efi-configs
>> + '("CONFIG_OF_EMBED="
>> + "CONFIG_OF_BOARD=y"
>> + "CONFIG_BOOTDELAY=0"))
>
> This is surely a matter of opinion, but CONFIG_BOOTDELAY=0 is kind of
> nasty; it makes it nearly impossible to debug from a u-boot prompt if
> needed. The default is probably "2" ... long enough to actually
> interrupt it, but short enough that it shouldn't cause huge delays in
> the boot process...
>
> I know grub-efi will add it's own delay, so in a working environment,
> this just seems like an additional two seconds, but u-boot's EFI
> implementation is changing often enough that I wouldn't be surprised if
> you need to occasionally debug something.

During all the months of work to get Guix System booting over network with U-Boot and GRUB, there was no need for me to play around on the U-Boot prompt. I was even affected by a bug¹ preventing U-Boot to detect my keyboard at all. The actual problem with that bug was not that the U-Boot prompt was unusable, but that GRUB relies on the keyboard functionality of U-Boot, so I couldn’t debug boot problems e.g. due to kernel argument problems in GRUB.

Well, in this constellation U-Boot just needs to find and load the efi/boot/bootaa64.efi file. It doesn’t need to load device-tree files or care for overlays. It doesn’t need to load other stuff like SPL or other images. Its only purpose is to impose an EFI interface and to load GRUB. So the benefit of the U-Boot prompt is quite limited.

Also other distributions like openSUSE use U-Boot as EFI firmware, so I think the basic EFI functionality is tested quite well. My preference is to not bother pure users with a delayed boot time. However, I changed it to CONFIG_BOOTDELAY=1.


Bye

Stefan


S
S
Stefan wrote on 17 Jul 18:48 +0200
Re: [PATCH v3] Install guix system on Raspberry Pi
(name . phodina)(address . phodina@protonmail.com)
AAE2B273-DF62-467E-8827-34FC58335D38@vodafonemail.de
Hi!

Sorry for tho long period of silence.

Toggle quote (2 lines)
> do you need help with the patches?

Actually not with the patches, but with building and testing.

I was affected by the lack of substitutes for aarch64. Building with only 1 GB RAM and swap space is a pain.

For building Guix I figured out that building only sub-targets like make-core-go, make-packages-go, etc. helps. But this way I missed to do a “make all” and was wondering a lot and for long time about errors because silently a wrong /gnu/stor/…-guix-module-union/ got used.

I have a set of patches to fix or disable tests, just because of too less RAM, too less computing-power and an NFS root file-system.

Currently one test of glib is failing. So I can’t proof that my patches lead to a working system on current Guix.

Toggle quote (4 lines)
> Also should we provide some patches to the upstream kernel in Guix? [1]
>
> [1] https://github.com/lategoodbye/rpi-zero/issues/43

I’m far from a point to care for patches to the kernel. I’d be glad, if the linux-libre kernel is able to run a minimal Guix System. :-)


Bye

Stefan
V
V
Vagrant Cascadian wrote on 17 Jul 19:21 +0200
Re: [bug#48314] Patches to install guix system on Raspberry Pi
(name . Stefan)(address . stefan-guix@vodafonemail.de)
878rork63k.fsf@contorta
On 2022-07-17, Stefan wrote:
Toggle quote (19 lines)
>>> +(define-public %u-boot-rpi-efi-configs
>>> + '("CONFIG_OF_EMBED="
>>> + "CONFIG_OF_BOARD=y"
>>> + "CONFIG_BOOTDELAY=0"))
>>
>> This is surely a matter of opinion, but CONFIG_BOOTDELAY=0 is kind of
>> nasty; it makes it nearly impossible to debug from a u-boot prompt if
>> needed. The default is probably "2" ... long enough to actually
>> interrupt it, but short enough that it shouldn't cause huge delays in
>> the boot process...
>>
>> I know grub-efi will add it's own delay, so in a working environment,
>> this just seems like an additional two seconds, but u-boot's EFI
>> implementation is changing often enough that I wouldn't be surprised if
>> you need to occasionally debug something.
>
> During all the months of work to get Guix System booting over network
> with U-Boot and GRUB, there was no need for me to play around on the
> U-Boot prompt.
...
Toggle quote (6 lines)
> Well, in this constellation U-Boot just needs to find and load the
> efi/boot/bootaa64.efi file. It doesn’t need to load device-tree files
> or care for overlays. It doesn’t need to load other stuff like SPL or
> other images. Its only purpose is to impose an EFI interface and to
> load GRUB. So the benefit of the U-Boot prompt is quite limited.

So if it does not find that one file, what do you do?


Toggle quote (3 lines)
> Also other distributions like openSUSE use U-Boot as EFI firmware, so
> I think the basic EFI functionality is tested quite well.

Sure, it has improved greatly.


Toggle quote (3 lines)
> My preference is to not bother pure users with a delayed boot
> time. However, I changed it to CONFIG_BOOTDELAY=1.

Well, from my perspective, this is obviously significantly less bad that
0 seconds...

In general, it is my understanding that Guix prefers to go with upstream
defaults, unless there is a strong argument otherwise. I do not
personally see this as warranting a difference from upstream defaults to
gain 1 or 2 seconds of boot time.


live well,
vagrant
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRlgHNhO/zFx+LkXUXcUY/If5cWqgUCYtRFIAAKCRDcUY/If5cW
qkV1AQD5YpgU1NoDSozQ9h76dRLSKujel1If4JX8OoYBxJIeHQEAlkUgCXjX2S4i
JAov6lkPch3hjAfJst0RxMN6yGAmjQQ=
=z7Bo
-----END PGP SIGNATURE-----

S
S
Stefan wrote on 17 Jul 20:04 +0200
(name . Vagrant Cascadian)(address . vagrant@debian.org)
CFA3B77F-C576-4BC4-A839-AE311DC587E6@vodafonemail.de
Hi Vagrant!

Toggle quote (2 lines)
> So if it does not find that one file, what do you do?

Valid point. Actually I would have copied back a working U-Boot version from the NFS server side. ;-)

Toggle quote (2 lines)
> it is my understanding that Guix prefers to go with upstream defaults

Would you mind removing that line if committing?


Bye

Stefan
S
S
Stefan wrote on 17 Jul 18:48 +0200
Re: [PATCH v3] Install guix system on Raspberry Pi
(address . 48314@debbugs.gnu.org)
125F42BC-E90F-47A5-9997-7E0089AF07BF@vodafonemail.de
Hi!

A new patch series based on 7558417360d2ae011ec23197c75ef8e411558810. I tried to apply all review comments.


Bye

Stefan
P
P
phodina wrote on 18 Jul 21:23 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
EVxfptst8kQwYbgw-hyQkPLP2R1rpwgH2NstR8TCt9qZNr95av9XIxIdsJfM4GX6fepKHx9u0jRRXlxIsm9KGxRrLFCM9J3eAua75mFhVvM=@protonmail.com
Thanks Stefan for the updated patches!

I've applied them and build the system. However,
I'm unable to test the system as there is an error when invoking `guix system init` command:

$ sudo -E ./pre-inst-env guix system init --target=aarch64-linux-gnu gnu/system/examples/raspberry-pi-64.tmpl /mnt
/gnu/store/hhb5l2f5287xmfzz4jgvi15kb9bcqi33-system
/gnu/store/fiq006ykhc0dkninzz5gxl2nh3vzc37p-grub.cfg

initializing operating system under '/mnt'...
copying to '/mnt'...
populating '/mnt'...
guix system: error: symlink: Operation not permitted: "/boot/efi/gnu/store"

$ sudo fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.37.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.

Command (m for help): p

Disk /dev/mmcblk0: 29.12 GiB, 31267487744 bytes, 61069312 sectors
Disk model: 1081CS0
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 526335 524288 256M 83 Linux
/dev/sda2 526336 61069311 60542976 28.9G 83 Linux

$ mount
/dev/mmcblk0p2 on /mnt type ext4 (rw,relatime)
/dev/mmcblk0p1 on /mnt/boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

I have these 2 remarks:
1) Why does it point to "/boot/efi/gnu/store" and not "/mnt"/boot/efi/gnu/store"?
2) Symlink from ext4 "Guix" partition will not work on another vfat "EFI" partition.

Do you know how to fix this issue?

----
Petr
S
S
Stefan wrote on 19 Jul 08:55 +0200
(name . phodina)(address . phodina@protonmail.com)
3828D5BC-ABCF-4864-8AD8-A33ACBB99359@vodafonemail.de
Hi Petr!

Toggle quote (2 lines)
> Do you know how to fix this issue?

Yes. Like on other EFI systems, you have to mount /dev/mmdblk0p1 on /mnt/boot/efi.

There is the usual bootloader installation fallback, to use the bootloader-target argument for installation on /, if it is not existing below /mnt. And this is happening in your case.

I don’t understand why this common fallback got invented. I think it’s actually dangerous. It could destroy your booted system, if you simply forgot to mount the EFI system partition. I would prefer a clear error message.

But well, the code is following existing standards.

Toggle quote (2 lines)
> 1) Why does it point to "/boot/efi/gnu/store" and not "/mnt"/boot/efi/gnu/store"?

Because /mnt/boot/efi was not existing in your case and because of that fallback to ignore /mnt and use / instead.

Toggle quote (2 lines)
> 2) Symlink from ext4 "Guix" partition will not work on another vfat "EFI" partition.

That’s true. This symlink will not be created for your use case. The symlink will be created for booting over network, when the /mnt/boot/efi is an NFS share which allows symlinks. The use-case decision is based on symlink support at the bootloader-target.

Actually the installation on a microSD card is just a by-product of installation for netboot. :-)

Even on a normal x86_64 EFI system you could install the grub-efi-netboot-(removable-)bootloader instead of the grub-efi-(removable-)bootloader. The difference is, that all GRUB files will reside on the EFI system partition instead of the root partition. This could be helpful for encryption problems.


Bye

Stefan
P
P
phodina wrote on 19 Jul 09:35 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
gSGTYbtO2aatMamvptaZ2ENBQ9AjVkovjsV1SOD9u1oa0lpJoX9oiq5MNllaAQmvbYOO941T58pfy_L3bi_Dhd9oawdiSBrv1BFSg4JMG-A=@protonmail.com
Hi Stefan!
Toggle quote (10 lines)
>
> > Do you know how to fix this issue?
>
>
> Yes. Like on other EFI systems, you have to mount /dev/mmdblk0p1 on /mnt/boot/efi.
>
> There is the usual bootloader installation fallback, to use the bootloader-target argument for installation on /, if it is not existing below /mnt. And this is happening in your case.
>
> I don’t understand why this common fallback got invented. I think it’s actually dangerous. It could destroy your booted system, if you simply forgot to mount the EFI system partition. I would prefer a clear error message.

Thanks. I've mounted the boot partition to /mnt/boot instead of /mnt/boot/efi.

I tend to agree with you as the default behaviour can damage the host system without a warning which is dangerous.

So now I get some weird guix error during copying files:

sudo -E ./pre-inst-env guix system init --target=aarch64-linux-gnu gnu/system/examples/raspberry-pi-64.tmpl /mnt -v 3
gnu/system/examples/raspberry-pi-64.tmpl:32:24: warning: the 'target' field is deprecated, please use 'targets' instead
gnu/system/examples/raspberry-pi-64.tmpl:27:2: warning: List elements of the field 'swap-devices' should now use the <swap-space> record, as the old method is deprecated. See "(guix) operating-system Reference" for more details.
/gnu/store/hhb5l2f5287xmfzz4jgvi15kb9bcqi33-system
/gnu/store/fiq006ykhc0dkninzz5gxl2nh3vzc37p-grub.cfg

initializing operating system under '/mnt'...
copying to '/mnt'... [#################### ]guix system: error: readdir: Bad message
copying to '/mnt'...

I've added the verbosity level 3 to print everything but I didn't get more info about what fails :-(

----
Petr
S
S
Stefan wrote on 20 Jul 08:13 +0200
(name . phodina)(address . phodina@protonmail.com)
9A647306-1C70-4A55-B6AB-35A414E6E633@vodafonemail.de
Hi Petr!

Toggle quote (6 lines)
> So now I get some weird guix error during copying files:

> initializing operating system under '/mnt'...
> copying to '/mnt'... [#################### ]guix system: error: readdir: Bad message
> copying to '/mnt'...

The function make-grub-efi-netboot-installer in gnu/bootloader/grub.scm first uses copy-recursively to copy the collection of bootloader files to /mnt/boot/efi and creates afterwards the symlinks to /gnu/store and /boot/grub/grub.cfg or – as in your case – creates a /mnt/boot/efi/efi/boot/grub.cfg to point GRUB to the root partition to access /boot/grub/grub.cfg and /gnu/store.

Yesterday your guix system init struggled to create these symlinks. That means it was already done with the copy-recursively call.

I’m pretty sure that this copy-recursively is using readdir internally. The functionallity afterwards is surely not.

Yesterday you also got the message ‘populating '/mnt'…’ before the symlink struggle. Therefore I assume that your current error has nothing to do with the bootloader installation.

Maybe there are leftovers from yesterday in /mnt, which prevent guix to copy files sucessfully onto /dev/mmcblk0p2?

Reformatting the ext4 filesystem might help.


Bye

Stefan
P
P
phodina wrote on 20 Jul 09:16 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
t2GTPoH03C4JrkGm9sXt_K8RQtTPqvNzKN7L8a7ws6oklFIlhvY3n2vH4EQ_ohOldf6Nqz21gzmv9IfEoyV28_inllHOOVbEF1iP7yLyepU=@protonmail.com
Hi Stefan,

Toggle quote (20 lines)
> > So now I get some weird guix error during copying files:
>
> > initializing operating system under '/mnt'...
> > copying to '/mnt'... [#################### ]guix system: error: readdir: Bad message
> > copying to '/mnt'...
>
>
> The function make-grub-efi-netboot-installer in gnu/bootloader/grub.scm first uses copy-recursively to copy the collection of bootloader files to /mnt/boot/efi and creates afterwards the symlinks to /gnu/store and /boot/grub/grub.cfg or – as in your case – creates a /mnt/boot/efi/efi/boot/grub.cfg to point GRUB to the root partition to access /boot/grub/grub.cfg and /gnu/store.
>
> Yesterday your guix system init struggled to create these symlinks. That means it was already done with the copy-recursively call.
>
> I’m pretty sure that this copy-recursively is using readdir internally. The functionallity afterwards is surely not.
>
> Yesterday you also got the message ‘populating '/mnt'…’ before the symlink struggle. Therefore I assume that your current error has nothing to do with the bootloader installation.
>
> Maybe there are leftovers from yesterday in /mnt, which prevent guix to copy files sucessfully onto /dev/mmcblk0p2?
>
> Reformatting the ext4 filesystem might help.


the issue seems to be connected to my guix instance on the host. I got another weird messages and what finally help was to clean the profile cache in my home dir.

I then reformatted the SD card just to be sure.

# parted /dev/mmcblk0
GNU Parted 3.5
Using /dev/mmcblk0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) p
Model: NORELSYS 1081CS0 (scsi)
Disk /dev/mmcblk0: 31.3GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number Start End Size Type File system Flags
1 1049kB 269MB 268MB primary fat32 lba
2 269MB 31.3GB 31.0GB primary ext4

And then I also copied the firmware files [1] neccessary to boot:
$ ls /mnt/boot/efi
bcm2708-rpi-b.dtb bcm2710-rpi-2-b.dtb bcm2711-rpi-4-b.dtb efi/ fixup_db.dat start4.elf
bcm2708-rpi-b-plus.dtb bcm2710-rpi-3-b.dtb bcm2711-rpi-cm4.dtb fixup4cd.dat fixup_x.dat start4x.elf
bcm2708-rpi-b-rev1.dtb bcm2710-rpi-3-b-plus.dtb bcm2711-rpi-cm4s.dtb fixup4.dat LICENCE.broadcom start_cd.elf
bcm2708-rpi-cm.dtb bcm2710-rpi-cm3.dtb bootcode.bin fixup4db.dat manifest start_db.elf
bcm2708-rpi-zero.dtb bcm2710-rpi-zero-2.dtb bootloader.txt fixup4x.dat overlays/ start.elf
bcm2708-rpi-zero-w.dtb bcm2710-rpi-zero-2-w.dtb config.txt fixup_cd.dat start4cd.elf start_x.elf
bcm2709-rpi-2-b.dtb bcm2711-rpi-400.dtb dtb.txt fixup.dat start4db.elf u-boot.bin

The board powers up and I see the RGB screen when the raspberrypi boots. Then it switches to black screen and I don't see any output on the HDMI. Also there is no IP address assigned on the Ethernet even though the port itself is active.

I haven't run tcpdump or attached serial adapter yet so I don't know what's wrong and where the system hangs.

I'm testing this on Raspberry Pi 4.



----
Petr
S
S
Stefan wrote on 20 Jul 21:42 +0200
(name . phodina)(address . phodina@protonmail.com)
1707AE25-4041-462A-B7D0-8611A02B0E41@vodafonemail.de
Hi Petr!

Toggle quote (2 lines)
> the issue seems to be connected to my guix instance on the host.

Glad to hear you figured it out.

Toggle quote (2 lines)
> Then it switches to black screen

That should mean that the graphic-card is not set up properly.

But additionally U-Boot, GRUB or the kernel could be hanging. :-/

Toggle quote (2 lines)
> I'm testing this on Raspberry Pi 4.

I prepared everything for a 3b monthes ago. Potentially this does not match the current firmware or kernel anymore or does not fit the 4.

Take a look at grub-efi-bootloader-chain-raspi-64 in gnu/packages/raspberry-pi.scm. Read the notes there.

Take a look at raspi-custom-txt and the others there as well. You probably have to use it to set some parameters.

I use these with an older kernel:

dtoverlay=disable-wifi
dtoverlay=vc4-fkms-v3d,cma-64
enable_uart=1

My best guess is a missing dtoverlay=vc4-fkms-v3d. I just noticed that there is meanwhile a vc4-fkms-v3d-pi4. Try that first. There are also flavours without the f(ake).

Attention with enable_uart, it is set in %raspi-u-boot-bootloader-txt to 1 already. There was once a U-Boot version working without enable_uart, but the recent one seems to require it again.

If this does not help, then maybe the kernel needs to be customized. I never heard of somone else running the linux-libre kernel on a Raspberry Pi. :-)

The kernel configuration in gnu/system/examples/raspberry-pi-64.tmpl has some comments regarding possible customizations.


Bye

Stefan
P
P
phodina wrote on 12 Aug 16:27 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
l6WqHiPe2KyGlSJh6P0GC-HgB2FtQ9KNr64YZNUv581fODPnfdcujxm0cpxYTR6QL9sz85YavhYa9oaerpfhNQn1UMqe8GbGT4GRoYnN_6c=@protonmail.com
Hi Stefan!

Good news. I managed to run Guix libre kernel on the raspberry pi. Thanks for the help along the way!

pi@raspberrypi-guix ~$ uname -a
Linux raspberrypi-guix 5.18.16-gnu #1 SMP PREEMPT 1 aarch64 GNU/Linux

The issue was in the firmware, therefore I'll post the hashes of the files from the EFI partition:

pi@raspberrypi-guix ~$ sha256sum /boot/efi/*
010beacf073dbf7a4be24288a5c8b93001f0d852387dce50bf50de51a7412cd6 /boot/efi/bcm2711-rpi-400.dtb
489645357820f2e7e8f13841c901ba9571b779c07b3203f1627538d04ce45ad3 /boot/efi/bcm2711-rpi-4-b.dtb
c0f057eea9e357341265910000e56dab94b3200465b0556deb1eda3af117d3c9 /boot/efi/bcm2837-rpi-3-a-plus.dtb
df83b6dc6cda7e8eae62e8316b02a4c1659a6b0cf874c6caa075be9413a00b98 /boot/efi/bcm2837-rpi-3-b.dtb
c008e84ac57aa9c35aedabd1ed2cb4290088e33d85d1ef8ca56c5ef9b5f0d13c /boot/efi/bcm2837-rpi-3-b-plus.dtb
6a1cc758d38edcf9f9213a8fcbc75d4bf06fbd86806b4430c15742b6ab427de9 /boot/efi/bcm2837-rpi-cm3-io3.dtb
69309823da13dc96b89e3d82b44f820e4f84efa79d207adad2c8784559794f03 /boot/efi/bootcode.bin
1ac38b353f924c56c5d5a587971f3f81d09c433787b99f889368fd342c4336da /boot/efi/bootloader.txt
df0ac4af19615f13ff7ffa395ae553c70813ef9d2a82fab0e1175adf80ed1294 /boot/efi/cmdline.txt
9d4975d57f5eb54b08a430cb3d677e5dbf23ed48c73fe33a4e3efdfc35f8d41e /boot/efi/config.txt
bcc22553ef64d361270103e84c80ab5362bdb2ffba3c9eea13ee3de60f6cbaff /boot/efi/dtb.txt
22db24c621c326d907c7b8c5975b1730e6ce78dea680bec3958d907093031638 /boot/efi/fixup4cd.dat
7d28775bff4781bda065f37fbb64c88ed1b56d1f4af79d85f792032f55bb6de7 /boot/efi/fixup4.dat
b0d299dd46ddecd2c4eeeca61f42d114a0c464dcd6165861a662d118daa3afc0 /boot/efi/fixup4db.dat
495076ed0488703ba59bd0d43bc577ad1695470379263854197a752cd1989330 /boot/efi/fixup4x.dat
22db24c621c326d907c7b8c5975b1730e6ce78dea680bec3958d907093031638 /boot/efi/fixup_cd.dat
8e90c8a379f3f99ee59370c50e48853db82669dbd6515d4ce08a24307d3dc4c5 /boot/efi/fixup.dat
4f5d2433956f64cec640ae91dc47bdea3aa2c6c7cc579faafb779826bd7e554c /boot/efi/fixup_db.dat
82bbf5a3f86f73a41e9f8975deb75e50ab4d7581500a43ec7f0fcc42214948dd /boot/efi/fixup_x.dat
9756eca19be1a443fc6a6cd5f8ffb0759d8b5d68f24248829d39abdc59388490 /boot/efi/manifest
9e1474d3b3078bb80e87f65a5122fd4a8a828b563de5652b37d8b40019b3a51a /boot/efi/start4cd.elf
2dfb27b876ec00e54857e199e939def019b148010f03ce1947e4b48fa226e4f7 /boot/efi/start4db.elf
a607afd09523830bd524eafa2eb3f530d70cef643eb8eca14a80dcbd6830ec8f /boot/efi/start4.elf
7ffa3ce1f93f61737fee68f61747b876fd1b15203553ebc096d2b64d79fb7da2 /boot/efi/start4x.elf
b21aeceec40aff935f70dfe3adc4d96963e61d4696f909ad910f299da978d8bb /boot/efi/start_cd.elf
378e84616f28e63cb33c794e3430b7deeca5bb84067f79e71408f6aab587e0e7 /boot/efi/start_db.elf
e4a374d78f31d333b20ab128a614d3549f9dfe4103781c0938104fc0dd45d3fc /boot/efi/start.elf
dbdeb7c679566419035e70db8aff90954ca6ba45a579e990886ddc0b964b2621 /boot/efi/start_x.elf
f9c7d5534c787479601f1e70b4b108cd765445aecbc154296d0d35f423045ca4 /boot/efi/sysconf.txt
d47f45c6221ccaaf1ca0e66d01b90fca350a0b06b4c7a44a81b6f68a99f36607 /boot/efi/u-boot.bin

I'll test it also on RPi3 and I'll change the storage media to SSD on my RPi4 to provide more space and faster reliable storage.

- I just have question regarding the example if it wouldn't be better to prepare the whole image - partition the SD card and just copy it to the actual media?

- Should there be some manual how to prepare the firmware files or format the SD card in case we prepare just the root filesystem and bootloader?

IMHO having ISO image for Raspberry Pi 3,4 (aarch64) would be great as it would allow them to run Guix easily without need to build it on some other aarch64 machine or resort to crosscompile. What do you think?


Also there's small patch to fix deprecated calls in os-defintion files.

----
Petr
Toggle diff (51 lines)
diff --git a/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl b/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
y-pi-64-nfs-root.tmpl
index a1e41e3399..279620b0fb 100644
--- a/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
+++ b/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
@@ -30,7 +30,7 @@
    (timezone "Europe/Berlin")
    (bootloader (bootloader-configuration
                 (bootloader grub-efi-bootloader-chain-raspi-64)
-                (target "/boot/efi")
+                (targets (list "/boot/efi"))
                 (theme (grub-theme (resolution '(1920 . 1080))
                        (image (file-append
                                %artwork-repository
@@ -49,7 +49,10 @@
                          (device ":/export/raspberrypi/guix")
                          (options "addr=10.20.30.40,vers=4.1"))
                         %base-file-systems))
-   (swap-devices '("/run/swapfile"))
+    (swap-devices
+     (list
+      (swap-space
+       (target "/run/swapfile"))))
    (users (cons* (user-account
                   (name "pi")
                   (group "users")
diff --git a/gnu/system/examples/raspberry-pi-64.tmpl b/gnu/system/examples/raspberry-pi-64.tmpl
index 7e18f00d86..0739582cf0 100644
--- a/gnu/system/examples/raspberry-pi-64.tmpl
+++ b/gnu/system/examples/raspberry-pi-64.tmpl
@@ -29,7 +29,7 @@
    (timezone "Europe/Berlin")
    (bootloader (bootloader-configuration
                 (bootloader grub-efi-bootloader-chain-raspi-64)
-                (target "/boot/efi")
+                (targets (list "/boot/efi"))
                 (theme (grub-theme (resolution '(1920 . 1080))
                        (image (file-append
                                %artwork-repository
@@ -53,7 +53,10 @@
                          (type "vfat")
                          (device (file-system-label "EFI")))
                         %base-file-systems))
-   (swap-devices '("/run/swapfile"))
+   (swap-devices
+    (list
+     (swap-space
+      (target "/run/swapfile"))))
    (users (cons* (user-account
                   (name "pi")
                   (group "users")
S
S
Stefan wrote on 13 Aug 12:48 +0200
(name . phodina)(address . phodina@protonmail.com)
B1668A7F-A974-4CBE-93EF-24EEB776C680@vodafonemail.de
Hi Petr!

Toggle quote (2 lines)
> Good news. I managed to run Guix libre kernel on the raspberry pi.

Woot! Great!

Toggle quote (2 lines)
> The issue was in the firmware

Good to know!

Toggle quote (2 lines)
> I'll test it also on RPi3

In the meantime I got everything compiled and installed for my Raspberry Pi 3b as well. But there is some issue with the U-Boot. If I replace U-Boot with an older version, it boots and the system is running fine. However, during boot the Linux-Libre-Gnus and early kernel messages are not visible, but after boot all seems to be fine.

Maybe the troubles stem from the firmware, as in your case – I use a different one –, or maybe the U-Boot only works on a Pi 4.

I’m using the Linux-Libre kernel with the %bcmrpi3-defconfig from the Raspberry Pi Linux sources (removing a long list of unsupported configurations)

stefan@guix ~$ uname -a
Linux guix 5.18.12-bcmrpi3-v8 #1 SMP PREEMPT 1 aarch64 GNU/Linux

Toggle quote (2 lines)
> I just have question regarding the example if it wouldn't be better to prepare the whole image

Yes, certainly. As you may know I started with Guix on void with an NFS root file-system and patched Guix to get to this point, still on NFS. So I have no experience yet to build an image.

From what I saw in the code, I guess that more work needs to be done to generate an image. My personal focus is to first get the patches merged.

Toggle quote (2 lines)
> Should there be some manual how to prepare the firmware files or format the SD card in case we prepare just the root filesystem and bootloader?

I think the comments in e.g. raspberry-pi-64.tmpl could be improved. A hint to the non-free firmware is certainly problematic. Not sure, if we should or even can mention the Raspberry Pi in the manual.

Toggle quote (2 lines)
> IMHO having ISO image for Raspberry Pi 3,4 (aarch64) would be great as it would allow them to run Guix easily without need to build it on some other aarch64 machine or resort to crosscompile. What do you think?

Yes, I totally agree. I also think that it could help to spread Guix. It would be great to see something like e.g. Pi-hole in the future to be based on Guix System.

But first things first, the merge is still pending.

Toggle quote (2 lines)
> Also there's small patch to fix deprecated calls in os-defintion files.

Thanks, much appreciated!


Bye

Stefan
P
P
phodina wrote on 14 Aug 11:59 +0200
(name . Stefan)(address . stefan-guix@vodafonemail.de)
xjr0W3rUn2GueNJb8lTEyJfyt5ECWhhz6FymZT-rQmOFC_H7woQjM_l9TFaza-5Sruwkn8XgBv5LTcR-gyKkSzwC5VU078zVqqDkSP7Sn2U=@protonmail.com
Hi Stefan!

Toggle quote (2 lines)
> > I'll test it also on RPi3

I got it working also there. I do have RPi2 but I doubt it will run there as it's just not that powerful.

Toggle quote (8 lines)
> > I just have question regarding the example if it wouldn't be better to prepare the whole image
>
>
> Yes, certainly. As you may know I started with Guix on void with an NFS root file-system and patched Guix to get to this point, still on NFS. So I have no experience yet to build an image.
>
> From what I saw in the code, I guess that more work needs to be done to generate an image. My personal focus is to first get the patches merged.
>

Yes, the focus should be on mainlining these changes first.


Toggle quote (6 lines)
> > IMHO having ISO image for Raspberry Pi 3,4 (aarch64) would be great as it would allow them to run Guix easily without need to build it on some other aarch64 machine or resort to crosscompile. What do you think?
>
>
> Yes, I totally agree. I also think that it could help to spread Guix. It would be great to see something like e.g. Pi-hole in the future to be based on Guix System.
>

I know there is some open source bootloader which is already packaged in Guix `raspi-arm64-chainloader`. Maybe this would be the way in the future :-)

Good luck

----
Petr
S
S
Stefan wrote on 14 Aug 13:35 +0200
(name . phodina)(address . phodina@protonmail.com)
CA07C169-EBA6-46B5-8EE1-FE7BDB9F00EE@vodafonemail.de
Hi Petr!

Toggle quote (2 lines)
> I got it working also there.

Great!