unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
* [bug#48314] Patches to install guix system on Raspberry Pi
@ 2021-05-09 15:32 Stefan
  2021-05-16 12:46 ` Stefan
                   ` (4 more replies)
  0 siblings, 5 replies; 74+ messages in thread
From: Stefan @ 2021-05-09 15:32 UTC (permalink / raw)
  To: 48314

[-- Attachment #1: Type: text/plain, Size: 3024 bytes --]

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


[-- Attachment #2: 01-gnu-qemu-disable-tests-on.patch --]
[-- Type: application/octet-stream, Size: 1299 bytes --]

gnu: qemu: Disable tests on aarch64.

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

* gnu/packages/virtualization.scm (qemu): Disable tests on aarch64 because
of <https://bugs.gnu.org/43534>.
---
 gnu/packages/virtualization.scm |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/gnu/packages/virtualization.scm b/gnu/packages/virtualization.scm
index a2df3e763c..0f90a7feea 100644
--- a/gnu/packages/virtualization.scm
+++ b/gnu/packages/virtualization.scm
@@ -172,10 +172,11 @@
     (outputs '("out" "static" "doc"))   ;5.3 MiB of HTML docs
     (build-system gnu-build-system)
     (arguments
-     ;; FIXME: Disable tests on i686 to work around
-     ;; <https://bugs.gnu.org/40527>.
-     `(#:tests? ,(or (%current-target-system)
-                     (not (string=? "i686-linux" (%current-system))))
+     ;; FIXME: Disable tests on aarch64 and i686 to work around
+     ;; <https://bugs.gnu.org/43534> and <https://bugs.gnu.org/40527>.
+     `(#:tests? ,(and (not (target-aarch64?))
+                      (or (%current-target-system)
+                          (not (string=? "i686-linux" (%current-system)))))
        #:configure-flags
        (let ((gcc (string-append (assoc-ref %build-inputs "gcc") "/bin/gcc"))
              (out (assoc-ref %outputs "out")))

[-- Attachment #3: 02-gnu-bootloader-rework-chaining.patch --]
[-- Type: application/octet-stream, Size: 37476 bytes --]

gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.

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

* 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")
     …))
 …)
)
---
 doc/guix.texi                |   24 +++-
 gnu/bootloader.scm           |  104 +++++++++---------
 gnu/bootloader/grub.scm      |  241 ++++++++++++++++++++++++++----------------
 gnu/packages/bootloaders.scm |   90 ++++++++++++++++
 4 files changed, 308 insertions(+), 151 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 0947b9f028..40cef21f78 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -32595,8 +32595,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
@@ -32622,9 +32623,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{target}
-(@pxref{Bootloader Configuration, @code{target}}), to be served by a TFTP server.
- You may want to mount your TFTP server directory onto @code{target} to move the
-required files to the TFTP server automatically.
+(@pxref{Bootloader Configuration, @code{target}}) below the sub-directory
+@file{efi/Guix}, to be served by a TFTP server.  You may want to mount your TFTP
+server directory onto @code{target} 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
@@ -32655,13 +32657,23 @@ TFTP, for example by copying them into the TFTP root directory at @code{target}.
 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{target}
 This is a string denoting the target onto which to install the
 bootloader.
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index 6d7352ddd2..f7c4a8f338 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -232,26 +232,22 @@ record."
             (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))
@@ -275,7 +271,7 @@ HOOKS lists additional hook functions to modify the profile."
             (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
@@ -284,11 +280,11 @@ HOOKS lists additional hook functions to modify the profile."
                                 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)))
@@ -296,57 +292,63 @@ HOOKS lists additional hook functions to modify the profile."
                     #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 ce146aba3c..c03a04818e 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -50,11 +50,12 @@
             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
 
@@ -346,7 +347,7 @@ code."
         ((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))
@@ -376,27 +377,27 @@ when booting a root file system on a Btrfs subvolume."
                 (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
 }~%"
@@ -434,9 +435,7 @@ menuentry ~s {
   (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))))
@@ -462,8 +461,6 @@ set lang=~a~%"
 
   (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))
@@ -514,6 +511,16 @@ fi~%"))))
                  #: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")
+
 \f
 
 ;;;
@@ -607,42 +614,31 @@ fi~%"))))
                         "--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.
@@ -651,17 +647,18 @@ TARGET is the target argument given to the bootloader-configuration in
 
 (operating-system
  (bootloader (bootloader-configuration
-              (target \"/boot\")
+              (target \"/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.
@@ -671,34 +668,78 @@ paths on the TFTP server side are unknown.
 
 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")))))))))))
 
 \f
 
@@ -716,7 +757,7 @@ considered for security aspects."
    (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
@@ -726,17 +767,29 @@ considered for security aspects."
 
 (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 56bef57cb7..32dae92531 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -15,6 +15,7 @@
 ;;; Copyright © 2020 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.
 ;;;
@@ -65,13 +66,17 @@
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages web)
   #: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
@@ -353,6 +358,91 @@ menu to select one of the installed operating systems.")
                   (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

[-- Attachment #4: 03-build-kconfig-add-new-module.patch --]
[-- Type: application/octet-stream, Size: 15475 bytes --]

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.
---
 Makefile.am                  |    1 
 gnu/packages/bootloaders.scm |   87 +++++++++++--------------
 guix/build/kconfig.scm       |  148 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 186 insertions(+), 50 deletions(-)
 create mode 100644 guix/build/kconfig.scm

diff --git a/Makefile.am b/Makefile.am
index 0129011ebf..c17a417703 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -217,6 +217,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 32dae92531..38cf933c22 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -717,8 +717,9 @@ def test_ctrl_c"))
 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)))))
@@ -736,8 +737,11 @@ board-independent tools.")))
       (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"
@@ -748,9 +752,18 @@ board-independent tools.")))
          (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))
@@ -801,7 +814,11 @@ board-independent tools.")))
   (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")
@@ -810,25 +827,13 @@ also initializes the boards (RAM etc).
 
 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
@@ -858,20 +863,10 @@ it fits within common partitioning schemes.")
   (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"))
@@ -895,25 +890,17 @@ it fits within common partitioning schemes.")
   (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)))

[-- Attachment #5: 04-gnu-bootloader-add-u-boot.patch --]
[-- Type: application/octet-stream, Size: 8452 bytes --]

gnu: bootloader: Add U-Boot packages for Raspberry Pi models.

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

* 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.
---
 gnu/packages/bootloaders.scm |  172 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 168 insertions(+), 4 deletions(-)

diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 38cf933c22..e3bd6733cb 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -717,17 +717,30 @@ def test_ctrl_c"))
 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))
@@ -1023,6 +1036,157 @@ to Novena upstream, does not load u-boot.img from the first partition."))))
        `(("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")

[-- Attachment #6: 05-gnu-linux-correct-name-of.patch --]
[-- Type: application/octet-stream, Size: 2546 bytes --]

gnu: linux: Correct name of EXTRAVERSION and prepend "-" to content.

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

gnu/packages/linux.scm (make-linux-libre): Move the comment for the
configuration-file argument to the correct position between the extra-version
and configuration-file arguments.
gnu/packages/linux.scm (make-linux-libre*): Move the comment for the
configuration-file argument to the correct position between the extra-version
and configuration-file arguments.  Remove the underscore from the environment
variable EXTRAVERSION.  Prepend a hyphen to the content of EXTRAVERSION.
---
 gnu/packages/linux.scm |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 84ea849108..6ba1119da4 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,7 @@ 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" (string-append "-" ,extra-version))
 
              (let ((build  (assoc-ref %standard-phases 'build))
                    (config (assoc-ref (or native-inputs inputs) "kconfig")))

[-- Attachment #7: 06-gnu-linux-new-function-to.patch --]
[-- Type: application/octet-stream, Size: 7341 bytes --]

gnu: linux: New function to modify the configuration of a Linux kernel.

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

* gnu/packages/linux.scm (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 and sha256.
---
 gnu/packages/linux.scm |  111 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 107 insertions(+), 4 deletions(-)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 6ba1119da4..4b2096b2fb 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -54,6 +54,7 @@
 ;;; Copyright © 2020 David Dashyan <mail@davie.li>
 ;;; Copyright © 2020 pukkamustard <pukkamustard@posteo.net>
 ;;; Copyright © 2021 B. Wilson <elaexuotee@wilsonb.com>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -165,7 +166,8 @@
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-2)
   #:use-module (srfi srfi-26)
-  #:use-module (ice-9 match))
+  #:use-module (ice-9 match)
+  #:use-module (ice-9 optargs))
 
 (define-public (system->linux-architecture arch)
   "Return the Linux architecture name for ARCH, a Guix system name such as
@@ -820,8 +822,8 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
              (substitute* (find-files "." "^Makefile(\\.include)?$")
                (("/bin/pwd") "pwd"))
              #t))
-         (replace 'configure
-           (lambda* (#:key inputs native-inputs target #:allow-other-keys)
+         (add-before 'configure 'set-environment
+           (lambda* (#:key target #:allow-other-keys)
              ;; Avoid introducing timestamps
              (setenv "KCONFIG_NOTIMESTAMP" "1")
              (setenv "KBUILD_BUILD_TIMESTAMP" (getenv "SOURCE_DATE_EPOCH"))
@@ -839,7 +841,9 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
                          (getenv "CROSS_COMPILE"))))
 
              (setenv "EXTRAVERSION" (string-append "-" ,extra-version))
-
+             #t))
+         (replace 'configure
+           (lambda* (#:key inputs native-inputs #:allow-other-keys)
              (let ((build  (assoc-ref %standard-phases 'build))
                    (config (assoc-ref (or native-inputs inputs) "kconfig")))
 
@@ -1154,6 +1158,105 @@ It has been modified to remove all non-free binary blobs.")
       (inherit base-linux-libre)
       (inputs `(("cpio" ,cpio) ,@(package-inputs base-linux-libre))))))
 
+\f
+;;;
+;;; Linux kernel customization functions.
+;;;
+
+(define*-public (modify-linux #:key name
+                                    (linux linux-libre)
+                                    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.
+
+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 follows the special removal extension:
+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)))
+    (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* ((configs (string-append "arch/" (getenv "ARCH")
+                                              "/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 (and (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))))
 
 \f
 ;;;

[-- Attachment #8: 07-gnu-raspberry-pi-add-defconfig.patch --]
[-- Type: application/octet-stream, Size: 3217 bytes --]

gnu: raspberry-pi: Add defconfig objects to build customized Linux kernels.

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

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.
---
 gnu/packages/raspberry-pi.scm |   44 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

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 @@
   #: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 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                (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"))

[-- Attachment #9: 08-gnu-raspberry-pi-add-helpers.patch --]
[-- Type: application/octet-stream, Size: 3018 bytes --]

gnu: raspberry-pi: Add helpers for config.txt file generation.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   53 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

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 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                #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

[-- Attachment #10: 09-gnu-raspberry-pi-new-function.patch --]
[-- Type: application/octet-stream, Size: 2078 bytes --]

gnu: raspberry-pi: New function to make a package with device-tree files.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

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 @@
   #: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 @@ 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-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

[-- Attachment #11: 10-gnu-raspberry-pi-add-a.patch --]
[-- Type: application/octet-stream, Size: 9951 bytes --]

gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.

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

* 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.
---
 gnu/packages/raspberry-pi.scm                     |   19 +++++
 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl |   73 ++++++++++++++++++++
 gnu/system/examples/raspberry-pi-64.tmpl          |   77 +++++++++++++++++++++
 3 files changed, 169 insertions(+)
 create mode 100644 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
 create mode 100644 gnu/system/examples/raspberry-pi-64.tmpl

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 @@ kernel 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..a1e41e3399
--- /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)
+                (target "/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 '("/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..7e18f00d86
--- /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)
+                (target "/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 '("/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

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-05-09 15:32 [bug#48314] Patches to install guix system on Raspberry Pi Stefan
@ 2021-05-16 12:46 ` Stefan
  2021-06-19 18:11   ` Danny Milosavljevic
                     ` (3 more replies)
  2021-11-17 14:00 ` [bug#48314] Install " phodina via Guix-patches via
                   ` (3 subsequent siblings)
  4 siblings, 4 replies; 74+ messages in thread
From: Stefan @ 2021-05-16 12:46 UTC (permalink / raw)
  To: 48314

[-- Attachment #1: Type: text/plain, Size: 231 bytes --]

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


[-- Attachment #2: 01-gnu-qemu-disable-tests-on.patch --]
[-- Type: application/octet-stream, Size: 1299 bytes --]

gnu: qemu: Disable tests on aarch64.

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

* gnu/packages/virtualization.scm (qemu): Disable tests on aarch64 because
of <https://bugs.gnu.org/43534>.
---
 gnu/packages/virtualization.scm |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/gnu/packages/virtualization.scm b/gnu/packages/virtualization.scm
index a2df3e763c..0f90a7feea 100644
--- a/gnu/packages/virtualization.scm
+++ b/gnu/packages/virtualization.scm
@@ -172,10 +172,11 @@
     (outputs '("out" "static" "doc"))   ;5.3 MiB of HTML docs
     (build-system gnu-build-system)
     (arguments
-     ;; FIXME: Disable tests on i686 to work around
-     ;; <https://bugs.gnu.org/40527>.
-     `(#:tests? ,(or (%current-target-system)
-                     (not (string=? "i686-linux" (%current-system))))
+     ;; FIXME: Disable tests on aarch64 and i686 to work around
+     ;; <https://bugs.gnu.org/43534> and <https://bugs.gnu.org/40527>.
+     `(#:tests? ,(and (not (target-aarch64?))
+                      (or (%current-target-system)
+                          (not (string=? "i686-linux" (%current-system)))))
        #:configure-flags
        (let ((gcc (string-append (assoc-ref %build-inputs "gcc") "/bin/gcc"))
              (out (assoc-ref %outputs "out")))

[-- Attachment #3: 02-gnu-bootloader-rework-chaining.patch --]
[-- Type: application/octet-stream, Size: 37476 bytes --]

gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.

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

* 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")
     …))
 …)
)
---
 doc/guix.texi                |   24 +++-
 gnu/bootloader.scm           |  104 +++++++++---------
 gnu/bootloader/grub.scm      |  241 ++++++++++++++++++++++++++----------------
 gnu/packages/bootloaders.scm |   90 ++++++++++++++++
 4 files changed, 308 insertions(+), 151 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 0947b9f028..40cef21f78 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -32595,8 +32595,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
@@ -32622,9 +32623,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{target}
-(@pxref{Bootloader Configuration, @code{target}}), to be served by a TFTP server.
- You may want to mount your TFTP server directory onto @code{target} to move the
-required files to the TFTP server automatically.
+(@pxref{Bootloader Configuration, @code{target}}) below the sub-directory
+@file{efi/Guix}, to be served by a TFTP server.  You may want to mount your TFTP
+server directory onto @code{target} 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
@@ -32655,13 +32657,23 @@ TFTP, for example by copying them into the TFTP root directory at @code{target}.
 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{target}
 This is a string denoting the target onto which to install the
 bootloader.
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index 6d7352ddd2..f7c4a8f338 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -232,26 +232,22 @@ record."
             (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))
@@ -275,7 +271,7 @@ HOOKS lists additional hook functions to modify the profile."
             (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
@@ -284,11 +280,11 @@ HOOKS lists additional hook functions to modify the profile."
                                 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)))
@@ -296,57 +292,63 @@ HOOKS lists additional hook functions to modify the profile."
                     #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 ce146aba3c..c03a04818e 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -50,11 +50,12 @@
             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
 
@@ -346,7 +347,7 @@ code."
         ((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))
@@ -376,27 +377,27 @@ when booting a root file system on a Btrfs subvolume."
                 (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
 }~%"
@@ -434,9 +435,7 @@ menuentry ~s {
   (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))))
@@ -462,8 +461,6 @@ set lang=~a~%"
 
   (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))
@@ -514,6 +511,16 @@ fi~%"))))
                  #: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")
+
 \f
 
 ;;;
@@ -607,42 +614,31 @@ fi~%"))))
                         "--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.
@@ -651,17 +647,18 @@ TARGET is the target argument given to the bootloader-configuration in
 
 (operating-system
  (bootloader (bootloader-configuration
-              (target \"/boot\")
+              (target \"/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.
@@ -671,34 +668,78 @@ paths on the TFTP server side are unknown.
 
 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")))))))))))
 
 \f
 
@@ -716,7 +757,7 @@ considered for security aspects."
    (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
@@ -726,17 +767,29 @@ considered for security aspects."
 
 (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 56bef57cb7..32dae92531 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -15,6 +15,7 @@
 ;;; Copyright © 2020 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.
 ;;;
@@ -65,13 +66,17 @@
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages web)
   #: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
@@ -353,6 +358,91 @@ menu to select one of the installed operating systems.")
                   (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

[-- Attachment #4: 03-build-kconfig-add-new-module.patch --]
[-- Type: application/octet-stream, Size: 15475 bytes --]

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.
---
 Makefile.am                  |    1 
 gnu/packages/bootloaders.scm |   87 +++++++++++--------------
 guix/build/kconfig.scm       |  148 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 186 insertions(+), 50 deletions(-)
 create mode 100644 guix/build/kconfig.scm

diff --git a/Makefile.am b/Makefile.am
index 0129011ebf..c17a417703 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -217,6 +217,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 32dae92531..38cf933c22 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -717,8 +717,9 @@ def test_ctrl_c"))
 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)))))
@@ -736,8 +737,11 @@ board-independent tools.")))
       (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"
@@ -748,9 +752,18 @@ board-independent tools.")))
          (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))
@@ -801,7 +814,11 @@ board-independent tools.")))
   (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")
@@ -810,25 +827,13 @@ also initializes the boards (RAM etc).
 
 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
@@ -858,20 +863,10 @@ it fits within common partitioning schemes.")
   (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"))
@@ -895,25 +890,17 @@ it fits within common partitioning schemes.")
   (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)))

[-- Attachment #5: 04-gnu-bootloader-add-u-boot.patch --]
[-- Type: application/octet-stream, Size: 8452 bytes --]

gnu: bootloader: Add U-Boot packages for Raspberry Pi models.

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

* 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.
---
 gnu/packages/bootloaders.scm |  172 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 168 insertions(+), 4 deletions(-)

diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 38cf933c22..e3bd6733cb 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -717,17 +717,30 @@ def test_ctrl_c"))
 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))
@@ -1023,6 +1036,157 @@ to Novena upstream, does not load u-boot.img from the first partition."))))
        `(("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")

[-- Attachment #6: 05-gnu-linux-correct-name-of.patch --]
[-- Type: application/octet-stream, Size: 2610 bytes --]

gnu: linux: Correct name of EXTRAVERSION and prepend "-" to content.

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

gnu/packages/linux.scm (make-linux-libre): Move the comment for the
configuration-file argument to the correct position between the extra-version
and configuration-file arguments.
gnu/packages/linux.scm (make-linux-libre*): Move the comment for the
configuration-file argument to the correct position between the extra-version
and configuration-file arguments.  Remove the underscore from the environment
variable EXTRAVERSION.  Prepend a hyphen to the content of EXTRAVERSION.
---
 gnu/packages/linux.scm |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

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")))

[-- Attachment #7: 06-gnu-linux-new-function-to.patch --]
[-- Type: application/octet-stream, Size: 8712 bytes --]

gnu: linux: New function to modify the configuration of a Linux kernel.

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.
---
 gnu/packages/linux.scm |  132 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 4 deletions(-)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 51e692a8c3..983f0c2b22 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -54,6 +54,7 @@
 ;;; Copyright © 2020 David Dashyan <mail@davie.li>
 ;;; Copyright © 2020 pukkamustard <pukkamustard@posteo.net>
 ;;; Copyright © 2021 B. Wilson <elaexuotee@wilsonb.com>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -165,7 +166,8 @@
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-2)
   #:use-module (srfi srfi-26)
-  #:use-module (ice-9 match))
+  #:use-module (ice-9 match)
+  #:use-module (ice-9 optargs))
 
 (define-public (system->linux-architecture arch)
   "Return the Linux architecture name for ARCH, a Guix system name such as
@@ -181,6 +183,21 @@
           ((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
@@ -820,8 +837,8 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
              (substitute* (find-files "." "^Makefile(\\.include)?$")
                (("/bin/pwd") "pwd"))
              #t))
-         (replace 'configure
-           (lambda* (#:key inputs native-inputs target #:allow-other-keys)
+         (add-before 'configure 'set-environment
+           (lambda* (#:key target #:allow-other-keys)
              ;; Avoid introducing timestamps
              (setenv "KCONFIG_NOTIMESTAMP" "1")
              (setenv "KBUILD_BUILD_TIMESTAMP" (getenv "SOURCE_DATE_EPOCH"))
@@ -840,7 +857,9 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
 
              (setenv "EXTRAVERSION" ,(and extra-version
                                           (string-append "-" extra-version)))
-
+             #t))
+         (replace 'configure
+           (lambda* (#:key inputs native-inputs #:allow-other-keys)
              (let ((build  (assoc-ref %standard-phases 'build))
                    (config (assoc-ref (or native-inputs inputs) "kconfig")))
 
@@ -1155,6 +1174,111 @@ It has been modified to remove all non-free binary blobs.")
       (inherit base-linux-libre)
       (inputs `(("cpio" ,cpio) ,@(package-inputs base-linux-libre))))))
 
+\f
+;;;
+;;; 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))))
 
 \f
 ;;;

[-- Attachment #8: 07-gnu-raspberry-pi-add-defconfig.patch --]
[-- Type: application/octet-stream, Size: 3217 bytes --]

gnu: raspberry-pi: Add defconfig objects to build customized Linux kernels.

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

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.
---
 gnu/packages/raspberry-pi.scm |   44 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

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 @@
   #: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 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                (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"))

[-- Attachment #9: 08-gnu-raspberry-pi-add-helpers.patch --]
[-- Type: application/octet-stream, Size: 3018 bytes --]

gnu: raspberry-pi: Add helpers for config.txt file generation.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   53 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

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 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                #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

[-- Attachment #10: 09-gnu-raspberry-pi-new-function.patch --]
[-- Type: application/octet-stream, Size: 2078 bytes --]

gnu: raspberry-pi: New function to make a package with device-tree files.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

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 @@
   #: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 @@ 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-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

[-- Attachment #11: 10-gnu-raspberry-pi-add-a.patch --]
[-- Type: application/octet-stream, Size: 9951 bytes --]

gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.

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

* 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.
---
 gnu/packages/raspberry-pi.scm                     |   19 +++++
 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl |   73 ++++++++++++++++++++
 gnu/system/examples/raspberry-pi-64.tmpl          |   77 +++++++++++++++++++++
 3 files changed, 169 insertions(+)
 create mode 100644 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
 create mode 100644 gnu/system/examples/raspberry-pi-64.tmpl

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 @@ kernel 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..a1e41e3399
--- /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)
+                (target "/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 '("/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..7e18f00d86
--- /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)
+                (target "/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 '("/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

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-05-16 12:46 ` Stefan
@ 2021-06-19 18:11   ` Danny Milosavljevic
  2021-06-19 18:13   ` Danny Milosavljevic
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 74+ messages in thread
From: Danny Milosavljevic @ 2021-06-19 18:11 UTC (permalink / raw)
  To: Stefan; +Cc: Mark H Weaver, Leo Famulari, 48314

[-- Attachment #1: Type: text/plain, Size: 2190 bytes --]

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)

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")))

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-05-16 12:46 ` Stefan
  2021-06-19 18:11   ` Danny Milosavljevic
@ 2021-06-19 18:13   ` Danny Milosavljevic
  2021-06-19 19:10     ` Stefan
  2021-06-19 19:04   ` Danny Milosavljevic
  2021-06-19 19:10   ` Danny Milosavljevic
  3 siblings, 1 reply; 74+ messages in thread
From: Danny Milosavljevic @ 2021-06-19 18:13 UTC (permalink / raw)
  To: Stefan; +Cc: 48314

[-- Attachment #1: Type: text/plain, Size: 111 bytes --]

Hi Stefan,

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

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-05-16 12:46 ` Stefan
  2021-06-19 18:11   ` Danny Milosavljevic
  2021-06-19 18:13   ` Danny Milosavljevic
@ 2021-06-19 19:04   ` Danny Milosavljevic
  2021-06-19 19:18     ` Stefan
  2021-06-19 19:10   ` Danny Milosavljevic
  3 siblings, 1 reply; 74+ messages in thread
From: Danny Milosavljevic @ 2021-06-19 19:04 UTC (permalink / raw)
  To: Stefan; +Cc: 48314

[-- Attachment #1: Type: text/plain, Size: 1246 bytes --]

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?

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-05-16 12:46 ` Stefan
                     ` (2 preceding siblings ...)
  2021-06-19 19:04   ` Danny Milosavljevic
@ 2021-06-19 19:10   ` Danny Milosavljevic
  2021-06-19 20:21     ` Stefan
  3 siblings, 1 reply; 74+ messages in thread
From: Danny Milosavljevic @ 2021-06-19 19:10 UTC (permalink / raw)
  To: Stefan; +Cc: Mark H Weaver, Leo Famulari, 48314

[-- Attachment #1: Type: text/plain, Size: 499 bytes --]

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.

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-06-19 18:13   ` Danny Milosavljevic
@ 2021-06-19 19:10     ` Stefan
  0 siblings, 0 replies; 74+ messages in thread
From: Stefan @ 2021-06-19 19:10 UTC (permalink / raw)
  To: Danny Milosavljevic; +Cc: 48314

Hi Danny!

> 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



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-06-19 19:04   ` Danny Milosavljevic
@ 2021-06-19 19:18     ` Stefan
  0 siblings, 0 replies; 74+ messages in thread
From: Stefan @ 2021-06-19 19:18 UTC (permalink / raw)
  To: Danny Milosavljevic; +Cc: 48314

Hi Danny!

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

That’s OK.


Bye

Stefan



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-06-19 19:10   ` Danny Milosavljevic
@ 2021-06-19 20:21     ` Stefan
  2021-07-28 18:58       ` Stefan
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan @ 2021-06-19 20:21 UTC (permalink / raw)
  To: Danny Milosavljevic; +Cc: Mark H Weaver, Leo Famulari, 48314

Hi!

> @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).

> 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



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-06-19 20:21     ` Stefan
@ 2021-07-28 18:58       ` Stefan
  2021-10-31 22:07         ` Stefan
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan @ 2021-07-28 18:58 UTC (permalink / raw)
  To: Danny Milosavljevic; +Cc: Mark H Weaver, Leo Famulari, 48314

Hi Danny!

Are there any news on this topic¹?


Bye

Stefan


¹ <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=48314>






^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-07-28 18:58       ` Stefan
@ 2021-10-31 22:07         ` Stefan
  2021-11-13 18:05           ` Vagrant Cascadian
                             ` (2 more replies)
  0 siblings, 3 replies; 74+ messages in thread
From: Stefan @ 2021-10-31 22:07 UTC (permalink / raw)
  To: 48314; +Cc: Danny Milosavljevic

[-- Attachment #1: Type: text/plain, Size: 199 bytes --]

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


[-- Attachment #2: 01-gnu-bootloader-rework-chaining --]
[-- Type: application/octet-stream, Size: 37426 bytes --]

gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.

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

* 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")
     …))
 …)
)
---
 doc/guix.texi                |   24 +++-
 gnu/bootloader.scm           |  104 +++++++++---------
 gnu/bootloader/grub.scm      |  241 ++++++++++++++++++++++++++----------------
 gnu/packages/bootloaders.scm |   90 ++++++++++++++++
 4 files changed, 308 insertions(+), 151 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index ea1973f02c..1dad33cfae 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -33853,8 +33853,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
@@ -33880,9 +33881,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
@@ -33916,13 +33918,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 d1c72c0c85..cddb8daf93 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -261,26 +261,22 @@ instead~%")))
             (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))
@@ -304,7 +300,7 @@ HOOKS lists additional hook functions to modify the profile."
             (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
@@ -313,11 +309,11 @@ HOOKS lists additional hook functions to modify the profile."
                                 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)))
@@ -325,57 +321,63 @@ HOOKS lists additional hook functions to modify the profile."
                     #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 d8e888ff40..2235363c6d 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -50,11 +50,12 @@
             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
 
@@ -346,7 +347,7 @@ code."
         ((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))
@@ -376,27 +377,27 @@ when booting a root file system on a Btrfs subvolume."
                 (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
 }~%"
@@ -434,9 +435,7 @@ menuentry ~s {
   (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))))
@@ -462,8 +461,6 @@ set lang=~a~%"
 
   (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))
@@ -514,6 +511,16 @@ fi~%"))))
                  #: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")
+
 \f
 
 ;;;
@@ -607,42 +614,31 @@ fi~%"))))
                         "--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.
@@ -652,17 +648,18 @@ bootloader-configuration in:
 
 (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.
@@ -672,34 +669,78 @@ paths on the TFTP server side are unknown.
 
 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")))))))))))
 
 \f
 
@@ -717,7 +758,7 @@ considered for security aspects."
    (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
@@ -727,17 +768,29 @@ considered for security aspects."
 
 (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 706ddf0207..601912011b 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 @@
   #: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 @@ menu to select one of the installed operating systems.")
                   (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

[-- Attachment #3: 02-build-kconfig-add-new-module --]
[-- Type: application/octet-stream, Size: 15487 bytes --]

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.
---
 Makefile.am                  |    1 
 gnu/packages/bootloaders.scm |   87 +++++++++++--------------
 guix/build/kconfig.scm       |  148 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 186 insertions(+), 50 deletions(-)
 create mode 100644 guix/build/kconfig.scm

diff --git a/Makefile.am b/Makefile.am
index d608b08899..06cceebf07 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -221,6 +221,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 601912011b..3bc5600c7c 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -733,8 +733,9 @@ def test_ctrl_c"))
 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)))))
@@ -752,8 +753,11 @@ board-independent tools.")))
       (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"
@@ -764,9 +768,18 @@ board-independent tools.")))
          (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))
@@ -820,7 +833,11 @@ board-independent tools.")))
   (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")
@@ -829,25 +846,13 @@ also initializes the boards (RAM etc).
 
 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
@@ -877,20 +882,10 @@ it fits within common partitioning schemes.")
   (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"))
@@ -941,25 +936,17 @@ device while it's being turned on (and a while longer).")
   (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)))

[-- Attachment #4: 03-gnu-bootloader-add-u-boot --]
[-- Type: application/octet-stream, Size: 8452 bytes --]

gnu: bootloader: Add U-Boot packages for Raspberry Pi models.

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

* 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.
---
 gnu/packages/bootloaders.scm |  172 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 168 insertions(+), 4 deletions(-)

diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 3bc5600c7c..5121f3a6ea 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -733,17 +733,30 @@ def test_ctrl_c"))
 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))
@@ -1071,6 +1084,157 @@ to Novena upstream, does not load u-boot.img from the first partition."))))
        `(("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")

[-- Attachment #5: 04-gnu-linux-new-function-to --]
[-- Type: application/octet-stream, Size: 8577 bytes --]

gnu: linux: New function to modify the configuration of a Linux kernel.

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.
---
 gnu/packages/linux.scm |  130 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 127 insertions(+), 3 deletions(-)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index f4c1867c5d..d8ff747d20 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -53,6 +53,7 @@
 ;;; Copyright © 2021 B. Wilson <elaexuotee@wilsonb.com>
 ;;; Copyright © 2021 Ivan Gankevich <i.gankevich@spbu.ru>
 ;;; Copyright © 2021 Olivier Dion <olivier.dion@polymtl.ca>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -166,6 +167,7 @@
   #: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)
@@ -182,6 +184,21 @@
           ((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
@@ -811,8 +828,8 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
              (substitute* (find-files "." "^Makefile(\\.include)?$")
                (("/bin/pwd") "pwd"))
              #t))
-         (replace 'configure
-           (lambda* (#:key inputs native-inputs target #:allow-other-keys)
+         (add-before 'configure 'set-environment
+           (lambda* (#:key target #:allow-other-keys)
              ;; Avoid introducing timestamps
              (setenv "KCONFIG_NOTIMESTAMP" "1")
              (setenv "KBUILD_BUILD_TIMESTAMP" (getenv "SOURCE_DATE_EPOCH"))
@@ -831,7 +848,9 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
 
              (setenv "EXTRAVERSION" ,(and extra-version
                                           (string-append "-" extra-version)))
-
+             #t))
+         (replace 'configure
+           (lambda* (#:key inputs native-inputs #:allow-other-keys)
              (let ((build  (assoc-ref %standard-phases 'build))
                    (config (assoc-ref (or native-inputs inputs) "kconfig")))
 
@@ -1163,6 +1182,111 @@ It has been modified to remove all non-free binary blobs.")
       (inherit base-linux-libre)
       (inputs `(("cpio" ,cpio) ,@(package-inputs base-linux-libre))))))
 
+\f
+;;;
+;;; 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))))
 
 \f
 ;;;

[-- Attachment #6: 05-gnu-raspberry-pi-add-defconfig --]
[-- Type: application/octet-stream, Size: 3217 bytes --]

gnu: raspberry-pi: Add defconfig objects to build customized Linux kernels.

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

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.
---
 gnu/packages/raspberry-pi.scm |   44 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

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 @@
   #: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 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                (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"))

[-- Attachment #7: 06-gnu-raspberry-pi-add-helpers --]
[-- Type: application/octet-stream, Size: 3018 bytes --]

gnu: raspberry-pi: Add helpers for config.txt file generation.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   53 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

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 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                #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

[-- Attachment #8: 07-gnu-raspberry-pi-new-function --]
[-- Type: application/octet-stream, Size: 2078 bytes --]

gnu: raspberry-pi: New function to make a package with device-tree files.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

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 @@
   #: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 @@ 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-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

[-- Attachment #9: 08-gnu-raspberry-pi-add-a --]
[-- Type: application/octet-stream, Size: 9951 bytes --]

gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.

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

* 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.
---
 gnu/packages/raspberry-pi.scm                     |   19 +++++
 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl |   73 ++++++++++++++++++++
 gnu/system/examples/raspberry-pi-64.tmpl          |   77 +++++++++++++++++++++
 3 files changed, 169 insertions(+)
 create mode 100644 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
 create mode 100644 gnu/system/examples/raspberry-pi-64.tmpl

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 @@ kernel 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..a1e41e3399
--- /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)
+                (target "/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 '("/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..7e18f00d86
--- /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)
+                (target "/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 '("/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

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-10-31 22:07         ` Stefan
@ 2021-11-13 18:05           ` Vagrant Cascadian
  2021-11-13 18:51             ` Vagrant Cascadian
  2022-07-17 16:47             ` Stefan via Guix-patches via
  2021-11-13 18:23           ` Vagrant Cascadian
  2021-11-13 20:21           ` Vagrant Cascadian
  2 siblings, 2 replies; 74+ messages in thread
From: Vagrant Cascadian @ 2021-11-13 18:05 UTC (permalink / raw)
  To: Stefan, 48314; +Cc: Danny Milosavljevic

[-- Attachment #1: Type: text/plain, Size: 2434 bytes --]

On 2021-10-31, Stefan wrote:
> 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-10-31 22:07         ` Stefan
  2021-11-13 18:05           ` Vagrant Cascadian
@ 2021-11-13 18:23           ` Vagrant Cascadian
  2022-07-17 16:47             ` Stefan via Guix-patches via
  2021-11-13 20:21           ` Vagrant Cascadian
  2 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2021-11-13 18:23 UTC (permalink / raw)
  To: Stefan, 48314; +Cc: Danny Milosavljevic

[-- Attachment #1: Type: text/plain, Size: 1503 bytes --]

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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-11-13 18:05           ` Vagrant Cascadian
@ 2021-11-13 18:51             ` Vagrant Cascadian
  2022-07-17 16:47             ` Stefan via Guix-patches via
  1 sibling, 0 replies; 74+ messages in thread
From: Vagrant Cascadian @ 2021-11-13 18:51 UTC (permalink / raw)
  To: Stefan, 48314; +Cc: Danny Milosavljevic

[-- Attachment #1: Type: text/plain, Size: 2442 bytes --]

On 2021-11-13, Vagrant Cascadian wrote:
> 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.
...
> +(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 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):

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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-10-31 22:07         ` Stefan
  2021-11-13 18:05           ` Vagrant Cascadian
  2021-11-13 18:23           ` Vagrant Cascadian
@ 2021-11-13 20:21           ` Vagrant Cascadian
  2022-07-17 16:47             ` Stefan via Guix-patches via
  2 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2021-11-13 20:21 UTC (permalink / raw)
  To: Stefan, 48314; +Cc: Danny Milosavljevic

[-- Attachment #1: Type: text/plain, Size: 722 bytes --]

On 2021-10-31, Stefan wrote:
> +(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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Install guix system on Raspberry Pi
  2021-05-09 15:32 [bug#48314] Patches to install guix system on Raspberry Pi Stefan
  2021-05-16 12:46 ` Stefan
@ 2021-11-17 14:00 ` phodina via Guix-patches via
  2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 74+ messages in thread
From: phodina via Guix-patches via @ 2021-11-17 14:00 UTC (permalink / raw)
  To: 48314@debbugs.gnu.org

[-- Attachment #1: Type: text/plain, Size: 1261 bytes --]

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

[1]: https://github.com/rhboot/efivar/issues/186

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fixes-to-cross-compile-system-for-aarch64.patch --]
[-- Type: text/x-patch; name=0001-Fixes-to-cross-compile-system-for-aarch64.patch, Size: 7405 bytes --]

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.


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


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2021-05-09 15:32 [bug#48314] Patches to install guix system on Raspberry Pi Stefan
  2021-05-16 12:46 ` Stefan
  2021-11-17 14:00 ` [bug#48314] Install " phodina via Guix-patches via
@ 2022-04-14  7:38 ` phodina via Guix-patches via
  2022-04-14  8:17   ` phodina via Guix-patches via
                     ` (3 more replies)
  2022-10-30 17:32 ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
  2022-10-30 17:33 ` Stefan via Guix-patches via
  4 siblings, 4 replies; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-14  7:38 UTC (permalink / raw)
  To: 48314@debbugs.gnu.org
  Cc: Stefan, Vagrant Cascadian, Ludovic Courtès,
	dannym@scratchpost.org


[-- Attachment #1.1: Type: text/plain, Size: 1628 bytes --]

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 #1.2: Type: text/html, Size: 2395 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v3-0006-gnu-raspberry-pi-Add-helpers-for-config.txt-file-.patch --]
[-- Type: text/x-patch; name=v3-0006-gnu-raspberry-pi-Add-helpers-for-config.txt-file-.patch, Size: 3025 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: v3-0001-gnu-bootloader-Rework-chaining-add-grub-efi-netbo.patch --]
[-- Type: text/x-patch; name=v3-0001-gnu-bootloader-Rework-chaining-add-grub-efi-netbo.patch, Size: 36672 bytes --]

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")
     …))
 …)
)

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")
+
 \f
 
 ;;;
@@ -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")))))))))))
 
 \f
 
@@ -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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: v3-0003-gnu-bootloader-Add-U-Boot-packages-for-Raspberry-.patch --]
[-- Type: text/x-patch; name=v3-0003-gnu-bootloader-Add-U-Boot-packages-for-Raspberry-.patch, Size: 8437 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #5: v3-0008-gnu-raspberry-pi-Add-a-bootloader-chain-for-the-R.patch --]
[-- Type: text/x-patch; name=v3-0008-gnu-raspberry-pi-Add-a-bootloader-chain-for-the-R.patch, Size: 9792 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #6: v3-0007-gnu-raspberry-pi-New-function-to-make-a-package-w.patch --]
[-- Type: text/x-patch; name=v3-0007-gnu-raspberry-pi-New-function-to-make-a-package-w.patch, Size: 2138 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #7: v3-0002-build-kconfig-Add-new-module-to-modify-a-defconfi.patch --]
[-- Type: text/x-patch; name=v3-0002-build-kconfig-Add-new-module-to-modify-a-defconfi.patch, Size: 15384 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #8: v3-0005-gnu-raspberry-pi-Add-defconfig-objects-to-build-c.patch --]
[-- Type: text/x-patch; name=v3-0005-gnu-raspberry-pi-Add-defconfig-objects-to-build-c.patch, Size: 3170 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #9: v3-0004-gnu-linux-New-function-to-modify-the-configuratio.patch --]
[-- Type: text/x-patch; name=v3-0004-gnu-linux-New-function-to-modify-the-configuratio.patch, Size: 8740 bytes --]

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.

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))))))
 
+\f
+;;;
+;;; 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))))
 
 \f
 ;;;
-- 
2.35.1


[-- Attachment #10: chz6x0835ix8fzhsg6zspx8rslfwcr-guile-fibers-1.1.0.drv.gz --]
[-- Type: application/gzip, Size: 7372 bytes --]

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
@ 2022-04-14  8:17   ` phodina via Guix-patches via
  2022-04-14  8:32   ` Maxime Devos
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-14  8:17 UTC (permalink / raw)
  To: 48314@debbugs.gnu.org; +Cc: Mathieu Othacehe

[-- Attachment #1: Type: text/plain, Size: 103 bytes --]

The issue about guile-fibers has already been reported by Mathieu in https://issues.guix.gnu.org/54793.

[-- Attachment #2: Type: text/html, Size: 312 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
  2022-04-14  8:17   ` phodina via Guix-patches via
@ 2022-04-14  8:32   ` Maxime Devos
  2022-04-14  9:25     ` [bug#48314] [PATCH v4] " phodina via Guix-patches via
  2022-04-14 14:06   ` [bug#48314] [PATCH v3] " Maxime Devos
  2022-04-14 15:56   ` Vagrant Cascadian
  3 siblings, 1 reply; 74+ messages in thread
From: Maxime Devos @ 2022-04-14  8:32 UTC (permalink / raw)
  To: phodina, 48314@debbugs.gnu.org
  Cc: Stefan, Vagrant Cascadian, Ludovic Courtès,
	dannym@scratchpost.org

[-- Attachment #1: Type: text/plain, Size: 303 bytes --]

phodina via Guix-patches via schreef op do 14-04-2022 om 07:38 [+0000]:
> +        `(modify-phases ,phases
> +           (replace 'configure

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

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

(and replace the , by #$ etc).

Greetings,
Maxime.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v4] Install guix system on Raspberry Pi
  2022-04-14  8:32   ` Maxime Devos
@ 2022-04-14  9:25     ` phodina via Guix-patches via
  2022-04-14 11:00       ` Maxime Devos
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-14  9:25 UTC (permalink / raw)
  To: 48314@debbugs.gnu.org; +Cc: Stefan, Maxime Devos

[-- Attachment #1: Type: text/plain, Size: 2493 bytes --]

>
> > +        `(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

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v4-0001-Attempt-to-fix-modify-linux-procedure-using-Gexp.patch --]
[-- Type: text/x-patch; name=v4-0001-Attempt-to-fix-modify-linux-procedure-using-Gexp.patch, Size: 2882 bytes --]

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.


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


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v4] Install guix system on Raspberry Pi
  2022-04-14  9:25     ` [bug#48314] [PATCH v4] " phodina via Guix-patches via
@ 2022-04-14 11:00       ` Maxime Devos
  2022-04-14 12:23         ` [bug#48314] [PATCH v5] " phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Maxime Devos @ 2022-04-14 11:00 UTC (permalink / raw)
  To: phodina, 48314@debbugs.gnu.org; +Cc: Stefan

[-- Attachment #1: Type: text/plain, Size: 3333 bytes --]

phodina schreef op do 14-04-2022 om 09:25 [+0000]:
>                 (let* ((srcarch
> -                       ,(system->linux-srcarch (or (%current-target-
> system)
> +                       $#(system->linux-srcarch (or (%current-

it's #$, not $#

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

likewise

>                     ((not defconfig)
> -                    `(begin
> +                    $~(begin

in this case #~

>                         ;; 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)
#~ and #$
>                                    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"))))))))

Greetings,
Maxime.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-04-14 11:00       ` Maxime Devos
@ 2022-04-14 12:23         ` phodina via Guix-patches via
  2022-04-14 13:03           ` phodina via Guix-patches via
  2022-04-14 14:00           ` Maxime Devos
  0 siblings, 2 replies; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-14 12:23 UTC (permalink / raw)
  To: Maxime Devos; +Cc: Stefan, 48314@debbugs.gnu.org

[-- Attachment #1: Type: text/plain, Size: 1032 bytes --]

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

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v5-0001-gnu-bootloader-Rework-chaining-add-grub-efi-netbo.patch --]
[-- Type: text/x-patch; name=v5-0001-gnu-bootloader-Rework-chaining-add-grub-efi-netbo.patch, Size: 36672 bytes --]

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")
     …))
 …)
)

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")
+
 \f
 
 ;;;
@@ -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")))))))))))
 
 \f
 
@@ -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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: v5-0003-gnu-bootloader-Add-U-Boot-packages-for-Raspberry-.patch --]
[-- Type: text/x-patch; name=v5-0003-gnu-bootloader-Add-U-Boot-packages-for-Raspberry-.patch, Size: 8437 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: v5-0007-gnu-raspberry-pi-New-function-to-make-a-package-w.patch --]
[-- Type: text/x-patch; name=v5-0007-gnu-raspberry-pi-New-function-to-make-a-package-w.patch, Size: 2138 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #5: v5-0002-build-kconfig-Add-new-module-to-modify-a-defconfi.patch --]
[-- Type: text/x-patch; name=v5-0002-build-kconfig-Add-new-module-to-modify-a-defconfi.patch, Size: 15384 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #6: v5-0004-gnu-linux-New-function-to-modify-the-configuratio.patch --]
[-- Type: text/x-patch; name=v5-0004-gnu-linux-New-function-to-modify-the-configuratio.patch, Size: 8731 bytes --]

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.

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))))))
 
+\f
+;;;
+;;; 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))))
 
 \f
 ;;;
-- 
2.34.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #7: v5-0006-gnu-raspberry-pi-Add-helpers-for-config.txt-file-.patch --]
[-- Type: text/x-patch; name=v5-0006-gnu-raspberry-pi-Add-helpers-for-config.txt-file-.patch, Size: 3025 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #8: v5-0005-gnu-raspberry-pi-Add-defconfig-objects-to-build-c.patch --]
[-- Type: text/x-patch; name=v5-0005-gnu-raspberry-pi-Add-defconfig-objects-to-build-c.patch, Size: 3170 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #9: v5-0008-gnu-raspberry-pi-Add-a-bootloader-chain-for-the-R.patch --]
[-- Type: text/x-patch; name=v5-0008-gnu-raspberry-pi-Add-a-bootloader-chain-for-the-R.patch, Size: 9792 bytes --]

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.

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


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-04-14 12:23         ` [bug#48314] [PATCH v5] " phodina via Guix-patches via
@ 2022-04-14 13:03           ` phodina via Guix-patches via
  2022-04-14 13:57             ` Maxime Devos
  2022-04-14 14:00           ` Maxime Devos
  1 sibling, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-14 13:03 UTC (permalink / raw)
  To: Maxime Devos; +Cc: Stefan, 48314@debbugs.gnu.org

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




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-04-14 13:03           ` phodina via Guix-patches via
@ 2022-04-14 13:57             ` Maxime Devos
  0 siblings, 0 replies; 74+ messages in thread
From: Maxime Devos @ 2022-04-14 13:57 UTC (permalink / raw)
  To: phodina; +Cc: Stefan, 48314@debbugs.gnu.org

[-- Attachment #1: Type: text/plain, Size: 1613 bytes --]

phodina schreef op do 14-04-2022 om 13:03 [+0000]:
> ~$ 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).

> 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.

> 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.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-04-14 12:23         ` [bug#48314] [PATCH v5] " phodina via Guix-patches via
  2022-04-14 13:03           ` phodina via Guix-patches via
@ 2022-04-14 14:00           ` Maxime Devos
  1 sibling, 0 replies; 74+ messages in thread
From: Maxime Devos @ 2022-04-14 14:00 UTC (permalink / raw)
  To: phodina; +Cc: Stefan, 48314@debbugs.gnu.org

[-- Attachment #1: Type: text/plain, Size: 557 bytes --]

phodina schreef op do 14-04-2022 om 12:23 [+0000]:
> 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.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
  2022-04-14  8:17   ` phodina via Guix-patches via
  2022-04-14  8:32   ` Maxime Devos
@ 2022-04-14 14:06   ` Maxime Devos
  2022-04-14 15:53     ` phodina via Guix-patches via
  2022-04-14 15:56   ` Vagrant Cascadian
  3 siblings, 1 reply; 74+ messages in thread
From: Maxime Devos @ 2022-04-14 14:06 UTC (permalink / raw)
  To: phodina, 48314@debbugs.gnu.org
  Cc: Stefan, Vagrant Cascadian, Ludovic Courtès,
	dannym@scratchpost.org

[-- Attachment #1: Type: text/plain, Size: 382 bytes --]

phodina via Guix-patches via schreef op do 14-04-2022 om 07:38 [+0000]:
> 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.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14 14:06   ` [bug#48314] [PATCH v3] " Maxime Devos
@ 2022-04-14 15:53     ` phodina via Guix-patches via
  2022-04-14 17:33       ` Maxime Devos
  2022-04-15 17:17       ` Ludovic Courtès
  0 siblings, 2 replies; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-14 15:53 UTC (permalink / raw)
  To: Maxime Devos
  Cc: Stefan, Vagrant Cascadian, Ludovic Courtès,
	dannym@scratchpost.org, 48314@debbugs.gnu.org

[-- Attachment #1: Type: text/plain, Size: 1006 bytes --]

>
> > 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.

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

[-- Attachment #2: dnq1fk0xwj7fhmspnzqgdvlnk59p6p-shepherd-0.9.0.drv.gz --]
[-- Type: application/gzip, Size: 3957 bytes --]

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
                     ` (2 preceding siblings ...)
  2022-04-14 14:06   ` [bug#48314] [PATCH v3] " Maxime Devos
@ 2022-04-14 15:56   ` Vagrant Cascadian
  2022-04-28  2:57     ` Vagrant Cascadian
  3 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2022-04-14 15:56 UTC (permalink / raw)
  To: phodina, 48314@debbugs.gnu.org
  Cc: Stefan, dannym@scratchpost.org, Ludovic Courtès

[-- Attachment #1: Type: text/plain, Size: 4746 bytes --]

On 2022-04-14, phodina@protonmail.com wrote:
> (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:

  https://issues.guix.gnu.org/48314#12

(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. The EFI variants and 32-bit variants supported on armhf could
be easily added later once the other patches land.


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

See comment:

  https://issues.guix.gnu.org/48314#15

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.


> +(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! :)


> +(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.


> Subject: [PATCH v3 2/8] build: kconfig: Add new module to modify a defconfig
>  file.
...
>  (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.


>  (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:

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

... was used previously.


> 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14 15:53     ` phodina via Guix-patches via
@ 2022-04-14 17:33       ` Maxime Devos
  2022-04-15 17:17       ` Ludovic Courtès
  1 sibling, 0 replies; 74+ messages in thread
From: Maxime Devos @ 2022-04-14 17:33 UTC (permalink / raw)
  To: phodina
  Cc: Stefan, Vagrant Cascadian, Ludovic Courtès,
	dannym@scratchpost.org, 48314@debbugs.gnu.org

[-- Attachment #1: Type: text/plain, Size: 401 bytes --]

phodina schreef op do 14-04-2022 om 15:53 [+0000]:
> 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.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14 15:53     ` phodina via Guix-patches via
  2022-04-14 17:33       ` Maxime Devos
@ 2022-04-15 17:17       ` Ludovic Courtès
  2022-04-16  8:53         ` phodina via Guix-patches via
  1 sibling, 1 reply; 74+ messages in thread
From: Ludovic Courtès @ 2022-04-15 17:17 UTC (permalink / raw)
  To: phodina
  Cc: Stefan, Vagrant Cascadian, dannym@scratchpost.org, Maxime Devos,
	48314@debbugs.gnu.org

Hi,

phodina <phodina@protonmail.com> skribis:

> 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’.




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-15 17:17       ` Ludovic Courtès
@ 2022-04-16  8:53         ` phodina via Guix-patches via
  2022-04-18 21:00           ` Ludovic Courtès
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-16  8:53 UTC (permalink / raw)
  To: Ludovic Courtès
  Cc: Stefan, Vagrant Cascadian, dannym@scratchpost.org, Maxime Devos,
	48314@debbugs.gnu.org

[-- Attachment #1: Type: text/plain, Size: 808 bytes --]

> > 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



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-gnu-nss-certs-Support-cross-compilation.patch --]
[-- Type: text/x-patch; name=0001-gnu-nss-certs-Support-cross-compilation.patch, Size: 1412 bytes --]

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.

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-gnu-ntp-Support-cross-compilation.patch --]
[-- Type: text/x-patch; name=0002-gnu-ntp-Support-cross-compilation.patch, Size: 1059 bytes --]

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.

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


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-16  8:53         ` phodina via Guix-patches via
@ 2022-04-18 21:00           ` Ludovic Courtès
  2022-04-21 10:52             ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Ludovic Courtès @ 2022-04-18 21:00 UTC (permalink / raw)
  To: phodina
  Cc: Stefan, Vagrant Cascadian, dannym@scratchpost.org, Maxime Devos,
	48314@debbugs.gnu.org

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’.




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-18 21:00           ` Ludovic Courtès
@ 2022-04-21 10:52             ` phodina via Guix-patches via
  2022-04-21 19:32               ` Stefan
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-04-21 10:52 UTC (permalink / raw)
  To: Ludovic Courtès
  Cc: Stefan, Vagrant Cascadian, dannym@scratchpost.org, Maxime Devos,
	48314@debbugs.gnu.org

> 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




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-21 10:52             ` phodina via Guix-patches via
@ 2022-04-21 19:32               ` Stefan
  0 siblings, 0 replies; 74+ messages in thread
From: Stefan @ 2022-04-21 19:32 UTC (permalink / raw)
  To: phodina
  Cc: Vagrant Cascadian, dannym, Ludovic Courtès, Maxime Devos,
	48314

Hi Petr!

> 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.

> 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



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-14 15:56   ` Vagrant Cascadian
@ 2022-04-28  2:57     ` Vagrant Cascadian
  2022-04-28  6:05       ` Stefan
  0 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2022-04-28  2:57 UTC (permalink / raw)
  To: phodina, 48314@debbugs.gnu.org
  Cc: Stefan, dannym@scratchpost.org, Ludovic Courtès

[-- Attachment #1: Type: text/plain, Size: 1366 bytes --]

On 2022-04-14, Vagrant Cascadian wrote:
> 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-28  2:57     ` Vagrant Cascadian
@ 2022-04-28  6:05       ` Stefan
  2022-04-28 15:25         ` Vagrant Cascadian
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan @ 2022-04-28  6:05 UTC (permalink / raw)
  To: Vagrant Cascadian; +Cc: dannym, Ludovic Courtès, phodina, 48314

Hi Vagrant!

> 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?

> 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




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-28  6:05       ` Stefan
@ 2022-04-28 15:25         ` Vagrant Cascadian
  2022-07-02  6:40           ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2022-04-28 15:25 UTC (permalink / raw)
  To: Stefan; +Cc: dannym, Ludovic Courtès, phodina, 48314

[-- Attachment #1: Type: text/plain, Size: 1469 bytes --]

On 2022-04-28, Stefan wrote:
>> 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!


> 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:

  https://github.com/raspberrypi/firmware/issues/553


>> 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-04-28 15:25         ` Vagrant Cascadian
@ 2022-07-02  6:40           ` phodina via Guix-patches via
  2022-07-17 16:48             ` Stefan via Guix-patches via
  2022-07-17 16:48             ` Stefan via Guix-patches via
  0 siblings, 2 replies; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-07-02  6:40 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Stefan,

do you need help with the patches?

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

[1] https://github.com/lategoodbye/rpi-zero/issues/43
----
Petr




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-11-13 18:05           ` Vagrant Cascadian
  2021-11-13 18:51             ` Vagrant Cascadian
@ 2022-07-17 16:47             ` Stefan via Guix-patches via
  1 sibling, 0 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-17 16:47 UTC (permalink / raw)
  To: Vagrant Cascadian; +Cc: Stefan, Danny Milosavljevic, 48314

Hi Vagrant!


> 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.

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

OK

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

Yes.

> 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. :-)

> 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





^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-11-13 18:23           ` Vagrant Cascadian
@ 2022-07-17 16:47             ` Stefan via Guix-patches via
  0 siblings, 0 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-17 16:47 UTC (permalink / raw)
  To: Vagrant Cascadian; +Cc: Danny Milosavljevic, 48314

Hi Vagrant!

> 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.

> 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.

> 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.

> I've mostly been building u-boot natively these days. :)

Me too, exclusively. :-)


Bye

Stefan





^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2021-11-13 20:21           ` Vagrant Cascadian
@ 2022-07-17 16:47             ` Stefan via Guix-patches via
  2022-07-17 17:21               ` Vagrant Cascadian
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-17 16:47 UTC (permalink / raw)
  To: Vagrant Cascadian; +Cc: Danny Milosavljevic, 48314

Hi Vagrant!

>> +(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


¹ <https://en.opensuse.org/HCL:Raspberry_Pi3#I_cannot_use_keyboard_in_U-Boot_and_Grub_but_it_works_in_Linux>





^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-02  6:40           ` phodina via Guix-patches via
@ 2022-07-17 16:48             ` Stefan via Guix-patches via
  2022-07-17 16:48             ` Stefan via Guix-patches via
  1 sibling, 0 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-17 16:48 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi!

Sorry for tho long period of silence. 

> 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.

> 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





^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-02  6:40           ` phodina via Guix-patches via
  2022-07-17 16:48             ` Stefan via Guix-patches via
@ 2022-07-17 16:48             ` Stefan via Guix-patches via
  2022-07-18 19:23               ` phodina via Guix-patches via
  1 sibling, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-17 16:48 UTC (permalink / raw)
  To: 48314; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, phodina

[-- Attachment #1: Type: text/plain, Size: 139 bytes --]

Hi!

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


Bye

Stefan



[-- Attachment #2: 01-gnu-linux-fix-extra-version.patch --]
[-- Type: application/octet-stream, Size: 3237 bytes --]

gnu: linux: Fix the extra-version parameter in make-linux-libre*.

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

* gnu/packages/linux.scm (make-linux-libre*) ['set-environment]: Make
the Makefile accept EXTRAVERSION from the environment. Fix the usage of
an empty extra-version string. Split this new phase out of and adding
if before …
['configure]: … to make the phases more hackable.
---
 gnu/packages/linux.scm |   17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 19ba30aa16..b00b46be47 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -63,6 +63,7 @@
 ;;; Copyright © 2021 Petr Hodina <phodina@protonmail.com>
 ;;; Copyright © 2022 Artyom V. Poptsov <poptsov.artyom@gmail.com>
 ;;; Copyright © 2022 Rene Saavedra <nanuui@protonmail.com>
+;;; Copyright © 2022 Stefan <stefan-guix@vodafonemail.de>
 
 ;;;
 ;;; This file is part of GNU Guix.
@@ -823,8 +824,8 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
                  (lambda _
                    (substitute* (find-files "." "^Makefile(\\.include)?$")
                      (("/bin/pwd") "pwd"))))
-               (replace 'configure
-                 (lambda* (#:key inputs target #:allow-other-keys)
+               (add-before 'configure 'set-environment
+                 (lambda* (#:key target #:allow-other-keys)
                    ;; Avoid introducing timestamps.
                    (setenv "KCONFIG_NOTIMESTAMP" "1")
                    (setenv "KBUILD_BUILD_TIMESTAMP"
@@ -846,11 +847,15 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
                        (setenv "CROSS_COMPILE" (string-append target "-"))
                        (format #t "`CROSS_COMPILE' set to `~a'~%"
                                (getenv "CROSS_COMPILE"))))
-
+                   ;; Allow EXTRAVERSION to be set via the environment.
+                   (substitute* "Makefile"
+                     (("^ *EXTRAVERSION[[:blank:]]*=") "EXTRAVERSION ?="))
                    (setenv "EXTRAVERSION"
                            #$(and extra-version
-                                  (string-append "-" extra-version)))
-
+                                  (not (string-null? extra-version))
+                                  (string-append "-" extra-version)))))
+               (replace 'configure
+                 (lambda* (#:key inputs #:allow-other-keys)
                    (let ((build  (assoc-ref %standard-phases 'build))
                          (config (assoc-ref inputs "kconfig")))
 
@@ -871,7 +876,7 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
 
                      (invoke "make" "oldconfig"))))
                (replace 'install
-                 (lambda* (#:key inputs native-inputs #:allow-other-keys)
+                 (lambda* (#:key inputs #:allow-other-keys)
                    (let ((moddir (string-append #$output "/lib/modules"))
                          (dtbdir (string-append #$output "/lib/dtbs")))
                      ;; Install kernel image, kernel configuration and link map.

[-- Attachment #3: 02-gnu-bootloader-rework-chaining.patch --]
[-- Type: application/octet-stream, Size: 40614 bytes --]

gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.

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

* 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")
     …))
 …)
)
---
 doc/guix.texi                |   58 +++++++---
 gnu/bootloader.scm           |  104 +++++++++---------
 gnu/bootloader/grub.scm      |  241 ++++++++++++++++++++++++++----------------
 gnu/packages/bootloaders.scm |   90 ++++++++++++++++
 4 files changed, 331 insertions(+), 162 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 8fc8f53d0e..e4fb4a6bc8 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -36937,8 +36937,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{grub-efi-removable-bootloader},
-@code{extlinux-bootloader} and @code{u-boot-bootloader} are supported.
+@code{grub-efi-removable-bootloader}, @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
@@ -36947,15 +36948,29 @@ modules.  In particular, @code{(gnu bootloader u-boot)} contains definitions
 of bootloaders for a wide range of ARM and AArch64 systems, using the
 @uref{https://www.denx.de/wiki/U-Boot/, U-Boot bootloader}.
 
+@vindex grub-bootloader
+@code{grub-bootloader} allows you to boot in particular Intel-based machines
+in ``legacy'' BIOS mode.
+
 @vindex grub-efi-bootloader
 @code{grub-efi-bootloader} allows to boot on modern systems using the
 @dfn{Unified Extensible Firmware Interface} (UEFI).  This is what you should
 use if the installation image contains a @file{/sys/firmware/efi} directory
 when you boot it on your system.
 
-@vindex grub-bootloader
-@code{grub-bootloader} allows you to boot in particular Intel-based machines
-in ``legacy'' BIOS mode.
+@vindex grub-efi-removable-bootloader
+@code{grub-efi-removable-bootloader} allows you to boot your system from
+removable media by writing the GRUB file to the UEFI-specification location of
+@file{/EFI/BOOT/BOOTX64.efi} of the boot directory, usually @file{/boot/efi}.
+This is also useful for some UEFI firmwares that ``forget'' their configuration
+from their non-volatile storage. Like @code{grub-efi-bootloader}, this can only
+be used if the @file{/sys/firmware/efi} directory is available.
+
+@quotation Note
+This @emph{will} overwrite the GRUB file from any other operating systems that
+also place their GRUB file in the UEFI-specification location; making them
+unbootable.
+@end quotation
 
 @vindex grub-efi-netboot-bootloader
 @code{grub-efi-netboot-bootloader} allows you to boot your system over network
@@ -36964,9 +36979,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
@@ -36995,25 +37011,33 @@ this constellation the symlinks will work.
 For other constellations you will have to program your own bootloader
 installer, which then takes care to make necessary files from the store
 accessible through TFTP, for example by copying them into the TFTP root
-directory to your @code{targets}.
+directory for 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-removable-bootloader
-@code{grub-efi-removable-bootloader} allows you to boot your system from
-removable media by writing the GRUB file to the UEFI-specification location of
-@file{/EFI/BOOT/BOOTX64.efi} of the boot directory, usually @file{/boot/efi}.
-This is also useful for some UEFI firmwares that ``forget'' their configuration
-from their non-volatile storage. Like @code{grub-efi-bootloader}, this can only
-be used if the @file{/sys/firmware/efi} directory is available.
+If a local EFI System Partition (ESP) or a similar partition with a FAT file
+system is mounted in @code{targets}, then symlinks cannot be created.  In this
+case everything will be prepared for booting from local storage, simialar as if
+using @code{grub-efi-bootloader}, with the difference that all GRUB binaries
+reside on @code{targets}, too, like needed for booting over network.
+
+@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.
 
 @quotation Note
 This @emph{will} overwrite the GRUB file from any other operating systems that
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 @@ instead~%")))
             (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 @@ HOOKS lists additional hook functions to modify the profile."
             (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 @@ HOOKS lists additional hook functions to modify the profile."
                                 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 @@ HOOKS lists additional hook functions to modify the profile."
                     #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 4f18c9b518..2406e204ab 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -53,13 +53,14 @@
             grub-theme-gfxmode
 
             install-grub-efi-removable
-            install-grub-efi-netboot
+            make-grub-efi-netboot-installer
 
             grub-bootloader
             grub-efi-bootloader
             grub-efi-removable-bootloader
             grub-efi32-bootloader
             grub-efi-netboot-bootloader
+            grub-efi-netboot-removable-bootloader
             grub-mkrescue-bootloader
             grub-minimal-bootloader
 
@@ -353,7 +354,7 @@ code."
         ((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))
@@ -383,27 +384,27 @@ when booting a root file system on a Btrfs subvolume."
                 (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
 }~%"
@@ -440,9 +441,7 @@ menuentry ~s {
   (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))))
@@ -468,8 +467,6 @@ set lang=~a~%"
 
   (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))
@@ -520,6 +517,16 @@ fi~%"))))
                  #: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")
+
 \f
 
 ;;;
@@ -661,42 +668,31 @@ fi~%"))))
                               ((target-arm?) "--target=arm-efi"))
                         "--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.
@@ -706,17 +702,18 @@ bootloader-configuration in:
 
 (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.
@@ -726,34 +723,78 @@ paths on the TFTP server side are unknown.
 
 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")))))))))))
 
 \f
 
@@ -771,7 +812,7 @@ considered for security aspects."
    (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
@@ -781,11 +822,12 @@ considered for security aspects."
 
 (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-removable-bootloader
   (bootloader
@@ -800,11 +842,22 @@ considered for security aspects."
    (name 'grub-efi32)
    (package grub-efi32)))
 
-(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 71a10f54d5..3dbd3c97e8 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 © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -67,13 +68,17 @@
   #: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
@@ -379,6 +384,91 @@ menu to select one of the installed operating systems.")
                   (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

[-- Attachment #4: 03-build-kconfig-add-new-module.patch --]
[-- Type: application/octet-stream, Size: 17702 bytes --]

build: kconfig: Add new module to modify a defconfig file.

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

* guix/build/kconfig.scm (config-string->pair, (pair->config-string,
defconfig->alist, modify-defconfig, verify-config): New file with some new
functions for handling of defconfig and .config files.
* 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.
---
 Makefile.am                  |    1 
 gnu/packages/bootloaders.scm |   88 +++++++++-----------
 guix/build/kconfig.scm       |  184 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 223 insertions(+), 50 deletions(-)
 create mode 100644 guix/build/kconfig.scm

diff --git a/Makefile.am b/Makefile.am
index e5363140fb..8f53bb54bc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -233,6 +233,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 3dbd3c97e8..c4f23f239e 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -760,8 +760,9 @@ def test_ctrl_c"))
 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)))))
@@ -779,8 +780,11 @@ board-independent tools.")))
       (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"
@@ -791,9 +795,19 @@ board-independent tools.")))
          (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))
+                       (verify-config ".config" config-file))
                      (begin
                        (display "Invalid board name. Valid board names are:"
                                 (current-error-port))
@@ -847,7 +861,11 @@ board-independent tools.")))
   (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")
@@ -856,25 +874,13 @@ also initializes the boards (RAM etc).
 
 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
@@ -904,20 +910,10 @@ it fits within common partitioning schemes.")
   (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"))
@@ -968,25 +964,17 @@ device while it's being turned on (and a while longer).")
   (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..e32503c9c3
--- /dev/null
+++ b/guix/build/kconfig.scm
@@ -0,0 +1,184 @@
+;;; 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
+            verify-config))
+
+;; Commentary:
+;;
+;; Builder-side code to modify configurations for the Kconfig build system as
+;; used by Linux and U-Boot.
+;;
+;; Code:
+
+(define (config-string->pair config-string)
+  "Parse a configuration string like \"CONFIG_EXAMPLE=m\" into a key-value pair.
+An error is thrown for invalid configurations.
+
+\"CONFIG_A=y\"            -> '(\"CONFIG_A\" . \"y\")
+\"CONFIG_B=\\\"\\\"\"         -> '(\"CONFIG_B\" . \"\\\"\\\"\")
+\"# CONFIG_E is not set\" -> '(\"CONFIG_E\" . #f)
+\"CONFIG_C=\"             -> '(\"CONFIG_C\" . #f)
+\"CONFIG_D\"              -> '(\"CONFIG_D\" . #f)
+\"# Any comment\"         -> '(#f . \"# Any comment\")
+\"\"                      -> '(#f . \"\")
+\"# CONFIG_E=y\"          -> (error \"Invalid configuration\")
+\"CONFIG_E is not set\"   -> (error \"Invalid configuration\")
+\"Anything else\"         -> (error \"Invalid configuration\")"
+  (define config-regexp
+    (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 later emits "# … is not set".
+     "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*=[\\t ]*(.+)?|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
+
+  (define config-comment-regexp
+    (make-regexp "^(| [\\t ]*| *#.*)$"))
+
+  (let ((match (regexp-exec config-regexp (string-trim-right config-string))))
+    (if match
+        (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 (eq? (not comment) (not unset))
+              ;; The key is uncommented and set or commented and unset.
+              (cons key value)
+              ;; The key is set or unset ambigiously.
+              (error (format #f "Invalid configuration, did you mean \"~a\"?"
+                             (pair->config-string (cons key #f)))
+                     config-string)))
+        ;; This is not a valid or ambigious config-string, but mayby a comment.
+        (if (regexp-exec config-comment-regexp config-string)
+            ;; We keep valid comments.
+            (cons #f config-string)
+            (error "Invalid configuration" config-string)))))
+
+(define (pair->config-string pair)
+  "Convert a PAIR back to a config-string."
+  (let* ((key (first pair))
+         (value (cdr pair)))
+    (if (string? key)
+        (if (string? value)
+            (string-append key "=" value)
+            (string-append "# " key " is not set"))
+        value)))
+
+(define (defconfig->alist defconfig)
+  "Convert the content of a DEFCONFIG (or .config) file into an alist."
+  (with-input-from-file defconfig
+    (lambda ()
+      (let loop ((alist '())
+                 (line (read-line)))
+        (if (eof-object? line)
+            ;; Building the alist is done, now check for duplicates.
+            (let loop ((keys (map first (filter first alist)))
+                       (duplicates '()))
+              (if (null? keys)
+                  ;; The search for duplicates is done.
+                  ;; Return the alist or throw an error on duplicates.
+                  (if (null? duplicates)
+                      alist
+                      (error
+                       (format #f "Duplicate configurations in ~a" defconfig)
+                       duplicates))
+                  ;; Continue the search for duplicates.
+                  (loop (cdr keys)
+                        (if (member (first keys) (cdr keys) equal?)
+                            (cons (first keys) duplicates)
+                            duplicates))))
+            ;; Build the alist.
+            (loop (cons (config-string->pair line) alist)
+                  (read-line)))))))
+
+(define (modify-defconfig defconfig configs)
+  "This function can modify a given DEFCONFIG (or .config) file by adding,
+changing or removing the list of strings in CONFIGS.  This allows customization
+of Kconfig based projects like the kernel Linux or the bootloader 'Das U-Boot'.
+
+These are examples for CONFIGS to add, 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."
+  (let* (;; 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-pairs (map config-string->pair
+                            (append-map (cut string-split <>  #\newline)
+                                        (if (string? configs)
+                                            (list configs)
+                                            configs))))
+         ;; Generate a blocklist from all valid keys in config-pairs.
+         (blocklist (delete #f (map first config-pairs)))
+         ;; Generate an alist from the defconifg without the keys in blocklist.
+         (filtered-defconfig-pairs (remove (lambda (pair)
+                                             (member (first pair) blocklist))
+                                           (defconfig->alist defconfig))))
+    (with-output-to-file defconfig
+      (lambda ()
+        (for-each
+           (lambda (pair)
+             (display (pair->config-string pair))
+             (newline))
+           (append filtered-defconfig-pairs config-pairs))))))
+
+(define (verify-config config defconfig)
+  "Verify that the CONFIG file contains all configurations from the DEFCONFIG
+file and return #t in this case. Otherwise throw an error with the mismatching
+keys and their values."
+  (let* ((config-pairs (defconfig->alist config))
+         (defconfig-pairs (defconfig->alist defconfig))
+         (mismatching-pairs
+          (remove (lambda (pair)
+                    ;; Remove all configurations, whose values are #f and whose
+                    ;; keys are not in config-pairs, as not in config-pairs
+                    ;; means unset, …
+                    (and (not (cdr pair))
+                         (not (assoc-ref config-pairs (first pair)))))
+                  ;; … from the defconfig-pairs different to config-pairs.
+                  (lset-difference equal?
+                                   ;; Remove comments by filtering with first.
+                                   (filter first defconfig-pairs)
+                                   config-pairs))))
+    (if (null? mismatching-pairs)
+        #t
+        (error (format #f
+                       "Mismatching configurations in ~a and ~a"
+                       config
+                       defconfig)
+               (map (lambda (mismatching-pair)
+                      (let* ((key (first mismatching-pair))
+                             (defconfig-value (cdr mismatching-pair))
+                             (config-value (assoc-ref config-pairs key)))
+                        (cons key (list (list config-value defconfig-value)))))
+                    mismatching-pairs)))))

[-- Attachment #5: 04-gnu-bootloader-add-u-boot.patch --]
[-- Type: application/octet-stream, Size: 12547 bytes --]

gnu: bootloader: Add U-Boot packages for Raspberry Pi models.

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

* gnu/packages/bootloader.scm (make-u-boot-package): Add keyword
parameters 'name-suffix' and 'append-description'.
(make-u-boot-bin-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-2{,-efi,-bin,-efi-bin},
u-boot-rpi-3-32b{,-efi,-bin,-efi-bin},
u-boot-rpi-4-32b{,-efi,-bin,-efi-bin},
u-boot-rpi-arm64{,-efi,-bin,-efi-bin}): New packages.
---
 gnu/packages/bootloaders.scm |  198 +++++++++++++++++++++++++++++++++---------
 1 file changed, 155 insertions(+), 43 deletions(-)

diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index c4f23f239e..16112c7e4b 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -756,13 +756,21 @@ def test_ctrl_c"))
                        (setenv "PAGER" "cat")
                        (apply invoke "make" test-target make-flags))))
                  '()))))
-    (description "U-Boot is a bootloader used mostly for ARM boards.  It
-also initializes the boards (RAM etc).  This package provides its
-board-independent tools.")))
-
-(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."
+    (description (string-append (package-description u-boot)
+                                "  This package provides board-independent
+tools of U-Boot."))))
+
+(define*-public (make-u-boot-package board
+                                     triplet
+                                     #:key
+                                     defconfig
+                                     configs
+                                     name-suffix
+                                     append-description)
+  "Returns a U-Boot package for BOARD cross-compiled for TRIPLET with the
+optional DEFCONFIG file and optional configuration changes from CONFIGS.
+A NAME-SUFFIX will be appended to the package name. An APPEND-DESCRIPTION will
+be appended to the package description."
   (let ((same-arch? (lambda ()
                       (string=? (%current-system)
                                 (gnu-triplet->nix-system triplet)))))
@@ -770,7 +778,12 @@ optional DEFCONFIG file and optional configuration changes from CONFIGS."
       (inherit u-boot)
       (name (string-append "u-boot-"
                            (string-replace-substring (string-downcase board)
-                                                     "_" "-")))
+                                                     "_" "-")
+                           (or name-suffix "")))
+      (description (if append-description
+                       (string-append (package-description u-boot)
+                                      "\n\n" append-description)
+                       (package-description u-boot)))
       (native-inputs
        `(,@(if (not (same-arch?))
              `(("cross-gcc" ,(cross-gcc triplet))
@@ -861,20 +874,15 @@ optional DEFCONFIG file and optional configuration changes from CONFIGS."
   (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"
-               ;; 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")
-      (description "U-Boot is a bootloader used mostly for ARM boards.  It
-also initializes the boards (RAM etc).
-
-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."))))
+  (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"
+   ;; Patch out other device trees to build an 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\"")
+   #:name-suffix "-boneblack"
+   #:append-description "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."))
 
 (define-public u-boot-am335x-evm
   (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"))
@@ -929,7 +937,14 @@ it fits within common partitioning schemes."))))
 
 (define-public u-boot-nintendo-nes-classic-edition
   (let ((base (make-u-boot-package "Nintendo_NES_Classic_Edition"
-                                   "arm-linux-gnueabihf")))
+                                   "arm-linux-gnueabihf"
+                                   #:append-description "This version is for
+the Nintendo NES Classic Edition.  It is assumed that you have added a serial
+port to pins PB0 and PB1 as described on
+@url{https://linux-sunxi.org/Nintendo_NES_Classic_Edition}.
+
+In order to use FEL mode on the device, hold the Reset button on the
+device while it's being turned on (and a while longer).")))
     (package
       (inherit base)
       ;; Starting with 2019.01, FEL doesn't work anymore on A33.
@@ -944,15 +959,6 @@ it fits within common partitioning schemes."))))
                   "0znkwljfwwn4y7j20pzz4ilqw8znphrfxns0x1lwdzh3xbr96z3k"))
                 (patches (search-patches
                            "u-boot-nintendo-nes-serial.patch"))))
-      (description "U-Boot is a bootloader used mostly for ARM boards.  It
-also initializes the boards (RAM etc).
-
-This version is for the Nintendo NES Classic Edition.  It is assumed that
-you have added a serial port to pins PB0 and PB1 as described on
-@url{https://linux-sunxi.org/Nintendo_NES_Classic_Edition}.
-
-In order to use FEL mode on the device, hold the Reset button on the
-device while it's being turned on (and a while longer).")
       (native-inputs
        `(("python" ,python-2)
          ,@(package-native-inputs base))))))
@@ -964,17 +970,13 @@ device while it's being turned on (and a while longer).")
   (make-u-boot-package "mx6cuboxi" "arm-linux-gnueabihf"))
 
 (define-public u-boot-novena
-  (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."))))
+  (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=")
+   #:append-description "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."))
 
 (define-public u-boot-cubieboard
   (make-u-boot-package "Cubieboard" "arm-linux-gnueabihf"))
@@ -1130,6 +1132,116 @@ BOOT_TARGET_NVME(func) \\
        `(("firmware" ,arm-trusted-firmware-rk3399)
          ,@(package-native-inputs base))))))
 
+(define*-public (make-u-boot-bin-package u-boot-package
+                                         #:key
+                                         (u-boot-bin "u-boot.bin"))
+  "Return a package with a single U-BOOT-BIN file from the U-BOOT-PACKAGE.
+The package name will be that of the U-BOOT package suffixed with \"-bin\"."
+  (package
+    (name (string-append (package-name u-boot-package) "-bin"))
+    (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-bin)
+                    (string-append out "/" ,u-boot-bin))))))
+    (inputs `(("u-boot" ,u-boot-package)))
+    (home-page (package-home-page u-boot-package))
+    (synopsis (package-synopsis u-boot-package))
+    (description (format #f (string-append
+                             (package-description u-boot-package)
+                             "\n\nThis package only contains the file ~a.")
+                         u-boot-bin))
+    (license (package-license u-boot-package))))
+
+(define-public %u-boot-rpi-efi-configs
+  '("CONFIG_OF_EMBED="
+    "CONFIG_OF_BOARD=y"
+    "CONFIG_BOOTDELAY=1"))
+
+(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-2
+  (make-u-boot-package "rpi_2" "arm-linux-gnueabihf"
+                       #:append-description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-3-32b
+  (make-u-boot-package "rpi_3_32b" "arm-linux-gnueabihf"
+                       #:append-description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-4-32b
+  (make-u-boot-package "rpi_4_32b" "arm-linux-gnueabihf"
+                       #:append-description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-arm64
+  (make-u-boot-package "rpi_arm64" "aarch64-linux-gnu"
+                       #:append-description %u-boot-rpi-description-64-bit))
+
+(define-public u-boot-rpi-2-efi
+  (make-u-boot-package "rpi_2" "arm-linux-gnueabihf"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-3-32b-efi
+  (make-u-boot-package "rpi_3_32b" "arm-linux-gnueabihf"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-4-32b-efi
+  (make-u-boot-package "rpi_4_32b" "arm-linux-gnueabihf"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-arm64-efi
+  (make-u-boot-package "rpi_arm64""aarch64-linux-gnu"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description (string-append
+                                             %u-boot-rpi-efi-description "  "
+                                             %u-boot-rpi-description-64-bit)))
+
+(define-public u-boot-rpi-2-bin (make-u-boot-bin-package u-boot-rpi-2))
+
+(define-public u-boot-rpi-3_32b-bin (make-u-boot-bin-package u-boot-rpi-3-32b))
+
+(define-public u-boot-rpi-4_32b-bin (make-u-boot-bin-package u-boot-rpi-4-32b))
+
+(define-public u-boot-rpi-arm64-bin (make-u-boot-bin-package u-boot-rpi-arm64))
+
+(define-public u-boot-rpi-2-efi-bin (make-u-boot-bin-package u-boot-rpi-2-efi))
+
+(define-public u-boot-rpi-3-32b-efi-bin
+  (make-u-boot-bin-package u-boot-rpi-3-32b-efi))
+
+(define-public u-boot-rpi-4-32b-efi-bin
+  (make-u-boot-bin-package u-boot-rpi-4-32b-efi))
+
+(define-public u-boot-rpi-arm64-efi-bin
+  (make-u-boot-bin-package u-boot-rpi-arm64-efi))
+
 (define-public vboot-utils
   (package
     (name "vboot-utils")

[-- Attachment #6: 05-gnu-linux-new-function-to.patch --]
[-- Type: application/octet-stream, Size: 7145 bytes --]

gnu: linux: New function to modify the configuration of a Linux kernel.

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.
---
 gnu/packages/linux.scm |  124 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index b00b46be47..4febdbdece 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -185,8 +185,27 @@
   #: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 (linux-srcarch)
+  "Return the linux 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 (platform-linux-architecture
+                      (lookup-platform-by-target-or-system
+                        (or (%current-target-system)
+                            (%current-system))))))
+    (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
@@ -1180,6 +1199,111 @@ It has been modified to remove all non-free binary blobs.")
       (inputs (modify-inputs (package-inputs base-linux-libre)
                 (prepend cpio))))))
 
+\f
+;;;
+;;; 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 an origin, 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)
+                (setenv "EXTRAVERSION"
+                        #$(and extra-version
+                               (not (string-null? extra-version))
+                               (string-append "-" extra-version)))
+                (let* ((configs
+                        (string-append "arch/" #$(linux-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)))
+                  (chmod guix_defconfig #o644)
+                  (modify-defconfig guix_defconfig '#$configs)
+                  (invoke "make" "guix_defconfig")
+                  (verify-config ".config" guix_defconfig))))))))
+    (native-inputs
+     (append (if (or (not defconfig)
+                     (string? defconfig))
+                 '()
+                 ;; The defconfig should be an origin 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))))
 
 \f
 ;;;

[-- Attachment #7: 06-gnu-raspberry-pi-add-defconfig.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]

gnu: raspberry-pi: Add defconfig objects to build customized Linux kernels.

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

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, %bcm2711-defconfig, %bcm2711-defconfig-64,
%bcmrpi3-defconfig): New variables containing defconfig objects to build
Linux kernels customized for Raspberry Pi single board computers.
---
 gnu/packages/raspberry-pi.scm |   37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index bb38b8b218..8949d2237a 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 @@
   #: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,36 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                (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
+    ;; This is from commit 7838840 on branch rpi-5.18.y,
+    ;; see https://github.com/raspberrypi/linux/tree/rpi-5.18.y/
+    ;; and https://github.com/raspberrypi/linux/commit/7838840b5606a2051b31da4c598466df7b1c3005
+    "https://raw.githubusercontent.com/raspberrypi/linux/7838840b5606a2051b31da4c598466df7b1c3005/arch/"
+    arch "/configs/" defconfig)
+   sha256-as-base32))
+
+(define-public %bcm2709-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2709_defconfig"
+   "1hcxmsr131f92ay3bfglrggds8ajy904yj3vw7c42i4c66256a79"))
+
+(define-public %bcm2711-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2711_defconfig"
+   "1n7g5yq0hdp8lh0x6bfxph2ff8yn8zisdj3qg0gbn83j4v8i1zbd"))
+
+(define-public %bcm2711-defconfig-64
+  (make-raspi-defconfig
+   "arm64" "bcm2711_defconfig"
+   "0k9q7qvw826v2hrp49xnxnw93pnnkicwx869chvlf7i57461n4i7"))
+
+(define-public %bcmrpi3-defconfig
+  (make-raspi-defconfig
+   "arm64" "bcmrpi3_defconfig"
+   "1bfnl4p0ddx3200dg91kmh2pln36w95y05x1asc312kixv0jgd81"))

[-- Attachment #8: 07-gnu-raspberry-pi-add-helpers.patch --]
[-- Type: application/octet-stream, Size: 3018 bytes --]

gnu: raspberry-pi: Add helpers for config.txt file generation.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   53 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 8949d2237a..12a919d5c6 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -238,6 +238,59 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                #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

[-- Attachment #9: 08-gnu-raspberry-pi-new-function.patch --]
[-- Type: application/octet-stream, Size: 2078 bytes --]

gnu: raspberry-pi: New function to make a package with device-tree files.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 12a919d5c6..92f5d22677 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -30,6 +30,7 @@
   #: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 @@ 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-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

[-- Attachment #10: 09-gnu-raspberry-pi-add-a.patch --]
[-- Type: application/octet-stream, Size: 9958 bytes --]

gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.

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

* 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.
---
 gnu/packages/raspberry-pi.scm                     |   19 +++++
 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl |   73 ++++++++++++++++++++
 gnu/system/examples/raspberry-pi-64.tmpl          |   77 +++++++++++++++++++++
 3 files changed, 169 insertions(+)
 create mode 100644 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
 create mode 100644 gnu/system/examples/raspberry-pi-64.tmpl

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 92f5d22677..3d62b028ba 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 @@ kernel 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-arm64-efi-bin)
+                        #: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..a1e41e3399
--- /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)
+                (target "/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 '("/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..7e18f00d86
--- /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)
+                (target "/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 '("/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

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2022-07-17 16:47             ` Stefan via Guix-patches via
@ 2022-07-17 17:21               ` Vagrant Cascadian
  2022-07-17 18:04                 ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2022-07-17 17:21 UTC (permalink / raw)
  To: Stefan; +Cc: Danny Milosavljevic, 48314

[-- Attachment #1: Type: text/plain, Size: 2005 bytes --]

On 2022-07-17, Stefan wrote:
>>> +(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.
...
> 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?


> 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.


> 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] Patches to install guix system on Raspberry Pi
  2022-07-17 17:21               ` Vagrant Cascadian
@ 2022-07-17 18:04                 ` Stefan via Guix-patches via
  0 siblings, 0 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-17 18:04 UTC (permalink / raw)
  To: Vagrant Cascadian; +Cc: Danny Milosavljevic, 48314

Hi Vagrant!

> 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. ;-)

> it is my understanding that Guix prefers to go with upstream defaults

Would you mind removing that line if committing?


Bye

Stefan



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-17 16:48             ` Stefan via Guix-patches via
@ 2022-07-18 19:23               ` phodina via Guix-patches via
  2022-07-19  6:55                 ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-07-18 19:23 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

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





^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-18 19:23               ` phodina via Guix-patches via
@ 2022-07-19  6:55                 ` Stefan via Guix-patches via
  2022-07-19  7:35                   ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-19  6:55 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Petr!

> 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.

> 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.

> 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



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-19  6:55                 ` Stefan via Guix-patches via
@ 2022-07-19  7:35                   ` phodina via Guix-patches via
  2022-07-20  6:13                     ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-07-19  7:35 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Stefan!
>
> > 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




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-19  7:35                   ` phodina via Guix-patches via
@ 2022-07-20  6:13                     ` Stefan via Guix-patches via
  2022-07-20  7:16                       ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-20  6:13 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Petr!

> 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




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-20  6:13                     ` Stefan via Guix-patches via
@ 2022-07-20  7:16                       ` phodina via Guix-patches via
  2022-07-20 19:42                         ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-07-20  7:16 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314


Hi Stefan,

> > 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.

[1] https://github.com/raspberrypi/firmware


----
Petr




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-20  7:16                       ` phodina via Guix-patches via
@ 2022-07-20 19:42                         ` Stefan via Guix-patches via
  2022-08-12 14:27                           ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-07-20 19:42 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Petr!

> the issue seems to be connected to my guix instance on the host.

Glad to hear you figured it out.

> 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. :-/ 

> 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



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-07-20 19:42                         ` Stefan via Guix-patches via
@ 2022-08-12 14:27                           ` phodina via Guix-patches via
  2022-08-13 10:48                             ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-08-12 14:27 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

[-- Attachment #1: Type: text/plain, Size: 3856 bytes --]

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

 

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: raspberry-guix.diff --]
[-- Type: text/x-patch; name=raspberry-guix.diff, Size: 2112 bytes --]

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")

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-08-12 14:27                           ` phodina via Guix-patches via
@ 2022-08-13 10:48                             ` Stefan via Guix-patches via
  2022-08-14  9:59                               ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-08-13 10:48 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Petr!

> Good news. I managed to run Guix libre kernel on the raspberry pi.

Woot! Great!

> The issue was in the firmware

Good to know!

> 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

> 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.

> 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.

> 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.

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

Thanks, much appreciated!


Bye

Stefan



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-08-13 10:48                             ` Stefan via Guix-patches via
@ 2022-08-14  9:59                               ` phodina via Guix-patches via
  2022-08-14 11:35                                 ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-08-14  9:59 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Stefan!

> > 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.

> > 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.


> > 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




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-08-14  9:59                               ` phodina via Guix-patches via
@ 2022-08-14 11:35                                 ` Stefan via Guix-patches via
  2022-09-01 23:55                                   ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-08-14 11:35 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Petr!

> I got it working also there.

Great!

Which Pi is it exactly? Did you use the same build as for your Pi 4? And the same firmware? Did you see the Linux-Libre gnus and early kernel messages after GRUB?

> 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 :-)

I never tried it. It may be possible.


Bye

Stefan



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-08-14 11:35                                 ` Stefan via Guix-patches via
@ 2022-09-01 23:55                                   ` Stefan via Guix-patches via
  2022-09-02  5:49                                     ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-09-01 23:55 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, dannym, Ludovic Courtès, 48314

Hi Petr!

The firmware I’m using is the same, but all dtb files differ.

Did you use the same set of dtb files on our Pi 3? Especially I have a /boot/efi/bcm2710-rpi-3-b.dtb – which is loaded at boot due to the upstream_kernel=0 setting in dtb.txt –, which you seem to be missing.

I guess that your Pi 3 will not load any dtb file.

My current but not working U-Boot has a different hash.


Bye

Stefan






^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-09-01 23:55                                   ` Stefan via Guix-patches via
@ 2022-09-02  5:49                                     ` phodina via Guix-patches via
  2022-09-04 18:41                                       ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-09-02  5:49 UTC (permalink / raw)
  To: stefan-guix; +Cc: vagrant, dannym, ludo, 48314

[-- Attachment #1: Type: text/plain, Size: 612 bytes --]

Hi Stefan!

I'll check and post the config here but I don't have Raspberry Pi currently with me.

----
Petr

-------- Original Message --------
On Sep 2, 2022, 1:55 AM, Stefan wrote:

> Hi Petr!
>
> The firmware I’m using is the same, but all dtb files differ.
>
> Did you use the same set of dtb files on our Pi 3? Especially I have a /boot/efi/bcm2710-rpi-3-b.dtb – which is loaded at boot due to the upstream_kernel=0 setting in dtb.txt –, which you seem to be missing.
>
> I guess that your Pi 3 will not load any dtb file.
>
> My current but not working U-Boot has a different hash.
>
> Bye
>
> Stefan

[-- Attachment #2: Type: text/html, Size: 845 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v3] Install guix system on Raspberry Pi
  2022-09-02  5:49                                     ` phodina via Guix-patches via
@ 2022-09-04 18:41                                       ` Stefan via Guix-patches via
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-09-04 18:41 UTC (permalink / raw)
  To: phodina; +Cc: 48314

Hi Petr!

> I'll check and post the config here but I don't have Raspberry Pi currently with me.

Thanks, for the offer, but it isn’t necessary any more, I found the reason.

Actually I’m net-booting my Raspberry Pi 3b over network. But due to a known bug in the ROM code, I still have a microSD card inserted with only the bootcode.bin file.

If I boot the Pi with that card inserted, then GRUB has a problem:

error: variable `root' isn't set.
Entering rescue mode...
grub rescue>

If I remove the microSD card, then GRUB has no problem with its root variable, and Guix System is started.

Interestingly this does not happen, if I use the older U-Boot version 2020.10.

The current U-Boot version 2022.04 prints an error message – with and without the mircoSD card inserted:

libfdt fdt_check_header(): FDT_ERR_BADMAGIC

But I’m not sure, if this error message is related.


Bye

Stefan






^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-09-04 18:41                                       ` Stefan via Guix-patches via
@ 2022-09-22 16:18                                         ` Stefan via Guix-patches via
  2022-10-05 13:02                                           ` Ludovic Courtès
                                                             ` (6 more replies)
  0 siblings, 7 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-09-22 16:18 UTC (permalink / raw)
  To: 48314, Vagrant Cascadian, phodina, Danny Milosavljevic
  Cc: Ludovic Courtès

[-- Attachment #1: Type: text/plain, Size: 481 bytes --]

Hi!

I did a rebase onto commit 2e8b4f9bfa00489fd3acff305837a79af236e183.

Vagrant, there was a comment left about removing "CONFIG_BOOTDELAY=1" for the u-boot, this is now done. I think all review comments have been applied.

There is a new u-boot-rockpro64-rk3399 which I adapted as well to use the #:configs keyword argument.

The function modify-defconfig in guix/build/kconfig.scm no longer interprets "CONFIG_XY=" like "# CONFIG_XY is not set".


Bye

Stefan


[-- Attachment #2: 01-gnu-linux-fix-extra-version.patch --]
[-- Type: application/octet-stream, Size: 3312 bytes --]

gnu: linux: Fix the extra-version parameter in make-linux-libre*.

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

* gnu/packages/linux.scm (make-linux-libre*) ['set-environment]: Make
the Makefile accept EXTRAVERSION from the environment. Fix the usage of
an empty extra-version string. Split this new phase out of and adding
if before …
['configure]: … to make the phases more hackable.
---
 gnu/packages/linux.scm |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 306c18e398..1a35e857c3 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -64,6 +64,7 @@
 ;;; Copyright © 2022 Artyom V. Poptsov <poptsov.artyom@gmail.com>
 ;;; Copyright © 2022 Rene Saavedra <nanuui@protonmail.com>
 ;;; Copyright © 2022 muradm <mail@muradm.net>
+;;; Copyright © 2022 Stefan <stefan-guix@vodafonemail.de>
 
 ;;;
 ;;; This file is part of GNU Guix.
@@ -824,8 +825,8 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
                  (lambda _
                    (substitute* (find-files "." "^Makefile(\\.include)?$")
                      (("/bin/pwd") "pwd"))))
-               (replace 'configure
-                 (lambda* (#:key inputs target #:allow-other-keys)
+               (add-before 'configure 'set-environment
+                 (lambda* (#:key target #:allow-other-keys)
                    ;; Avoid introducing timestamps.
                    (setenv "KCONFIG_NOTIMESTAMP" "1")
                    (setenv "KBUILD_BUILD_TIMESTAMP"
@@ -847,13 +848,16 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
                        (setenv "CROSS_COMPILE" (string-append target "-"))
                        (format #t "`CROSS_COMPILE' set to `~a'~%"
                                (getenv "CROSS_COMPILE"))))
-
+                   ;; Allow EXTRAVERSION to be set via the environment.
+                   (substitute* "Makefile"
+                     (("^ *EXTRAVERSION[[:blank:]]*=") "EXTRAVERSION ?="))
                    (setenv "EXTRAVERSION"
                            #$(and extra-version
-                                  (string-append "-" extra-version)))
-
+                                  (not (string-null? extra-version))
+                                  (string-append "-" extra-version)))))
+               (replace 'configure
+                 (lambda* (#:key inputs #:allow-other-keys)
                    (let ((config (assoc-ref inputs "kconfig")))
-
                      ;; Use a custom kernel configuration file or a default
                      ;; configuration file.
                      (if config
@@ -871,7 +875,7 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
 
                      (invoke "make" "oldconfig"))))
                (replace 'install
-                 (lambda* (#:key inputs native-inputs #:allow-other-keys)
+                 (lambda* (#:key inputs #:allow-other-keys)
                    (let ((moddir (string-append #$output "/lib/modules"))
                          (dtbdir (string-append #$output "/lib/dtbs")))
                      ;; Install kernel image, kernel configuration and link map.

[-- Attachment #3: 02-gnu-bootloader-rework-chaining.patch --]
[-- Type: application/octet-stream, Size: 38600 bytes --]

gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.

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

* 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")
     …))
 …)
)
---
 doc/guix.texi                |   58 ++++++++---
 gnu/bootloader.scm           |  104 ++++++++++----------
 gnu/bootloader/grub.scm      |  215 ++++++++++++++++++++++++++----------------
 gnu/packages/bootloaders.scm |   90 ++++++++++++++++++
 4 files changed, 318 insertions(+), 149 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index eb12efa85e..17f5ffb431 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -37308,8 +37308,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{grub-efi-removable-bootloader},
-@code{extlinux-bootloader} and @code{u-boot-bootloader} are supported.
+@code{grub-efi-removable-bootloader}, @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
@@ -37318,15 +37319,29 @@ modules.  In particular, @code{(gnu bootloader u-boot)} contains definitions
 of bootloaders for a wide range of ARM and AArch64 systems, using the
 @uref{https://www.denx.de/wiki/U-Boot/, U-Boot bootloader}.
 
+@vindex grub-bootloader
+@code{grub-bootloader} allows you to boot in particular Intel-based machines
+in ``legacy'' BIOS mode.
+
 @vindex grub-efi-bootloader
 @code{grub-efi-bootloader} allows to boot on modern systems using the
 @dfn{Unified Extensible Firmware Interface} (UEFI).  This is what you should
 use if the installation image contains a @file{/sys/firmware/efi} directory
 when you boot it on your system.
 
-@vindex grub-bootloader
-@code{grub-bootloader} allows you to boot in particular Intel-based machines
-in ``legacy'' BIOS mode.
+@vindex grub-efi-removable-bootloader
+@code{grub-efi-removable-bootloader} allows you to boot your system from
+removable media by writing the GRUB file to the UEFI-specification location of
+@file{/EFI/BOOT/BOOTX64.efi} of the boot directory, usually @file{/boot/efi}.
+This is also useful for some UEFI firmwares that ``forget'' their configuration
+from their non-volatile storage. Like @code{grub-efi-bootloader}, this can only
+be used if the @file{/sys/firmware/efi} directory is available.
+
+@quotation Note
+This @emph{will} overwrite the GRUB file from any other operating systems that
+also place their GRUB file in the UEFI-specification location; making them
+unbootable.
+@end quotation
 
 @vindex grub-efi-netboot-bootloader
 @code{grub-efi-netboot-bootloader} allows you to boot your system over network
@@ -37335,9 +37350,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
@@ -37366,25 +37382,33 @@ this constellation the symlinks will work.
 For other constellations you will have to program your own bootloader
 installer, which then takes care to make necessary files from the store
 accessible through TFTP, for example by copying them into the TFTP root
-directory to your @code{targets}.
+directory for 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-removable-bootloader
-@code{grub-efi-removable-bootloader} allows you to boot your system from
-removable media by writing the GRUB file to the UEFI-specification location of
-@file{/EFI/BOOT/BOOTX64.efi} of the boot directory, usually @file{/boot/efi}.
-This is also useful for some UEFI firmwares that ``forget'' their configuration
-from their non-volatile storage. Like @code{grub-efi-bootloader}, this can only
-be used if the @file{/sys/firmware/efi} directory is available.
+If a local EFI System Partition (ESP) or a similar partition with a FAT file
+system is mounted in @code{targets}, then symlinks cannot be created.  In this
+case everything will be prepared for booting from local storage, simialar as if
+using @code{grub-efi-bootloader}, with the difference that all GRUB binaries
+reside on @code{targets}, too, like needed for booting over network.
+
+@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.
 
 @quotation Note
 This @emph{will} overwrite the GRUB file from any other operating systems that
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index da65b9d5d5..40c7ea6e8a 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -322,26 +322,22 @@ instead~%")))
             (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))
@@ -365,7 +361,7 @@ HOOKS lists additional hook functions to modify the profile."
             (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
@@ -374,11 +370,11 @@ HOOKS lists additional hook functions to modify the profile."
                                 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)))
@@ -386,57 +382,63 @@ HOOKS lists additional hook functions to modify the profile."
                     #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 7283257354..817dd9552b 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -53,13 +53,14 @@
             grub-theme-gfxmode
 
             install-grub-efi-removable
-            install-grub-efi-netboot
+            make-grub-efi-netboot-installer
 
             grub-bootloader
             grub-efi-bootloader
             grub-efi-removable-bootloader
             grub-efi32-bootloader
             grub-efi-netboot-bootloader
+            grub-efi-netboot-removable-bootloader
             grub-mkrescue-bootloader
             grub-minimal-bootloader
 
@@ -353,7 +354,7 @@ code."
         ((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))
@@ -453,9 +454,7 @@ menuentry ~s {
   (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))))
@@ -481,8 +480,6 @@ set lang=~a~%"
 
   (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))
@@ -533,6 +530,16 @@ fi~%"))))
                  #: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")
+
 \f
 
 ;;;
@@ -674,42 +681,31 @@ fi~%"))))
                               ((target-arm?) "--target=arm-efi"))
                         "--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.
@@ -719,17 +715,18 @@ bootloader-configuration in:
 
 (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.
@@ -739,34 +736,78 @@ paths on the TFTP server side are unknown.
 
 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")))))))))))
 
 \f
 
@@ -784,7 +825,7 @@ considered for security aspects."
    (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
@@ -794,11 +835,12 @@ considered for security aspects."
 
 (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-removable-bootloader
   (bootloader
@@ -813,11 +855,22 @@ considered for security aspects."
    (name 'grub-efi32)
    (package grub-efi32)))
 
-(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 210bc30536..658de5a808 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 © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
+;;; Copyright © 2021 Stefan <stefan-guix@vodafonemail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -67,13 +68,17 @@
   #: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
@@ -392,6 +397,91 @@ menu to select one of the installed operating systems.")
                   (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

[-- Attachment #4: 03-build-kconfig-add-new-module.patch --]
[-- Type: application/octet-stream, Size: 19389 bytes --]

build: kconfig: Add new module to modify defconfig files.

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

* guix/build/kconfig.scm (config-string->pair, (pair->config-string,
defconfig->alist, modify-defconfig, verify-config): New file with
functions for handling of defconfig and .config files.
* gnu/packages/bootloaders.scm (make-u-boot-package,
make-u-boot-sunxi64-package): Adding new keyword arguments to pass and/
or modify a defconfig file.
(u-boot-{am335x-boneblack,pinebook,u-boot-novena,rockpro64-rk3399}):
Simplify packages by using the new keyword arguments of the former
functions.
* Makefile.am: Adding guix/build/kconfig.scm to MODULES.
---
 Makefile.am                  |    1 
 gnu/packages/bootloaders.scm |  111 +++++++++++--------------
 guix/build/kconfig.scm       |  185 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 234 insertions(+), 63 deletions(-)
 create mode 100644 guix/build/kconfig.scm

diff --git a/Makefile.am b/Makefile.am
index 22dcc43f99..92ba939ab4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -235,6 +235,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 658de5a808..1f00c9a041 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -778,8 +778,9 @@ def test_ctrl_c"))
 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)))))
@@ -797,8 +798,11 @@ board-independent tools.")))
       (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"
@@ -809,9 +813,19 @@ board-independent tools.")))
          (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))
+                       (verify-config ".config" config-file))
                      (begin
                        (display "Invalid board name. Valid board names are:"
                                 (current-error-port))
@@ -865,7 +879,11 @@ board-independent tools.")))
   (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")
@@ -874,25 +892,13 @@ also initializes the boards (RAM etc).
 
 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
@@ -922,20 +928,10 @@ it fits within common partitioning schemes.")
   (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"))
@@ -986,25 +982,17 @@ device while it's being turned on (and a while longer).")
   (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 is not set"))))
     (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"))
@@ -1092,7 +1080,15 @@ to Novena upstream, does not load u-boot.img from the first partition.")
          ,@(package-native-inputs base))))))
 
 (define-public u-boot-rockpro64-rk3399
-  (let ((base (make-u-boot-package "rockpro64-rk3399" "aarch64-linux-gnu")))
+  (let ((base (make-u-boot-package "rockpro64-rk3399" "aarch64-linux-gnu"
+               #:configs '("CONFIG_USB=y"
+                           "CONFIG_AHCI=y"
+                           "CONFIG_AHCI_PCI=y"
+                           "CONFIG_SATA=y"
+                           "CONFIG_SATA_SIL=y"
+                           "CONFIG_SCSI=y"
+                           "CONFIG_SCSI_AHCI=y"
+                           "CONFIG_DM_SCSI=y"))))
     (package
       (inherit base)
       (arguments
@@ -1103,19 +1099,8 @@ to Novena upstream, does not load u-boot.img from the first partition.")
                 (lambda* (#:key inputs #:allow-other-keys)
                   (setenv "BL31"
                           (search-input-file inputs "/bl31.elf"))))
-              (add-after 'unpack 'patch-config
+              (add-after 'unpack 'patch-header
                 (lambda _
-                  (substitute* "configs/rockpro64-rk3399_defconfig"
-                    (("CONFIG_USB=y") "\
-CONFIG_USB=y
-CONFIG_AHCI=y
-CONFIG_AHCI_PCI=y
-CONFIG_SATA=y
-CONFIG_SATA_SIL=y
-CONFIG_SCSI=y
-CONFIG_SCSI_AHCI=y
-CONFIG_DM_SCSI=y
-"))
                   (substitute* "include/config_distro_bootcmd.h"
                     (("\"scsi_need_init=false")
                      "\"setenv scsi_need_init false")
diff --git a/guix/build/kconfig.scm b/guix/build/kconfig.scm
new file mode 100644
index 0000000000..0cfaffe056
--- /dev/null
+++ b/guix/build/kconfig.scm
@@ -0,0 +1,185 @@
+;;; 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
+            verify-config))
+
+;; Commentary:
+;;
+;; Builder-side code to modify configurations for the Kconfig build system as
+;; used by Linux and U-Boot.
+;;
+;; Code:
+
+(define (config-string->pair config-string)
+  "Parse a configuration string like \"CONFIG_EXAMPLE=m\" into a key-value pair.
+An error is thrown for invalid configurations.
+
+\"CONFIG_A=y\"            -> '(\"CONFIG_A\" . \"y\")
+\"CONFIG_B=\\\"\\\"\"         -> '(\"CONFIG_B\" . \"\\\"\\\"\")
+\"CONFIG_C=\"             -> '(\"CONFIG_C\" . \"\")
+\"# CONFIG_E is not set\" -> '(\"CONFIG_E\" . #f)
+\"CONFIG_D\"              -> '(\"CONFIG_D\" . #f)
+\"# Any comment\"         -> '(#f . \"# Any comment\")
+\"\"                      -> '(#f . \"\")
+\"# CONFIG_E=y\"          -> (error \"Invalid configuration\")
+\"CONFIG_E is not set\"   -> (error \"Invalid configuration\")
+\"Anything else\"         -> (error \"Invalid configuration\")"
+  (define config-regexp
+    (make-regexp
+     ;; (match:substring (string-match "=(.*)" "=") 1) returns "", but the
+     ;; pattern "=(.+)?" makes it return #f instead.  From a "CONFIG_A=" we like
+     ;; to get "", which later emits "CONFIG_A=" again.
+     "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*=[\\t ]*(.*)|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
+
+  (define config-comment-regexp
+    (make-regexp "^([\\t ]*(#.*)?)$"))
+
+  (let ((match (regexp-exec config-regexp (string-trim-right config-string))))
+    (if match
+        (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 (eq? (not comment) (not unset))
+              ;; The key is uncommented and set or commented and unset.
+              (cons key value)
+              ;; The key is set or unset ambigiously.
+              (error (format #f "Invalid configuration, did you mean \"~a\"?"
+                             (pair->config-string (cons key #f)))
+                     config-string)))
+        ;; This is not a valid or ambigious config-string, but mayby a comment.
+        (if (regexp-exec config-comment-regexp config-string)
+            ;; We keep valid comments.
+            (cons #f config-string)
+            (error "Invalid configuration" config-string)))))
+
+(define (pair->config-string pair)
+  "Convert a PAIR back to a config-string."
+  (let* ((key (first pair))
+         (value (cdr pair)))
+    (if (string? key)
+        (if (string? value)
+            (string-append key "=" value)
+            (string-append "# " key " is not set"))
+        value)))
+
+(define (defconfig->alist defconfig)
+  "Convert the content of a DEFCONFIG (or .config) file into an alist."
+  (with-input-from-file defconfig
+    (lambda ()
+      (let loop ((alist '())
+                 (line (read-line)))
+        (if (eof-object? line)
+            ;; Building the alist is done, now check for duplicates.
+            (let loop ((keys (map first (filter first alist)))
+                       (duplicates '()))
+              (if (null? keys)
+                  ;; The search for duplicates is done.
+                  ;; Return the alist or throw an error on duplicates.
+                  (if (null? duplicates)
+                      alist
+                      (error
+                       (format #f "Duplicate configurations in ~a" defconfig)
+                       duplicates))
+                  ;; Continue the search for duplicates.
+                  (loop (cdr keys)
+                        (if (member (first keys) (cdr keys) equal?)
+                            (cons (first keys) duplicates)
+                            duplicates))))
+            ;; Build the alist.
+            (loop (cons (config-string->pair line) alist)
+                  (read-line)))))))
+
+(define (modify-defconfig defconfig configs)
+  "This function can modify a given DEFCONFIG (or .config) file by adding,
+changing or removing the list of strings in CONFIGS.  This allows customization
+of Kconfig based projects like the kernel Linux or the bootloader 'Das U-Boot'.
+
+These are examples for CONFIGS to add, change or remove configurations to/from
+DEFCONFIG:
+
+'(\"CONFIG_A=\\\"a\\\"\"
+  \"CONFIG_B=0\"
+  \"CONFIG_C=y\"
+  \"CONFIG_D=m\"
+  \"CONFIG_E=\"
+  \"# CONFIG_G is not set\"
+  ;; For convinience this abbrevation can be used for not set configurations.
+  \"CONFIG_F\")
+
+Instead of a list, CONFGIS can be a string with one configuration per line."
+  (let* (;; 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-pairs (map config-string->pair
+                            (append-map (cut string-split <>  #\newline)
+                                        (if (string? configs)
+                                            (list configs)
+                                            configs))))
+         ;; Generate a blocklist from all valid keys in config-pairs.
+         (blocklist (delete #f (map first config-pairs)))
+         ;; Generate an alist from the defconifg without the keys in blocklist.
+         (filtered-defconfig-pairs (remove (lambda (pair)
+                                             (member (first pair) blocklist))
+                                           (defconfig->alist defconfig))))
+    (with-output-to-file defconfig
+      (lambda ()
+        (for-each
+           (lambda (pair)
+             (display (pair->config-string pair))
+             (newline))
+           (append filtered-defconfig-pairs config-pairs))))))
+
+(define (verify-config config defconfig)
+  "Verify that the CONFIG file contains all configurations from the DEFCONFIG
+file and return #t in this case. Otherwise throw an error with the mismatching
+keys and their values."
+  (let* ((config-pairs (defconfig->alist config))
+         (defconfig-pairs (defconfig->alist defconfig))
+         (mismatching-pairs
+          (remove (lambda (pair)
+                    ;; Remove all configurations, whose values are #f and whose
+                    ;; keys are not in config-pairs, as not in config-pairs
+                    ;; means unset, …
+                    (and (not (cdr pair))
+                         (not (assoc-ref config-pairs (first pair)))))
+                  ;; … from the defconfig-pairs different to config-pairs.
+                  (lset-difference equal?
+                                   ;; Remove comments by filtering with first.
+                                   (filter first defconfig-pairs)
+                                   config-pairs))))
+    (if (null? mismatching-pairs)
+        #t
+        (error (format #f
+                       "Mismatching configurations in ~a and ~a"
+                       config
+                       defconfig)
+               (map (lambda (mismatching-pair)
+                      (let* ((key (first mismatching-pair))
+                             (defconfig-value (cdr mismatching-pair))
+                             (config-value (assoc-ref config-pairs key)))
+                        (cons key (list (list config-value defconfig-value)))))
+                    mismatching-pairs)))))

[-- Attachment #5: 04-gnu-bootloader-add-u-boot.patch --]
[-- Type: application/octet-stream, Size: 13153 bytes --]

gnu: bootloader: Add U-Boot packages for Raspberry Pi models.

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

* gnu/packages/bootloader.scm (make-u-boot-package): Add keyword
parameters 'name-suffix' and 'append-description'.
(make-u-boot-bin-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-2{,-efi,-bin,-efi-bin},
u-boot-rpi-3-32b{,-efi,-bin,-efi-bin},
u-boot-rpi-4-32b{,-efi,-bin,-efi-bin},
u-boot-rpi-arm64{,-efi,-bin,-efi-bin}): New packages.
(u-boot-tools): Reuse the description of u-boot.
(u-boot-{am335x-boneblack,am335x-evm,nintendo-nes-classic-edition,
novena}): Make use of new keyword parameters of make-u-boot-package.
---
 gnu/packages/bootloaders.scm |  201 +++++++++++++++++++++++++++++++++---------
 1 file changed, 157 insertions(+), 44 deletions(-)

diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 1f00c9a041..5a35d3cb04 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -635,7 +635,7 @@ tree binary files.  These are board description files used by Linux and BSD.")
     (name "u-boot")
     (version "2022.04")
     (source (origin
-	      (patches
+              (patches
                (list %u-boot-rockchip-inno-usb-patch
                      %u-boot-allow-disabling-openssl-patch
                      %u-boot-sifive-prevent-relocating-initrd-fdt
@@ -774,13 +774,21 @@ def test_ctrl_c"))
                        (setenv "PAGER" "cat")
                        (apply invoke "make" test-target make-flags))))
                  '()))))
-    (description "U-Boot is a bootloader used mostly for ARM boards.  It
-also initializes the boards (RAM etc).  This package provides its
-board-independent tools.")))
-
-(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."
+    (description (string-append (package-description u-boot)
+                                "  This package provides board-independent
+tools of U-Boot."))))
+
+(define*-public (make-u-boot-package board
+                                     triplet
+                                     #:key
+                                     defconfig
+                                     configs
+                                     name-suffix
+                                     append-description)
+  "Returns a U-Boot package for BOARD cross-compiled for TRIPLET with the
+optional DEFCONFIG file and optional configuration changes from CONFIGS.
+A NAME-SUFFIX will be appended to the package name.  An APPEND-DESCRIPTION
+string will be appended to the package description."
   (let ((same-arch? (lambda ()
                       (string=? (%current-system)
                                 (gnu-triplet->nix-system triplet)))))
@@ -788,7 +796,12 @@ optional DEFCONFIG file and optional configuration changes from CONFIGS."
       (inherit u-boot)
       (name (string-append "u-boot-"
                            (string-replace-substring (string-downcase board)
-                                                     "_" "-")))
+                                                     "_" "-")
+                           (or name-suffix "")))
+      (description (if append-description
+                       (string-append (package-description u-boot)
+                                      "\n\n" append-description)
+                       (package-description u-boot)))
       (native-inputs
        `(,@(if (not (same-arch?))
              `(("cross-gcc" ,(cross-gcc triplet))
@@ -879,20 +892,15 @@ optional DEFCONFIG file and optional configuration changes from CONFIGS."
   (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"
-               ;; 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")
-      (description "U-Boot is a bootloader used mostly for ARM boards.  It
-also initializes the boards (RAM etc).
-
-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."))))
+  (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"
+   ;; Patch out other device trees to build an 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\"")
+   #:name-suffix "-boneblack"
+   #:append-description "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."))
 
 (define-public u-boot-am335x-evm
   (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"))
@@ -947,7 +955,14 @@ it fits within common partitioning schemes."))))
 
 (define-public u-boot-nintendo-nes-classic-edition
   (let ((base (make-u-boot-package "Nintendo_NES_Classic_Edition"
-                                   "arm-linux-gnueabihf")))
+                                   "arm-linux-gnueabihf"
+                                   #:append-description "This version is for
+the Nintendo NES Classic Edition.  It is assumed that you have added a serial
+port to pins PB0 and PB1 as described on
+@url{https://linux-sunxi.org/Nintendo_NES_Classic_Edition}.
+
+In order to use FEL mode on the device, hold the Reset button on the
+device while it's being turned on (and a while longer).")))
     (package
       (inherit base)
       ;; Starting with 2019.01, FEL doesn't work anymore on A33.
@@ -962,15 +977,6 @@ it fits within common partitioning schemes."))))
                   "0znkwljfwwn4y7j20pzz4ilqw8znphrfxns0x1lwdzh3xbr96z3k"))
                 (patches (search-patches
                            "u-boot-nintendo-nes-serial.patch"))))
-      (description "U-Boot is a bootloader used mostly for ARM boards.  It
-also initializes the boards (RAM etc).
-
-This version is for the Nintendo NES Classic Edition.  It is assumed that
-you have added a serial port to pins PB0 and PB1 as described on
-@url{https://linux-sunxi.org/Nintendo_NES_Classic_Edition}.
-
-In order to use FEL mode on the device, hold the Reset button on the
-device while it's being turned on (and a while longer).")
       (native-inputs
        `(("python" ,python-2)
          ,@(package-native-inputs base))))))
@@ -982,17 +988,13 @@ device while it's being turned on (and a while longer).")
   (make-u-boot-package "mx6cuboxi" "arm-linux-gnueabihf"))
 
 (define-public u-boot-novena
-  (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 is not set"))))
-    (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."))))
+  (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 is not set")
+   #:append-description "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."))
 
 (define-public u-boot-cubieboard
   (make-u-boot-package "Cubieboard" "arm-linux-gnueabihf"))
@@ -1145,6 +1147,117 @@ BOOT_TARGET_NVME(func) \\
        `(("firmware" ,arm-trusted-firmware-rk3399)
          ,@(package-native-inputs base))))))
 
+(define*-public (make-u-boot-bin-package u-boot-package
+                                         #:key
+                                         (u-boot-bin "u-boot.bin"))
+  "Return a package with a single U-BOOT-BIN file from the U-BOOT-PACKAGE.
+The package name will be that of the U-BOOT package suffixed with \"-bin\"."
+  (package
+    (name (string-append (package-name u-boot-package) "-bin"))
+    (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-bin)
+                    (string-append out "/" ,u-boot-bin))))))
+    (inputs `(("u-boot" ,u-boot-package)))
+    (home-page (package-home-page u-boot-package))
+    (synopsis (package-synopsis u-boot-package))
+    (description (string-append
+                  (package-description u-boot-package)
+                  "\n\n"
+                  (format #f
+                          "This package only contains the file ~a."
+                          u-boot-bin)))
+    (license (package-license u-boot-package))))
+
+(define-public %u-boot-rpi-efi-configs
+  '("CONFIG_OF_EMBED"
+    "CONFIG_OF_BOARD=y"))
+
+(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-2
+  (make-u-boot-package "rpi_2" "arm-linux-gnueabihf"
+                       #:append-description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-3-32b
+  (make-u-boot-package "rpi_3_32b" "arm-linux-gnueabihf"
+                       #:append-description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-4-32b
+  (make-u-boot-package "rpi_4_32b" "arm-linux-gnueabihf"
+                       #:append-description %u-boot-rpi-description-32-bit))
+
+(define-public u-boot-rpi-arm64
+  (make-u-boot-package "rpi_arm64" "aarch64-linux-gnu"
+                       #:append-description %u-boot-rpi-description-64-bit))
+
+(define-public u-boot-rpi-2-efi
+  (make-u-boot-package "rpi_2" "arm-linux-gnueabihf"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-3-32b-efi
+  (make-u-boot-package "rpi_3_32b" "arm-linux-gnueabihf"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-4-32b-efi
+  (make-u-boot-package "rpi_4_32b" "arm-linux-gnueabihf"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description %u-boot-rpi-efi-description-32-bit))
+
+(define-public u-boot-rpi-arm64-efi
+  (make-u-boot-package "rpi_arm64""aarch64-linux-gnu"
+                       #:name-suffix "-efi"
+                       #:configs %u-boot-rpi-efi-configs
+                       #:append-description (string-append
+                                             %u-boot-rpi-efi-description "  "
+                                             %u-boot-rpi-description-64-bit)))
+
+(define-public u-boot-rpi-2-bin (make-u-boot-bin-package u-boot-rpi-2))
+
+(define-public u-boot-rpi-3_32b-bin (make-u-boot-bin-package u-boot-rpi-3-32b))
+
+(define-public u-boot-rpi-4_32b-bin (make-u-boot-bin-package u-boot-rpi-4-32b))
+
+(define-public u-boot-rpi-arm64-bin (make-u-boot-bin-package u-boot-rpi-arm64))
+
+(define-public u-boot-rpi-2-efi-bin (make-u-boot-bin-package u-boot-rpi-2-efi))
+
+(define-public u-boot-rpi-3-32b-efi-bin
+  (make-u-boot-bin-package u-boot-rpi-3-32b-efi))
+
+(define-public u-boot-rpi-4-32b-efi-bin
+  (make-u-boot-bin-package u-boot-rpi-4-32b-efi))
+
+(define-public u-boot-rpi-arm64-efi-bin
+  (make-u-boot-bin-package u-boot-rpi-arm64-efi))
+
 (define-public vboot-utils
   (package
     (name "vboot-utils")

[-- Attachment #6: 05-gnu-linux-new-function-to.patch --]
[-- Type: application/octet-stream, Size: 6958 bytes --]

gnu: linux: New function to modify the configuration of a Linux kernel.

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.
(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.
---
 gnu/packages/linux.scm |  123 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 1a35e857c3..33bc168074 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -186,8 +186,27 @@
   #: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 (linux-srcarch)
+  "Return the linux 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 (platform-linux-architecture
+                      (lookup-platform-by-target-or-system
+                        (or (%current-target-system)
+                            (%current-system))))))
+    (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
@@ -1179,6 +1198,110 @@ It has been modified to remove all non-free binary blobs.")
       (inputs (modify-inputs (package-inputs base-linux-libre)
                 (prepend cpio))))))
 
+\f
+;;;
+;;; 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 an origin, 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 follows an extension to unset a configuration:
+CONFIG_CMDLINE_EXTEND\")
+
+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)
+                (setenv "EXTRAVERSION"
+                        #$(and extra-version
+                               (not (string-null? extra-version))
+                               (string-append "-" extra-version)))
+                (let* ((configs
+                        (string-append "arch/" #$(linux-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)))
+                  (chmod guix_defconfig #o644)
+                  (modify-defconfig guix_defconfig '#$configs)
+                  (invoke "make" "guix_defconfig")
+                  (verify-config ".config" guix_defconfig))))))))
+    (native-inputs
+     (append (if (or (not defconfig)
+                     (string? defconfig))
+                 '()
+                 ;; The defconfig should be an origin 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))))
 
 \f
 ;;;

[-- Attachment #7: 06-gnu-raspberry-pi-add-defconfig.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]

gnu: raspberry-pi: Add defconfig objects to build customized Linux kernels.

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

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, %bcm2711-defconfig, %bcm2711-defconfig-64,
%bcmrpi3-defconfig): New variables containing defconfig objects to build
Linux kernels customized for Raspberry Pi single board computers.
---
 gnu/packages/raspberry-pi.scm |   37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index bb38b8b218..8949d2237a 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 @@
   #: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,36 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                (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
+    ;; This is from commit 7838840 on branch rpi-5.18.y,
+    ;; see https://github.com/raspberrypi/linux/tree/rpi-5.18.y/
+    ;; and https://github.com/raspberrypi/linux/commit/7838840b5606a2051b31da4c598466df7b1c3005
+    "https://raw.githubusercontent.com/raspberrypi/linux/7838840b5606a2051b31da4c598466df7b1c3005/arch/"
+    arch "/configs/" defconfig)
+   sha256-as-base32))
+
+(define-public %bcm2709-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2709_defconfig"
+   "1hcxmsr131f92ay3bfglrggds8ajy904yj3vw7c42i4c66256a79"))
+
+(define-public %bcm2711-defconfig
+  (make-raspi-defconfig
+   "arm" "bcm2711_defconfig"
+   "1n7g5yq0hdp8lh0x6bfxph2ff8yn8zisdj3qg0gbn83j4v8i1zbd"))
+
+(define-public %bcm2711-defconfig-64
+  (make-raspi-defconfig
+   "arm64" "bcm2711_defconfig"
+   "0k9q7qvw826v2hrp49xnxnw93pnnkicwx869chvlf7i57461n4i7"))
+
+(define-public %bcmrpi3-defconfig
+  (make-raspi-defconfig
+   "arm64" "bcmrpi3_defconfig"
+   "1bfnl4p0ddx3200dg91kmh2pln36w95y05x1asc312kixv0jgd81"))

[-- Attachment #8: 07-gnu-raspberry-pi-add-helpers.patch --]
[-- Type: application/octet-stream, Size: 3018 bytes --]

gnu: raspberry-pi: Add helpers for config.txt file generation.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   53 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 8949d2237a..12a919d5c6 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -238,6 +238,59 @@ Raspberry Pi.  Note: It does not work on Raspberry Pi 1.")
                #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

[-- Attachment #9: 08-gnu-raspberry-pi-new-function.patch --]
[-- Type: application/octet-stream, Size: 2078 bytes --]

gnu: raspberry-pi: New function to make a package with device-tree files.

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

* 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.
---
 gnu/packages/raspberry-pi.scm |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 12a919d5c6..92f5d22677 100644
--- a/gnu/packages/raspberry-pi.scm
+++ b/gnu/packages/raspberry-pi.scm
@@ -30,6 +30,7 @@
   #: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 @@ 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-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

[-- Attachment #10: 09-gnu-raspberry-pi-add-a.patch --]
[-- Type: application/octet-stream, Size: 10078 bytes --]

gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.

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

* 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.
---
 gnu/packages/raspberry-pi.scm                     |   19 +++++
 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl |   74 ++++++++++++++++++++
 gnu/system/examples/raspberry-pi-64.tmpl          |   78 +++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
 create mode 100644 gnu/system/examples/raspberry-pi-64.tmpl

diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
index 92f5d22677..3d62b028ba 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 @@ kernel 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-arm64-efi-bin)
+                        #: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..c635f8e323
--- /dev/null
+++ b/gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
@@ -0,0 +1,74 @@
+;; 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 (list "/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..dd933252c5
--- /dev/null
+++ b/gnu/system/examples/raspberry-pi-64.tmpl
@@ -0,0 +1,78 @@
+;; 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 (list "/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

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
@ 2022-10-05 13:02                                           ` Ludovic Courtès
  2022-10-08 16:22                                           ` Vagrant Cascadian
                                                             ` (5 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Ludovic Courtès @ 2022-10-05 13:02 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, Danny Milosavljevic, phodina, 48314

Hi,

Vagrant, Danny: could you take a look at these patches?  They seem to
have fallen through the cracks.

TIA.  :-)

Ludo’.

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

> Hi!
>
> I did a rebase onto commit 2e8b4f9bfa00489fd3acff305837a79af236e183.
>
> Vagrant, there was a comment left about removing "CONFIG_BOOTDELAY=1" for the u-boot, this is now done. I think all review comments have been applied.
>
> There is a new u-boot-rockpro64-rk3399 which I adapted as well to use the #:configs keyword argument.
>
> The function modify-defconfig in guix/build/kconfig.scm no longer interprets "CONFIG_XY=" like "# CONFIG_XY is not set".
>
>
> Bye
>
> Stefan




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
  2022-10-05 13:02                                           ` Ludovic Courtès
@ 2022-10-08 16:22                                           ` Vagrant Cascadian
  2022-10-09 13:41                                             ` Stefan via Guix-patches via
  2022-12-01 14:25                                           ` [bug#48314] [PATCH] " Maxim Cournoyer
                                                             ` (4 subsequent siblings)
  6 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2022-10-08 16:22 UTC (permalink / raw)
  To: Stefan, 48314, phodina, Danny Milosavljevic; +Cc: Ludovic Courtès

[-- Attachment #1: Type: text/plain, Size: 15986 bytes --]

On 2022-09-22, Stefan wrote:
> I did a rebase onto commit 2e8b4f9bfa00489fd3acff305837a79af236e183.

Thanks! It definitely looks like great progress.

> Vagrant, there was a comment left about removing "CONFIG_BOOTDELAY=1"
> for the u-boot, this is now done. I think all review comments have
> been applied.

Great!

> There is a new u-boot-rockpro64-rk3399 which I adapted as well to use
> the #:configs keyword argument.

I like how that works.

> The function modify-defconfig in guix/build/kconfig.scm no longer
> interprets "CONFIG_XY=" like "# CONFIG_XY is not set".

Nervous about how that actually works, but hopefully it plays out correctly.


This whole patch series is large and overwhelming and at least a bit
beyond my abilities to wrap my head around (which has certainly caused
me to wait a bit to review)... so I cannot possibly comment on weather
the series as a whole is "good", through no fault of the patch
author(s)! I will try and comment where I can, but really need help to
review it in any meaningful way.

Also from what I recall on earlier iterations of this patch series,
different reviewers seemed to have differing style recommendations
around weather to split patches into smaller commits or merge patches
into combined commits, which can surely be frustrating. I don't *want*
to be frustrating, but I lean towards splitting patches into as small a
commit as possible to wrap my head around the distinct ideas.

I also like to refactor out anything that can be applied directly to
master as soon as possible (e.g. the description-appending patches look
promising for that) with the hope to get the remaining patch series
smaller and smaller with each iteration. Some people may want to do an
all-or-nothing merge. I don't know what's "right" for the guix
community...

With all that out of the way... here goes my attempt to review!


> gnu: linux: Fix the extra-version parameter in make-linux-libre*.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * gnu/packages/linux.scm (make-linux-libre*) ['set-environment]: Make
> the Makefile accept EXTRAVERSION from the environment. Fix the usage of
> an empty extra-version string. Split this new phase out of and adding
> if before …
> ['configure]: … to make the phases more hackable.

Overall, this looks good, to me, though have one question...

> diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
> index 306c18e398..1a35e857c3 100644
> --- a/gnu/packages/linux.scm
> +++ b/gnu/packages/linux.scm
...
> @@ -824,8 +825,8 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
>                   (lambda _
>                     (substitute* (find-files "." "^Makefile(\\.include)?$")
>                       (("/bin/pwd") "pwd"))))
> -               (replace 'configure
> -                 (lambda* (#:key inputs target #:allow-other-keys)
> +               (add-before 'configure 'set-environment
> +                 (lambda* (#:key target #:allow-other-keys)
>                     ;; Avoid introducing timestamps.
>                     (setenv "KCONFIG_NOTIMESTAMP" "1")
>                     (setenv "KBUILD_BUILD_TIMESTAMP"
> @@ -847,13 +848,16 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
>                         (setenv "CROSS_COMPILE" (string-append target "-"))
>                         (format #t "`CROSS_COMPILE' set to `~a'~%"
>                                 (getenv "CROSS_COMPILE"))))
> -
> +                   ;; Allow EXTRAVERSION to be set via the environment.
> +                   (substitute* "Makefile"
> +                     (("^ *EXTRAVERSION[[:blank:]]*=") "EXTRAVERSION ?="))
>                     (setenv "EXTRAVERSION"
>                             #$(and extra-version
> -                                  (string-append "-" extra-version)))
> -
> +                                  (not (string-null? extra-version))
> +                                  (string-append "-" extra-version)))))
> +               (replace 'configure
> +                 (lambda* (#:key inputs #:allow-other-keys)
>                     (let ((config (assoc-ref inputs "kconfig")))
> -
>                       ;; Use a custom kernel configuration file or a default
>                       ;; configuration file.
>                       (if config
> @@ -871,7 +875,7 @@ for ARCH and optionally VARIANT, or #f if there is no such configuration."
>  
>                       (invoke "make" "oldconfig"))))
>                 (replace 'install
> -                 (lambda* (#:key inputs native-inputs #:allow-other-keys)
> +                 (lambda* (#:key inputs #:allow-other-keys)
>                     (let ((moddir (string-append #$output "/lib/modules"))
>                           (dtbdir (string-append #$output "/lib/dtbs")))
>                       ;; Install kernel image, kernel configuration and link map.

Why is native-inputs removed from the 'install phase? Is it no longer
needed? Was it not actually needed before? I see no mention of this
change in the comment.


> gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * 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")
>      …))
>  …)
> )
> ---
>  doc/guix.texi                |   58 ++++++++---
>  gnu/bootloader.scm           |  104 ++++++++++----------
>  gnu/bootloader/grub.scm      |  215 ++++++++++++++++++++++++++----------------
>  gnu/packages/bootloaders.scm |   90 ++++++++++++++++++
>  4 files changed, 318 insertions(+), 149 deletions(-)

There is too much going on here for me to follow, but it is perhaps just
doing a lot of big changes... help? :)


> build: kconfig: Add new module to modify defconfig files.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * guix/build/kconfig.scm (config-string->pair, (pair->config-string,
> defconfig->alist, modify-defconfig, verify-config): New file with
> functions for handling of defconfig and .config files.
> * gnu/packages/bootloaders.scm (make-u-boot-package,
> make-u-boot-sunxi64-package): Adding new keyword arguments to pass and/
> or modify a defconfig file.
> (u-boot-{am335x-boneblack,pinebook,u-boot-novena,rockpro64-rk3399}):
> Simplify packages by using the new keyword arguments of the former
> functions.
> * Makefile.am: Adding guix/build/kconfig.scm to MODULES.
> ---
>  Makefile.am                  |    1 
>  gnu/packages/bootloaders.scm |  111 +++++++++++--------------
>  guix/build/kconfig.scm       |  185 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 234 insertions(+), 63 deletions(-)
>  create mode 100644 guix/build/kconfig.scm

I like how this simplifies the various u-boot-* package definitions!


> gnu: bootloader: Add U-Boot packages for Raspberry Pi models.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * gnu/packages/bootloader.scm (make-u-boot-package): Add keyword
> parameters 'name-suffix' and 'append-description'.

This seems good to me.

> (make-u-boot-bin-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-2{,-efi,-bin,-efi-bin},
> u-boot-rpi-3-32b{,-efi,-bin,-efi-bin},
> u-boot-rpi-4-32b{,-efi,-bin,-efi-bin},
> u-boot-rpi-arm64{,-efi,-bin,-efi-bin}): New packages.
> (u-boot-tools): Reuse the description of u-boot.
> (u-boot-{am335x-boneblack,am335x-evm,nintendo-nes-classic-edition,
> novena}): Make use of new keyword parameters of make-u-boot-package.

It would be nice to first switch the existing u-boot-* packages to use
the new append-description feature one commit (I think this could even
be applied directly to master?), and then add the new functionality
(e.g. make-u-boot-bin-package, *u-boot-rpi-*, etc.) in another commit or
a couple commits. At least, that would make it a little easier for me to
read.


> gnu: linux: New function to modify the configuration of a Linux kernel.
>
> 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.
> (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.
> ---
>  gnu/packages/linux.scm |  123 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 123 insertions(+)

Looks ok to me, though to say I fully understand it would be a stretch. :)


> gnu: raspberry-pi: Add defconfig objects to build customized Linux kernels.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> 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, %bcm2711-defconfig, %bcm2711-defconfig-64,
> %bcmrpi3-defconfig): New variables containing defconfig objects to build
> Linux kernels customized for Raspberry Pi single board computers.
> ---
>  gnu/packages/raspberry-pi.scm |   37 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 36 insertions(+), 1 deletion(-)

Seems good. I think I even understand this one!


> gnu: raspberry-pi: Add helpers for config.txt file generation.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * 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.
> ---
>  gnu/packages/raspberry-pi.scm |   53 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)

Seems good.


> From: Stefan <stefan-guix@vodafonemail.de>
>
> * 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.
> ---
>  gnu/packages/raspberry-pi.scm |   21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
>
> diff --git a/gnu/packages/raspberry-pi.scm b/gnu/packages/raspberry-pi.scm
> index 12a919d5c6..92f5d22677 100644
> --- a/gnu/packages/raspberry-pi.scm
> +++ b/gnu/packages/raspberry-pi.scm
> @@ -30,6 +30,7 @@
>    #: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 @@ 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-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
> gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * 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.

I'd split this into two commits, one adding
grub-efi-bootloader-chain-raspi-64, and one adding examples using it,
but that is really a judgement call.


live well,
  vagrant

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-10-08 16:22                                           ` Vagrant Cascadian
@ 2022-10-09 13:41                                             ` Stefan via Guix-patches via
  2022-10-30 12:39                                               ` phodina via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-10-09 13:41 UTC (permalink / raw)
  To: Vagrant Cascadian
  Cc: Danny Milosavljevic, Ludovic Courtès, phodina, 48314

Hi Vagrant!

>> The function modify-defconfig in guix/build/kconfig.scm no longer
>> interprets "CONFIG_XY=" like "# CONFIG_XY is not set".
> 
> Nervous about how that actually works, but hopefully it plays out correctly.

This is described in the doc-string of config-string->pair in the module (guix build kconfig), which contains a regular expression for the parsing.

Basically any “# CONFIG_X is not set” or “CONFIG_X” is treated as unset and produces a ("CONFIG_X" . #f). The latter is just for convenience, as the first one is hard to remember and easy to get wrong. Any “CONFIG=…” is treated as set and produces a ("CONFIG_X" . "…").

Anything else except comments with “#…” or empty lines will throw an error.

In a previous patch “CONFIG_X=“ was also treated as unset, which was confusing, as this is actually a valid makefile assignment.

The function pair->config-string produces a “# CONFIG_X is not set” for any #f value, or a proper assignment otherwise.

> This whole patch series is large and overwhelming and at least a bit
> beyond my abilities to wrap my head around (which has certainly caused
> me to wait a bit to review)... so I cannot possibly comment on weather
> the series as a whole is "good", through no fault of the patch
> author(s)! I will try and comment where I can, but really need help to
> review it in any meaningful way.

I’ll try to help.

> Also from what I recall on earlier iterations of this patch series,
> different reviewers seemed to have differing style recommendations
> around weather to split patches into smaller commits or merge patches
> into combined commits, which can surely be frustrating. I don't *want*
> to be frustrating, but I lean towards splitting patches into as small a
> commit as possible to wrap my head around the distinct ideas.
> 
> I also like to refactor out anything that can be applied directly to
> master as soon as possible (e.g. the description-appending patches look
> promising for that) with the hope to get the remaining patch series
> smaller and smaller with each iteration. Some people may want to do an
> all-or-nothing merge. I don't know what's "right" for the guix
> community…

The single patch files can be applied separately, they don’t break anything. Some reordering is also possible. In particular, 02-gnu-bootloader-rework-chaining.patch (the monster) can be applied later but before 09-gnu-raspberry-pi-add-a.patch.

> With all that out of the way... here goes my attempt to review!
> 
> 
>> gnu: linux: Fix the extra-version parameter in make-linux-libre*.

> Overall, this looks good, to me, though have one question…

Great! :-)

> Why is native-inputs removed from the 'install phase? Is it no longer
> needed? Was it not actually needed before? I see no mention of this
> change in the comment.

Exactly, it was even not needed before, an obsolete argument, which I removed. I figured this out by chance when selecting the needed arguments for the 'set-environment phase.

>> gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.

> There is too much going on here for me to follow, but it is perhaps just
> doing a lot of big changes… help? :)

As noted, this patch can be delayed before 09-gnu-raspberry-pi-add-a.patch is to be applied.

Before this patch, the bootloader-installer of efi-bootloader-chain called grub-mknetdir (actually the installer of grub-efi-netboot-bootloader) and copied the content of a special collection folder of the bootloader-profile. That collection folder was very special and did not fit well to the bootloader-profile idea. Well, actually the grub-efi package with all its tools being part of the profile was the problem, making the collection folder necessary. 

With this patch the packages of grub-efi-netboot-bootloader and grub-efi-netboot-removable-bootloader are already pre-installed – grub-mknetdir is already called during package creation. Their installer just copies the whole package/profile into the target directory. The efi-bootloader-chain only creates a profile with the bootloader (e.g. grub-efi-netboot-bootloader) and additional packages or files. The collection folder is not needed any more. Most complexity got moved from the bootloader installation time to the package build time.

Other patches generate more “pre-installed“ files like u-boot.bin, config.txt, device-tree files, etc., which now all fit much bettor to the bootloader-profile idea, to just be copied to a target directory.

This patch is also inspired by older comments. Maybe take a look at the comments below <https://issues.guix.gnu.org/issue/41066#25> and especially at <https://issues.guix.gnu.org/issue/41066#28-lineno18>

I don’t think splitting this into smaller parts is possible without a breakage.  

>> build: kconfig: Add new module to modify defconfig files.

> I like how this simplifies the various u-boot-* package definitions!

Great! :-)

>> gnu: bootloader: Add U-Boot packages for Raspberry Pi models.

> This seems good to me.

Great! :-)

> It would be nice to first switch the existing u-boot-* packages to use
> the new append-description feature one commit (I think this could even
> be applied directly to master?), and then add the new functionality
> (e.g. make-u-boot-bin-package, *u-boot-rpi-*, etc.) in another commit or
> a couple commits. At least, that would make it a little easier for me to
> read.

Splitting is possible.

>> gnu: linux: New function to modify the configuration of a Linux kernel.

> Looks ok to me, though to say I fully understand it would be a stretch. :)

The idea here is very similar to the use for u-boot: Take some Linux, pretend some defconfig being used, do simple modifications to it, and verify the result.

The defconfig can be provided via #:defconfig (any file-like-object or a file-name) or will otherwise be generated with “make savedefconfig”.

The function (make-defconfig) is a helper to use a defconfig file from some url. 

The function system->linux-srcarch is needed to locate existing defconfig files in the Linux sources like arch/arm/configs/bcm2835_defconfig, so that you can just pass the filename “bcm2835_defconfig” to #:defconfig. This enables the use of defconfig files existing in the Linux sources. As Kbuild expects defconfig files at a certain location, this function is also needed to copy an own defconfig file there. 

There was once a blog post about a custom Linux kernel stating “Suggestions and contributions toward working toward a satisfactory custom initrd and kernel are welcome!”, see <https://guix.gnu.org/de/blog/2019/creating-and-using-a-custom-linux-kernel-on-guix-system/>. This is my take including a verification for the kernel. :-)

>> gnu: raspberry-pi: Add defconfig objects to build customized Linux kernels.

> Seems good. I think I even understand this one!

Great! :-)

>> gnu: raspberry-pi: Add helpers for config.txt file generation.

> Seems good.

Great! :-)

>> gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.

> I'd split this into two commits, one adding
> grub-efi-bootloader-chain-raspi-64, and one adding examples using it,
> but that is really a judgement call.

True. Combining the example with the new function was my choice. If you don't mind, I'd keep it this way.

Thanks a lot for the review, Vagrant!

How to proceed from here? 

I'd suggest to postpone 02-gnu-bootloader-rework-chaining.patch and 09-gnu-raspberry-pi-add-a.patch, until all others got merged.

To me it seems possible to commit these patches as they are in this order:

01-gnu-linux-fix-extra-version.patch
03-build-kconfig-add-new-module.patch
05-gnu-linux-new-function-to.patch
06-gnu-raspberry-pi-add-defconfig.patch
07-gnu-raspberry-pi-add-helpers.patch
08-gnu-raspberry-pi-new-function.patch

Then I could send a reduced patch-series with:

splitted 04-gnu-bootloader-add-u-boot.patch
02-gnu-bootloader-rework-chaining.patch
09-gnu-raspberry-pi-add-a.patch

What do you think?


Bye

Stefan





^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-10-09 13:41                                             ` Stefan via Guix-patches via
@ 2022-10-30 12:39                                               ` phodina via Guix-patches via
  2022-10-30 17:08                                                 ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: phodina via Guix-patches via @ 2022-10-30 12:39 UTC (permalink / raw)
  To: Stefan; +Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	48314

Hi Stefan,

I've recently encoutered an issue on Raspberry Pi 4 when attaching USB Hard drive.

I formatted it with fat32 and ext4. Ran `guix system init config.scm /init`.

I selected `(initrd-modules (list "xhci_pci" "pcie_brcmstb"))` in the config and rebooted.

Unfortunately I get error about missing file:

```
error: file /gnu/store/xxx-raw-initrd/initrd.cpio.gz not found
Press any key to continue ...
```

After that I get kernel panic.

Shoudn't the initrd be placed in the EFI partition? That way you get the modules in order to  mount the rootfs.

Should I copy it and modify the Grub entry?

The goal here is to run completly from USB then there won't be any need for SD card.

----
Petr




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-10-30 12:39                                               ` phodina via Guix-patches via
@ 2022-10-30 17:08                                                 ` Stefan via Guix-patches via
  2022-10-30 17:31                                                   ` Stefan via Guix-patches via
  0 siblings, 1 reply; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-10-30 17:08 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	48314

Hi Petr!

> Shoudn't the initrd be placed in the EFI partition?

No. As on a PC, the /boot/grub/grub.cfg lists the location of the initrd in the store, as it does for the kernel as well. Grub is able to read from most file-systems and load the initrd.

> Should I copy it and modify the Grub entry?

No.

> Unfortunately I get error about missing file:
> 
> ```
> error: file /gnu/store/xxx-raw-initrd/initrd.cpio.gz not found
> Press any key to continue ...
> ```

Is this error from GRUB? Is that file actually existing?

> I formatted it with fat32 and ext4. Ran `guix system init config.scm /init`.
> 
> I selected `(initrd-modules (list "xhci_pci" "pcie_brcmstb"))` in the config and rebooted.

Was there maybe some error message about missing kernel-modules?

Was the GRUB screen as usual with a background graphic? Because that is loaded from the store as well.

If not, then GRUB is not able to access the store. Check the content of /boot/efi/efi/boot/grub.cfg. It contains two lines: one to search for the right file-system containing the /boot/grub/grub.cfg, and another to load it.

The search line is usually referring to an fs-uuid determined during the bootloader installation with the help of the grub-probe command. However, there is the risk grub-probe does not find an fs-uuid. In that case as a fallback the search command will look for a /boot/grub/grub.cfg on any readable file-system. Maybe it found one on a wrong file-system?

> The goal here is to run completly from USB then there won't be any need for SD card.


From what you wrote, U-Boot is able to boot from USB and load GRUB. I’m just not absolutely sure, if GRUB is able to boot from USB on the RPi 4, but I would think so.


Bye

Stefan



^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2022-10-30 17:08                                                 ` Stefan via Guix-patches via
@ 2022-10-30 17:31                                                   ` Stefan via Guix-patches via
  0 siblings, 0 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-10-30 17:31 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	48314

Hi Petr!

It must be that your initrd is missing in the store.

The /boot/grub/grub.cfg is the only file referring to the initrd and GRUB is the only program reading it. So an error message referring to the initrd must be from GRUB and then GRUB was able to access your root-file-system, which should contain /boot and /gnu/store.


Bye

Stefan

> Am 30.10.2022 um 18:08 schrieb Stefan <stefan-guix@vodafonemail.de>:
> 
> Hi Petr!
> 
>> Shoudn't the initrd be placed in the EFI partition?
> 
> No. As on a PC, the /boot/grub/grub.cfg lists the location of the initrd in the store, as it does for the kernel as well. Grub is able to read from most file-systems and load the initrd.
> 
>> Should I copy it and modify the Grub entry?
> 
> No.
> 
>> Unfortunately I get error about missing file:
>> 
>> ```
>> error: file /gnu/store/xxx-raw-initrd/initrd.cpio.gz not found
>> Press any key to continue ...
>> ```
> 
> Is this error from GRUB? Is that file actually existing?
> 
>> I formatted it with fat32 and ext4. Ran `guix system init config.scm /init`.
>> 
>> I selected `(initrd-modules (list "xhci_pci" "pcie_brcmstb"))` in the config and rebooted.
> 
> Was there maybe some error message about missing kernel-modules?
> 
> Was the GRUB screen as usual with a background graphic? Because that is loaded from the store as well.
> 
> If not, then GRUB is not able to access the store. Check the content of /boot/efi/efi/boot/grub.cfg. It contains two lines: one to search for the right file-system containing the /boot/grub/grub.cfg, and another to load it.
> 
> The search line is usually referring to an fs-uuid determined during the bootloader installation with the help of the grub-probe command. However, there is the risk grub-probe does not find an fs-uuid. In that case as a fallback the search command will look for a /boot/grub/grub.cfg on any readable file-system. Maybe it found one on a wrong file-system?
> 
>> The goal here is to run completly from USB then there won't be any need for SD card.
> 
> 
> From what you wrote, U-Boot is able to boot from USB and load GRUB. I’m just not absolutely sure, if GRUB is able to boot from USB on the RPi 4, but I would think so.
> 
> 
> Bye
> 
> Stefan




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2021-05-09 15:32 [bug#48314] Patches to install guix system on Raspberry Pi Stefan
                   ` (2 preceding siblings ...)
  2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
@ 2022-10-30 17:32 ` Stefan via Guix-patches via
  2022-10-30 17:33 ` Stefan via Guix-patches via
  4 siblings, 0 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-10-30 17:32 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	48314


Hi Petr!

It must be that your initrd is missing in the store.

The /boot/grub/grub.cfg is the only file referring to the initrd and GRUB is the only program reading it. So an error message referring to the initrd must be from GRUB and then GRUB was able to access your root-file-system, which should contain /boot and /gnu/store.


Bye

Stefan




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH v5] Install guix system on Raspberry Pi
  2021-05-09 15:32 [bug#48314] Patches to install guix system on Raspberry Pi Stefan
                   ` (3 preceding siblings ...)
  2022-10-30 17:32 ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
@ 2022-10-30 17:33 ` Stefan via Guix-patches via
  4 siblings, 0 replies; 74+ messages in thread
From: Stefan via Guix-patches via @ 2022-10-30 17:33 UTC (permalink / raw)
  To: phodina; +Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	48314






^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH] Install guix system on Raspberry Pi
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
  2022-10-05 13:02                                           ` Ludovic Courtès
  2022-10-08 16:22                                           ` Vagrant Cascadian
@ 2022-12-01 14:25                                           ` Maxim Cournoyer
  2022-12-01 15:32                                           ` Maxim Cournoyer
                                                             ` (3 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Maxim Cournoyer @ 2022-12-01 14:25 UTC (permalink / raw)
  To: Stefan
  Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	phodina, 48314

Hi Stefan!

Some comments/question for this proposed change.

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

[...]

> gnu: linux: Fix the extra-version parameter in make-linux-libre*.

This first commit LGTM.  I'll push it shortly.

[...]

> gnu: bootloader: Rework chaining, add grub-efi-netboot-removable-bootloader.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * 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")
>      …))
>  …)
> )

That's *a lot* of text :-). For the future, some of the things there are
improvements rather than necessary changes it seems, so could have been
split into something different, smaller & easier to review.  I've
standardized to use the imperative tense in the change log message (Added
-> Add for example).

[...]

> +(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")

In GRUB-EFI-CONFIGURATION-FILE above, why do we hard-code grub-efi
instead of retrieving it from config the same as for
GRUB-CONFIGURATION-FILE?  It seems that'd be preferable, as otherwise
someone cannot override GRUB-EFI with their own variant, no?

>  \f
>  
>  ;;;
> @@ -674,42 +681,31 @@ fi~%"))))
>                                ((target-arm?) "--target=arm-efi"))
>                          "--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.
> @@ -719,17 +715,18 @@ bootloader-configuration in:

I've unified the above docstring as one; otherwise it was mangled with
Scheme and it wouldn't have appeared as a whole in the online
documentation system of Guile.

I've improved the writing a bit (I think!), use gexps in some places,
and other smallish changes that amount to:

--8<---------------cut here---------------start------------->8---
4 files changed, 80 insertions(+), 76 deletions(-)
doc/guix.texi                | 17 +++++++++--------
gnu/bootloader.scm           | 11 +++++------
gnu/bootloader/grub.scm      | 77 ++++++++++++++++++++++++++++++++++++++++-------------------------------------
gnu/packages/bootloaders.scm | 51 ++++++++++++++++++++++++++-------------------------

modified   doc/guix.texi
@@ -38083,17 +38083,18 @@ 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}.
 
-If a local EFI System Partition (ESP) or a similar partition with a FAT file
-system is mounted in @code{targets}, then symlinks cannot be created.  In this
-case everything will be prepared for booting from local storage, simialar as if
-using @code{grub-efi-bootloader}, with the difference that all GRUB binaries
-reside on @code{targets}, too, like needed for booting over network.
+If a local EFI System Partition (ESP) or a similar partition with a FAT
+file system is mounted in @code{targets}, then symlinks cannot be
+created.  In this case everything will be prepared for booting from
+local storage, matching the behavior of @code{grub-efi-bootloader}, with
+the difference that all GRUB binaries are copied to @code{targets},
+necessary for booting over the network.
 
 @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.
+@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 with the UEFI specification for removable media.
 
 @quotation Note
 This @emph{will} overwrite the GRUB file from any other operating systems that
modified   gnu/bootloader.scm
@@ -361,8 +361,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* ((output #$output)
-                   (files '#$files)
+            (let* ((files '#$files)
                    (directories (filter name-ends-with-/? files))
                    (names-from-directories
                     (append-map (lambda (directory)
@@ -370,11 +369,11 @@ (define (name-is-store-entry? name)
                                 directories))
                    (names (append names-from-directories
                                   (remove name-ends-with-/? files))))
-              (mkdir-p output)
+              (mkdir-p #$output)
               (if (every file-exists? names)
                   (begin
                     (for-each (lambda (name)
-                               (symlink-to name output
+                               (symlink-to name #$output
                                             (if (name-is-store-entry? name)
                                                 strip-store-file-name
                                                 basename)))
@@ -410,7 +409,7 @@ (define* (efi-bootloader-chain final-bootloader
 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,
+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
@@ -424,7 +423,7 @@ (define* (efi-bootloader-chain final-bootloader
 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
+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)
modified   gnu/bootloader/grub.scm
@@ -685,7 +685,7 @@ (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
+As a grub-efi-netboot package is already pre-installed by 'grub-mknetdir', the
 installer basically copies all files from the bootloader-package (or profile)
 into the bootloader-target directory.
 
@@ -700,12 +700,12 @@ (define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
 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.
+The installer does not manipulate the system's 'UEFI Boot Manager'.
+
+The returned installer accepts the BOOTLOADER, TARGET and MOUNT-POINT
+arguments.  Its job is to copy the BOOTLOADER, which must be a pre-installed
+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.
@@ -720,13 +720,14 @@ (define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
  …)
 
 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.
+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 are 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.
@@ -740,16 +741,18 @@ (define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
 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
+The installer can also be used to prepare booting from local storage, 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."
+  (with-imported-modules '((guix build union))
+    #~(lambda (bootloader target mount-point)
         ;; 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).
+        ;; 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)
@@ -779,35 +782,35 @@ (define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
             (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?)
+                 (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.  Add a 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
+                          (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")))))))))))
+                       (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")))))))))))
 
 \f
 
modified   gnu/packages/bootloaders.scm
@@ -427,8 +427,8 @@ (define-public (make-grub-efi-netboot name subdir)
     (build-system trivial-build-system)
     (arguments
      (let* ((system (string-split (nix-system->gnu-triplet
-                                  (or (%current-target-system)
-                                      (%current-system)))
+                                   (or (%current-target-system)
+                                       (%current-system)))
                                   #\-))
             (arch (first system))
             (boot-efi
@@ -454,29 +454,30 @@ (define-public (make-grub-efi-netboot name subdir)
                          ("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)))
+       (list
+        #:modules ((guix build utils))
+        #:builder
+        #~(begin
+            (use-modules (guix build utils))
+            (let* ((bootloader #$(this-package-input "grub-efi"))
+                   (net-dir #$output)
+                   (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 pre-loaded 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 (list grub-efi))
     (synopsis (package-synopsis grub-efi))
     (description (package-description grub-efi))
     (home-page (package-home-page grub-efi))
--8<---------------cut here---------------end--------------->8---

It's a pity we do not have tests for that, but I'll try to test it
manually and if it works I can push it shortly.  I'd still like feedback
on my question above.

-- 
Thanks,
Maxim




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH] Install guix system on Raspberry Pi
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
                                                             ` (2 preceding siblings ...)
  2022-12-01 14:25                                           ` [bug#48314] [PATCH] " Maxim Cournoyer
@ 2022-12-01 15:32                                           ` Maxim Cournoyer
  2022-12-01 16:22                                           ` Maxim Cournoyer
                                                             ` (2 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Maxim Cournoyer @ 2022-12-01 15:32 UTC (permalink / raw)
  To: Stefan
  Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	phodina, 48314

Hi again,

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

[...]

> +(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))

Another question regarding that same piece of code: why isn't
grub-efi-configuration-file used in the definition of the
grub-efi-bootloader definition?  It's still using
grub-configuration-file.

-- 
Thanks,
Maxim




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH] Install guix system on Raspberry Pi
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
                                                             ` (3 preceding siblings ...)
  2022-12-01 15:32                                           ` Maxim Cournoyer
@ 2022-12-01 16:22                                           ` Maxim Cournoyer
  2022-12-01 18:01                                           ` Maxim Cournoyer
  2022-12-01 19:33                                           ` bug#48314: " Maxim Cournoyer
  6 siblings, 0 replies; 74+ messages in thread
From: Maxim Cournoyer @ 2022-12-01 16:22 UTC (permalink / raw)
  To: Stefan
  Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	phodina, 48314

Hi,

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

[...]

> new file mode 100644
> index 0000000000..0cfaffe056
> --- /dev/null
> +++ b/guix/build/kconfig.scm

[...]

> +(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
> +            verify-config))
> +
> +;; Commentary:
> +;;
> +;; Builder-side code to modify configurations for the Kconfig build system as
> +;; used by Linux and U-Boot.
> +;;
> +;; Code:
> +
> +(define (config-string->pair config-string)
> +  "Parse a configuration string like \"CONFIG_EXAMPLE=m\" into a key-value pair.
> +An error is thrown for invalid configurations.
> +
> +\"CONFIG_A=y\"            -> '(\"CONFIG_A\" . \"y\")
> +\"CONFIG_B=\\\"\\\"\"         -> '(\"CONFIG_B\" . \"\\\"\\\"\")
> +\"CONFIG_C=\"             -> '(\"CONFIG_C\" . \"\")
> +\"# CONFIG_E is not set\" -> '(\"CONFIG_E\" . #f)
> +\"CONFIG_D\"              -> '(\"CONFIG_D\" . #f)
> +\"# Any comment\"         -> '(#f . \"# Any comment\")
> +\"\"                      -> '(#f . \"\")
> +\"# CONFIG_E=y\"          -> (error \"Invalid configuration\")
> +\"CONFIG_E is not set\"   -> (error \"Invalid configuration\")
> +\"Anything else\"         -> (error \"Invalid configuration\")"
> +  (define config-regexp
> +    (make-regexp
> +     ;; (match:substring (string-match "=(.*)" "=") 1) returns "", but the
> +     ;; pattern "=(.+)?" makes it return #f instead.  From a "CONFIG_A=" we like
> +     ;; to get "", which later emits "CONFIG_A=" again.
> +     "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*=[\\t ]*(.*)|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
> +
> +  (define config-comment-regexp
> +    (make-regexp "^([\\t ]*(#.*)?)$"))
> +
> +  (let ((match (regexp-exec config-regexp (string-trim-right config-string))))
> +    (if match
> +        (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 (eq? (not comment) (not unset))
> +              ;; The key is uncommented and set or commented and unset.
> +              (cons key value)
> +              ;; The key is set or unset ambigiously.
> +              (error (format #f "Invalid configuration, did you mean \"~a\"?"
> +                             (pair->config-string (cons key #f)))
> +                     config-string)))
> +        ;; This is not a valid or ambigious config-string, but mayby a comment.
> +        (if (regexp-exec config-comment-regexp config-string)
> +            ;; We keep valid comments.
> +            (cons #f config-string)
> +            (error "Invalid configuration" config-string)))))
> +
> +(define (pair->config-string pair)
> +  "Convert a PAIR back to a config-string."
> +  (let* ((key (first pair))
> +         (value (cdr pair)))
> +    (if (string? key)
> +        (if (string? value)
> +            (string-append key "=" value)
> +            (string-append "# " key " is not set"))
> +        value)))
> +
> +(define (defconfig->alist defconfig)
> +  "Convert the content of a DEFCONFIG (or .config) file into an alist."
> +  (with-input-from-file defconfig
> +    (lambda ()
> +      (let loop ((alist '())
> +                 (line (read-line)))
> +        (if (eof-object? line)
> +            ;; Building the alist is done, now check for duplicates.
> +            (let loop ((keys (map first (filter first alist)))
                                           ^
What is this filter used for here? EDIT: saw later, it's used to filter
out comments.

[...]

> +(define (verify-config config defconfig)
> +  "Verify that the CONFIG file contains all configurations from the DEFCONFIG
> +file and return #t in this case. Otherwise throw an error with the mismatching
> +keys and their values."
> +  (let* ((config-pairs (defconfig->alist config))
> +         (defconfig-pairs (defconfig->alist defconfig))
> +         (mismatching-pairs
> +          (remove (lambda (pair)
> +                    ;; Remove all configurations, whose values are #f and whose
> +                    ;; keys are not in config-pairs, as not in config-pairs
> +                    ;; means unset, …
> +                    (and (not (cdr pair))
> +                         (not (assoc-ref config-pairs (first pair)))))
> +                  ;; … from the defconfig-pairs different to config-pairs.

So, it finds mismatched configurations that exist in both CONFIG and
DEFCONFIG, but it doesn't error when there are configs that exist in
DEFCONFIG but missing from CONFIG, right?  Should it?

> +                  (lset-difference equal?
> +                                   ;; Remove comments by filtering with first.
> +                                   (filter first defconfig-pairs)
> +                                   config-pairs))))
> +    (if (null? mismatching-pairs)
> +        #t
> +        (error (format #f
> +                       "Mismatching configurations in ~a and ~a"
> +                       config
> +                       defconfig)
> +               (map (lambda (mismatching-pair)
> +                      (let* ((key (first mismatching-pair))
> +                             (defconfig-value (cdr mismatching-pair))
> +                             (config-value (assoc-ref config-pairs key)))
> +                        (cons key (list (list config-value defconfig-value)))))
> +                    mismatching-pairs)))))
>
>

I've made the following mostly cosmetic changes:

--8<---------------cut here---------------start------------->8---
2 files changed, 43 insertions(+), 45 deletions(-)
gnu/packages/bootloaders.scm | 18 +++++++++---------
guix/build/kconfig.scm       | 70 ++++++++++++++++++++++++++++++++++------------------------------------

modified   gnu/packages/bootloaders.scm
@@ -792,9 +792,9 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
                                                      "_" "-")))
       (native-inputs
        `(,@(if (not (same-arch?))
-             `(("cross-gcc" ,(cross-gcc triplet))
-               ("cross-binutils" ,(cross-binutils triplet)))
-             `())
+               `(("cross-gcc" ,(cross-gcc triplet))
+                 ("cross-binutils" ,(cross-binutils triplet)))
+               `())
          ,@(package-native-inputs u-boot)))
       (arguments
        `(#:modules ((ice-9 ftw)
@@ -808,8 +808,8 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
          #:make-flags
          (list "HOSTCC=gcc"
                ,@(if (not (same-arch?))
-                   `((string-append "CROSS_COMPILE=" ,triplet "-"))
-                   '()))
+                     `((string-append "CROSS_COMPILE=" ,triplet "-"))
+                     '()))
          #:phases
          (modify-phases %standard-phases
            (replace 'configure
@@ -828,7 +828,7 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
                        (apply invoke "make" `(,@make-flags ,config-name))
                        (verify-config ".config" config-file))
                      (begin
-                       (display "Invalid board name. Valid board names are:"
+                       (display "invalid board name; valid board names are:"
                                 (current-error-port))
                        (let ((suffix-len (string-length "_defconfig"))
                              (entries (scandir "configs")))
@@ -839,7 +839,7 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
                                                (string-drop-right file-name
                                                                   suffix-len))))
                                    (sort entries string-ci<)))
-                       (error "Invalid boardname ~s." ,board))))))
+                       (error "invalid boardname ~s" ,board))))))
            (add-after 'configure 'disable-tools-libcrypto
              ;; Disable libcrypto due to GPL and OpenSSL license
              ;; incompatibilities
@@ -881,8 +881,8 @@ (define-public u-boot-malta

 (define-public u-boot-am335x-boneblack
   (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
+               ;; Patch out other device trees to build an 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
modified   guix/build/kconfig.scm
@@ -50,7 +50,8 @@ (define config-regexp
      ;; (match:substring (string-match "=(.*)" "=") 1) returns "", but the
      ;; pattern "=(.+)?" makes it return #f instead.  From a "CONFIG_A=" we like
      ;; to get "", which later emits "CONFIG_A=" again.
-     "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*=[\\t ]*(.*)|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
+     (string-append "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*="
+                    "[\\t ]*(.*)|([\\t ]+is[\\t ]+not[\\t ]+set))?$")))

   (define config-comment-regexp
     (make-regexp "^([\\t ]*(#.*)?)$"))
@@ -67,13 +68,13 @@ (define config-comment-regexp
               ;; The key is uncommented and set or commented and unset.
               (cons key value)
               ;; The key is set or unset ambigiously.
-              (error (format #f "Invalid configuration, did you mean \"~a\"?"
+              (error (format #f "invalid configuration, did you mean \"~a\"?"
                              (pair->config-string (cons key #f)))
                      config-string)))
-        ;; This is not a valid or ambigious config-string, but mayby a comment.
+        ;; This is not a valid or ambigious config-string, but maybe a
+        ;; comment.
         (if (regexp-exec config-comment-regexp config-string)
-            ;; We keep valid comments.
-            (cons #f config-string)
+            (cons #f config-string)     ;keep valid comments
             (error "Invalid configuration" config-string)))))

 (define (pair->config-string pair)
@@ -94,6 +95,7 @@ (define (defconfig->alist defconfig)
                  (line (read-line)))
         (if (eof-object? line)
             ;; Building the alist is done, now check for duplicates.
+            ;; Note: the filter invocation is used to remove comments.
             (let loop ((keys (map first (filter first alist)))
                        (duplicates '()))
               (if (null? keys)
@@ -102,11 +104,11 @@ (define (defconfig->alist defconfig)
                   (if (null? duplicates)
                       alist
                       (error
-                       (format #f "Duplicate configurations in ~a" defconfig)
+                       (format #f "duplicate configurations in ~a" defconfig)
                        duplicates))
                   ;; Continue the search for duplicates.
                   (loop (cdr keys)
-                        (if (member (first keys) (cdr keys) equal?)
+                        (if (member (first keys) (cdr keys))
                             (cons (first keys) duplicates)
                             duplicates))))
             ;; Build the alist.
@@ -127,13 +129,13 @@ (define (modify-defconfig defconfig configs)
   \"CONFIG_D=m\"
   \"CONFIG_E=\"
   \"# CONFIG_G is not set\"
-  ;; For convinience this abbrevation can be used for not set configurations.
+  ;; For convenience this abbrevation can be used for not set configurations.
   \"CONFIG_F\")

-Instead of a list, CONFGIS can be a string with one configuration per line."
-  (let* (;; 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.
+Instead of a list, CONFIGS can be a string with one configuration per line."
+  (let* (;; Split the configs into a list of single configurations.  Both a
+         ;; string and or a list of strings is supported, each with newlines
+         ;; to separate configurations.
          (config-pairs (map config-string->pair
                             (append-map (cut string-split <>  #\newline)
                                         (if (string? configs)
@@ -141,45 +143,41 @@ (define (modify-defconfig defconfig configs)
                                             configs))))
          ;; Generate a blocklist from all valid keys in config-pairs.
          (blocklist (delete #f (map first config-pairs)))
-         ;; Generate an alist from the defconifg without the keys in blocklist.
+         ;; Generate an alist from the defconfig without the keys in blocklist.
          (filtered-defconfig-pairs (remove (lambda (pair)
                                              (member (first pair) blocklist))
                                            (defconfig->alist defconfig))))
     (with-output-to-file defconfig
       (lambda ()
-        (for-each
-           (lambda (pair)
-             (display (pair->config-string pair))
-             (newline))
-           (append filtered-defconfig-pairs config-pairs))))))
+        (for-each (lambda (pair)
+                    (display (pair->config-string pair))
+                    (newline))
+                  (append filtered-defconfig-pairs config-pairs))))))

 (define (verify-config config defconfig)
   "Verify that the CONFIG file contains all configurations from the DEFCONFIG
-file and return #t in this case. Otherwise throw an error with the mismatching
-keys and their values."
+file.  When the verification fails, raise an error with the mismatching keys
+and their values."
   (let* ((config-pairs (defconfig->alist config))
          (defconfig-pairs (defconfig->alist defconfig))
          (mismatching-pairs
           (remove (lambda (pair)
-                    ;; Remove all configurations, whose values are #f and whose
-                    ;; keys are not in config-pairs, as not in config-pairs
-                    ;; means unset, …
+                    ;; Remove all configurations, whose values are #f and
+                    ;; whose keys are not in config-pairs, as not in
+                    ;; config-pairs means unset, ...
                     (and (not (cdr pair))
                          (not (assoc-ref config-pairs (first pair)))))
-                  ;; … from the defconfig-pairs different to config-pairs.
+                  ;; ... from the defconfig-pairs different to config-pairs.
                   (lset-difference equal?
                                    ;; Remove comments by filtering with first.
                                    (filter first defconfig-pairs)
                                    config-pairs))))
-    (if (null? mismatching-pairs)
-        #t
-        (error (format #f
-                       "Mismatching configurations in ~a and ~a"
-                       config
-                       defconfig)
-               (map (lambda (mismatching-pair)
-                      (let* ((key (first mismatching-pair))
-                             (defconfig-value (cdr mismatching-pair))
-                             (config-value (assoc-ref config-pairs key)))
-                        (cons key (list (list config-value defconfig-value)))))
-                    mismatching-pairs)))))
+    (unless (null? mismatching-pairs)
+      (error (format #f "Mismatching configurations in ~a and ~a"
+                     config defconfig)
+             (map (lambda (mismatching-pair)
+                    (let* ((key (first mismatching-pair))
+                           (defconfig-value (cdr mismatching-pair))
+                           (config-value (assoc-ref config-pairs key)))
+                      (cons key (list (list config-value defconfig-value)))))
+                  mismatching-pairs)))))
--8<---------------cut here---------------end--------------->8---

And streamlined the commit messages as:

--8<---------------cut here---------------start------------->8---
build: kconfig: Add new module to modify defconfig files.

* guix/build/kconfig.scm: New file.
* Makefile.am: Register it.
* gnu/packages/bootloaders.scm (make-u-boot-package)
(make-u-boot-sunxi64-package): Add DEFCONFIGS and CONFIGS arguments.
(u-boot-am335x-boneblack, u-boot-pinebook)
(u-boot-novena,u-boot-rockpro64-rk3399): Simplify packages by using the new
keyword arguments.
--8<---------------cut here---------------end--------------->8---

Explanations don't go in the GNU ChangeLog, they go ideally in comments
in the code or *before* the GNU ChangeLog, if some rationale helps
understanding the change, so you can keep things dry there.

I'll push this change shortly.

-- 
Thanks,
Maxim




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH] Install guix system on Raspberry Pi
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
                                                             ` (4 preceding siblings ...)
  2022-12-01 16:22                                           ` Maxim Cournoyer
@ 2022-12-01 18:01                                           ` Maxim Cournoyer
  2022-12-01 19:33                                           ` bug#48314: " Maxim Cournoyer
  6 siblings, 0 replies; 74+ messages in thread
From: Maxim Cournoyer @ 2022-12-01 18:01 UTC (permalink / raw)
  To: Stefan
  Cc: Vagrant Cascadian, Danny Milosavljevic, Ludovic Courtès,
	phodina, 48314

Hi,

> gnu: linux: New function to modify the configuration of a Linux kernel.
>
> 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.
> (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.

I've renamed it to customize-linux, and streamlined the commit message
like so:

--8<---------------cut here---------------start------------->8---
gnu: linux: Add a 'customize-linux' procedure.

* gnu/packages/linux.scm (linux-srcarch): New procedure.
(customize-linux): Likewise.
(make-defconfig): Procedure to retrieve a defconfig from an URI.

Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Modified-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
--8<---------------cut here---------------end--------------->8---

Otherwise, I've made the following changes (exporting procedures
explicitly from the modules):

--8<---------------cut here---------------start------------->8---
1 file changed, 25 insertions(+), 25 deletions(-)
gnu/packages/linux.scm | 50 +++++++++++++++++++++++++-------------------------

modified   gnu/packages/linux.scm
@@ -190,19 +190,19 @@ (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))
+  #:use-module (ice-9 regex)
+  #:export (customize-linux))
 
-(define-public (linux-srcarch)
+(define (linux-srcarch)
   "Return the linux SRCARCH name, which is set in the toplevel Makefile of
-Linux and denotes the architecture specific directory name below arch/ in its
+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 (platform-linux-architecture
-                      (lookup-platform-by-target-or-system
-                        (or (%current-target-system)
-                            (%current-system))))))
+                     (lookup-platform-by-target-or-system
+                      (or (%current-target-system)
+                          (%current-system))))))
     (match linux-arch
       ("i386"    "x86")
       ("x86_64"  "x86")
@@ -213,7 +213,7 @@ (define-public (linux-srcarch)
 
 (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
+defconfig.  Return the appropriate Make target if applicable, otherwise return
 \"defconfig\"."
   (cond ((string-prefix? "powerpc-" system) "pmac32_defconfig")
         ((string-prefix? "powerpc64-" system) "ppc64_defconfig")
@@ -1271,19 +1271,19 @@ (define-public linux-libre-with-bpf
 ;;; 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.
+(define* (customize-linux #:key name
+                          (linux linux-libre)
+                          source
+                          defconfig
+                          (configs "")
+                          extra-version)
+  "Make a customized Linux package NAME derived from the 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 an origin, as a file like object
+A DEFCONFIG file to be used can be given as an origin, 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.
@@ -1295,11 +1295,11 @@ (define*-public (modify-linux #:key name
 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:
+Here is an example:
 
   '(;; This string defines the version tail in 'uname -r'.
     \"CONFIG_LOCALVERSION=\\\"-handcrafted\\\"
-    ;; This '# CONFIG_… is not set' syntax has to match exactly!
+    ;; 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:
@@ -1339,13 +1339,13 @@ (define*-public (modify-linux #:key name
                   #$(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)))
+                          ;; 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)
--8<---------------cut here---------------end--------------->8---

I'll push it shortly.

-- 
Thanks,
Maxim




^ permalink raw reply	[flat|nested] 74+ messages in thread

* bug#48314: [PATCH] Install guix system on Raspberry Pi
  2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
                                                             ` (5 preceding siblings ...)
  2022-12-01 18:01                                           ` Maxim Cournoyer
@ 2022-12-01 19:33                                           ` Maxim Cournoyer
  2022-12-03  5:53                                             ` [bug#48314] " Vagrant Cascadian
  6 siblings, 1 reply; 74+ messages in thread
From: Maxim Cournoyer @ 2022-12-01 19:33 UTC (permalink / raw)
  To: Stefan
  Cc: Vagrant Cascadian, 48314-done, Ludovic Courtès, phodina,
	Danny Milosavljevic

Hi,

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

> gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.
>
> From: Stefan <stefan-guix@vodafonemail.de>
>
> * 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

Neat!

I've registered the new files in Makefile.am (and adjusted the commit
message), fixed their indentation and pushed!

This whole series is now in Guix.  I'll try to test it with actual
devices in the coming days and see if anything needs adjusting.

Thanks to you and to everyone else who contributed to the review.

Maxim




^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH] Install guix system on Raspberry Pi
  2022-12-01 19:33                                           ` bug#48314: " Maxim Cournoyer
@ 2022-12-03  5:53                                             ` Vagrant Cascadian
  2022-12-04  6:28                                               ` Maxim Cournoyer
  0 siblings, 1 reply; 74+ messages in thread
From: Vagrant Cascadian @ 2022-12-03  5:53 UTC (permalink / raw)
  To: Maxim Cournoyer, Stefan
  Cc: Danny Milosavljevic, Ludovic Courtès, phodina, 48314

[-- Attachment #1: Type: text/plain, Size: 1467 bytes --]

On 2022-12-01, Maxim Cournoyer wrote:
> Stefan <stefan-guix@vodafonemail.de> writes:
>
>> gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.
>>
>> From: Stefan <stefan-guix@vodafonemail.de>
>>
>> * 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

This does cause a test suite failure with tests/guix-system.sh:

+ guix system -n disk-image gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
accepted connection from pid 31196, user vagrant
guix system: warning: 'disk-image' is deprecated: use 'image' instead
guix system: error: canonicalize-path: No such file or directory: "/home/vagrant/.ssh/id_ecdsa.pub"
+ rm -f t-guix-system-30549 t-guix-system-error-30549 /tmp/t-guix-system-30549/config.scm /tmp/t-guix-system-30549/my-torrc
+ rmdir /tmp/t-guix-system-30549
FAIL tests/guix-system.sh (exit status: 1)

gnu/system/examples/raspberry-pi-64-nfs-root.tmpl

  (define %my-public-key
    (local-file (string-append (getenv "HOME") "/.ssh/id_ecdsa.pub")))

Seems like using local-file for should be removed or at least commented
out in the example. Or include the full text of an example key in the
.tmpl file instead of using local-file...

live well,
  vagrant

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [bug#48314] [PATCH] Install guix system on Raspberry Pi
  2022-12-03  5:53                                             ` [bug#48314] " Vagrant Cascadian
@ 2022-12-04  6:28                                               ` Maxim Cournoyer
  0 siblings, 0 replies; 74+ messages in thread
From: Maxim Cournoyer @ 2022-12-04  6:28 UTC (permalink / raw)
  To: Vagrant Cascadian
  Cc: Stefan, Danny Milosavljevic, Ludovic Courtès, phodina, 48314

Hello,

Vagrant Cascadian <vagrant@debian.org> writes:

> On 2022-12-01, Maxim Cournoyer wrote:
>> Stefan <stefan-guix@vodafonemail.de> writes:
>>
>>> gnu: raspberry-pi: Add a bootloader-chain for the Raspberry Pi and os examples.
>>>
>>> From: Stefan <stefan-guix@vodafonemail.de>
>>>
>>> * 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
>
> This does cause a test suite failure with tests/guix-system.sh:
>
> + guix system -n disk-image gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
> accepted connection from pid 31196, user vagrant
> guix system: warning: 'disk-image' is deprecated: use 'image' instead
> guix system: error: canonicalize-path: No such file or directory: "/home/vagrant/.ssh/id_ecdsa.pub"
> + rm -f t-guix-system-30549 t-guix-system-error-30549 /tmp/t-guix-system-30549/config.scm /tmp/t-guix-system-30549/my-torrc
> + rmdir /tmp/t-guix-system-30549
> FAIL tests/guix-system.sh (exit status: 1)
>
> gnu/system/examples/raspberry-pi-64-nfs-root.tmpl
>
>   (define %my-public-key
>     (local-file (string-append (getenv "HOME") "/.ssh/id_ecdsa.pub")))
>

Thanks for the heads-up!  I've removed key usage from the templates in
08dc9f2ca2e96476aa51c906c8ba01ca5d033568.  I also had to mark the
templates to be built for aarch64-linux in
93309efdce72ac5028944d5c1f7b081a7f62b84a.

-- 
Thanks,
Maxim




^ permalink raw reply	[flat|nested] 74+ messages in thread

end of thread, other threads:[~2022-12-04  6:29 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-09 15:32 [bug#48314] Patches to install guix system on Raspberry Pi Stefan
2021-05-16 12:46 ` Stefan
2021-06-19 18:11   ` Danny Milosavljevic
2021-06-19 18:13   ` Danny Milosavljevic
2021-06-19 19:10     ` Stefan
2021-06-19 19:04   ` Danny Milosavljevic
2021-06-19 19:18     ` Stefan
2021-06-19 19:10   ` Danny Milosavljevic
2021-06-19 20:21     ` Stefan
2021-07-28 18:58       ` Stefan
2021-10-31 22:07         ` Stefan
2021-11-13 18:05           ` Vagrant Cascadian
2021-11-13 18:51             ` Vagrant Cascadian
2022-07-17 16:47             ` Stefan via Guix-patches via
2021-11-13 18:23           ` Vagrant Cascadian
2022-07-17 16:47             ` Stefan via Guix-patches via
2021-11-13 20:21           ` Vagrant Cascadian
2022-07-17 16:47             ` Stefan via Guix-patches via
2022-07-17 17:21               ` Vagrant Cascadian
2022-07-17 18:04                 ` Stefan via Guix-patches via
2021-11-17 14:00 ` [bug#48314] Install " phodina via Guix-patches via
2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
2022-04-14  8:17   ` phodina via Guix-patches via
2022-04-14  8:32   ` Maxime Devos
2022-04-14  9:25     ` [bug#48314] [PATCH v4] " phodina via Guix-patches via
2022-04-14 11:00       ` Maxime Devos
2022-04-14 12:23         ` [bug#48314] [PATCH v5] " phodina via Guix-patches via
2022-04-14 13:03           ` phodina via Guix-patches via
2022-04-14 13:57             ` Maxime Devos
2022-04-14 14:00           ` Maxime Devos
2022-04-14 14:06   ` [bug#48314] [PATCH v3] " Maxime Devos
2022-04-14 15:53     ` phodina via Guix-patches via
2022-04-14 17:33       ` Maxime Devos
2022-04-15 17:17       ` Ludovic Courtès
2022-04-16  8:53         ` phodina via Guix-patches via
2022-04-18 21:00           ` Ludovic Courtès
2022-04-21 10:52             ` phodina via Guix-patches via
2022-04-21 19:32               ` Stefan
2022-04-14 15:56   ` Vagrant Cascadian
2022-04-28  2:57     ` Vagrant Cascadian
2022-04-28  6:05       ` Stefan
2022-04-28 15:25         ` Vagrant Cascadian
2022-07-02  6:40           ` phodina via Guix-patches via
2022-07-17 16:48             ` Stefan via Guix-patches via
2022-07-17 16:48             ` Stefan via Guix-patches via
2022-07-18 19:23               ` phodina via Guix-patches via
2022-07-19  6:55                 ` Stefan via Guix-patches via
2022-07-19  7:35                   ` phodina via Guix-patches via
2022-07-20  6:13                     ` Stefan via Guix-patches via
2022-07-20  7:16                       ` phodina via Guix-patches via
2022-07-20 19:42                         ` Stefan via Guix-patches via
2022-08-12 14:27                           ` phodina via Guix-patches via
2022-08-13 10:48                             ` Stefan via Guix-patches via
2022-08-14  9:59                               ` phodina via Guix-patches via
2022-08-14 11:35                                 ` Stefan via Guix-patches via
2022-09-01 23:55                                   ` Stefan via Guix-patches via
2022-09-02  5:49                                     ` phodina via Guix-patches via
2022-09-04 18:41                                       ` Stefan via Guix-patches via
2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
2022-10-05 13:02                                           ` Ludovic Courtès
2022-10-08 16:22                                           ` Vagrant Cascadian
2022-10-09 13:41                                             ` Stefan via Guix-patches via
2022-10-30 12:39                                               ` phodina via Guix-patches via
2022-10-30 17:08                                                 ` Stefan via Guix-patches via
2022-10-30 17:31                                                   ` Stefan via Guix-patches via
2022-12-01 14:25                                           ` [bug#48314] [PATCH] " Maxim Cournoyer
2022-12-01 15:32                                           ` Maxim Cournoyer
2022-12-01 16:22                                           ` Maxim Cournoyer
2022-12-01 18:01                                           ` Maxim Cournoyer
2022-12-01 19:33                                           ` bug#48314: " Maxim Cournoyer
2022-12-03  5:53                                             ` [bug#48314] " Vagrant Cascadian
2022-12-04  6:28                                               ` Maxim Cournoyer
2022-10-30 17:32 ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
2022-10-30 17:33 ` Stefan via Guix-patches via

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).