;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
;;; Copyright © 2020, 2021 Brice Waegeneire <brice@waegenei.re>
;;; Copyright © 2020 Florian Pelz <pelzflorian@pelzflorian.de>
-;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
+;;; Copyright © 2020, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <jannek@gnu.org>
-;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2020, 2022 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
;;; Copyright © 2021 raid5atemyhomework <raid5atemyhomework@protonmail.com>
;;;
(define-module (gnu system)
#:use-module (guix inferior)
#:use-module (guix store)
+ #:use-module (guix memoization)
#:use-module (guix monads)
#:use-module (guix gexp)
#:use-module (guix records)
#:use-module ((guix utils) #:select (substitute-keyword-arguments))
#:use-module (guix i18n)
#:use-module (guix diagnostics)
+ #:use-module (guix ui)
#:use-module (gnu packages admin)
#:use-module (gnu packages base)
#:use-module (gnu packages bash)
#:use-module (gnu system uuid)
#:use-module (gnu system file-systems)
#:use-module (gnu system mapped-devices)
+ #:use-module (ice-9 format)
#:use-module (ice-9 match)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-35)
+ #:use-module (srfi srfi-71)
#:use-module (rnrs bytevectors)
#:export (operating-system
operating-system?
boot-parameters-kernel-arguments
boot-parameters-initrd
boot-parameters-multiboot-modules
+ boot-parameters-version
+ %boot-parameters-version
read-boot-parameters
read-boot-parameters-file
boot-parameters->menu-entry
;;;
;;; Code:
-(define (bootable-kernel-arguments system root-device)
- "Return a list of kernel arguments (gexps) to boot SYSTEM from ROOT-DEVICE."
- (list (string-append "--root="
+(define* (bootable-kernel-arguments system root-device version)
+ "Return a list of kernel arguments (gexps) to boot SYSTEM from ROOT-DEVICE.
+VERSION is the target version of the boot-parameters record."
+ ;; If the version is newer than 0, we use the new style initrd parameter
+ ;; names, otherwise we use the legacy ones. This is to maintain backward
+ ;; compatibility when producing bootloader configurations for older
+ ;; generations.
+ (define version>0? (> version 0))
+ (list (string-append (if version>0? "root=" "--root=")
;; Note: Always use the DCE format because that's what
- ;; (gnu build linux-boot) expects for the '--root'
+ ;; (gnu build linux-boot) expects for the 'root'
;; kernel command-line option.
(file-system-device->string root-device
#:uuid-type 'dce))
- #~(string-append "--system=" #$system)
- #~(string-append "--load=" #$system "/boot")))
+ #~(string-append (if #$version>0? "gnu.system=" "--system=") #$system)
+ #~(string-append (if #$version>0? "gnu.load=" "--load=")
+ #$system "/boot")))
;; System-wide configuration.
;; TODO: Add per-field docstrings/stexi.
(packages operating-system-packages ; list of (PACKAGE OUTPUT...)
(default %base-packages)) ; or just PACKAGE
- (timezone operating-system-timezone) ; string
+ (timezone operating-system-timezone
+ (default "Etc/UTC")) ; string
(locale operating-system-locale ; string
(default "en_US.utf8"))
(locale-definitions operating-system-locale-definitions ; list of <locale-definition>
source-properties->location))
(innate)))
-(define (operating-system-kernel-arguments os root-device)
- "Return all the kernel arguments, including the ones not specified
-directly by the user."
- (append (bootable-kernel-arguments os root-device)
+(define* (operating-system-kernel-arguments
+ os root-device #:key (version %boot-parameters-version))
+ "Return all the kernel arguments, including the ones not specified directly
+by the user. VERSION should match that of the target <boot-parameters> record
+object that will contain the kernel parameters."
+ (append (bootable-kernel-arguments os root-device version)
(operating-system-user-kernel-arguments os)))
\f
;;; Boot parameters
;;;
+;;; Version 1 was introduced early 2022 to mark the departure from long option
+;;; names such as '--load' to the more conventional initrd option names like
+;;; 'gnu.load'.
+;;;
+;;; When bumping the boot-parameters version, increment it by one (1).
+(define %boot-parameters-version 1)
+
(define-record-type* <boot-parameters>
boot-parameters make-boot-parameters boot-parameters?
(label boot-parameters-label)
(kernel boot-parameters-kernel)
(kernel-arguments boot-parameters-kernel-arguments)
(initrd boot-parameters-initrd)
- (multiboot-modules boot-parameters-multiboot-modules))
+ (multiboot-modules boot-parameters-multiboot-modules)
+ (version boot-parameters-version ;positive integer
+ (default %boot-parameters-version)))
(define (ensure-not-/dev device)
"If DEVICE starts with a slash, return #f. This is meant to filter out
(define (read-boot-parameters port)
"Read boot parameters from PORT and return the corresponding
-<boot-parameters> object or #f if the format is unrecognized."
+<boot-parameters> object. Raise an error if the format is unrecognized."
(define device-sexp->device
(match-lambda
(('uuid (? symbol? type) (? bytevector? bv))
(warning (G_ "unrecognized uuid ~a at '~a'~%") x (port-filename port))
#f)))
+ ;; New versions are not backward-compatible, so only accept past and current
+ ;; versions, not future ones.
+ (define (version? n)
+ (member n (iota (1+ %boot-parameters-version))))
+
(match (read port)
- (('boot-parameters ('version 0)
+ (('boot-parameters ('version (? version? version))
('label label) ('root-device root)
('kernel kernel)
rest ...)
(boot-parameters
+ (version version)
(label label)
(root-device (device-sexp->device root))
(_ ;the old format
"/")))))
(x ;unsupported format
- (warning (G_ "unrecognized boot parameters at '~a'~%")
- (port-filename port))
- #f)))
+ (raise
+ (make-compound-condition
+ (formatted-message
+ (G_ "unrecognized boot parameters at '~a'~%")
+ (port-filename port))
+ (condition
+ (&fix-hint (hint (format #f (G_ "This probably means that this version
+of Guix is older than the one that created @file{~a}. To address this, you
+need to update Guix:
+
+@example
+guix pull
+@end example")
+ (port-filename port))))))))))
(define (read-boot-parameters-file system)
"Read boot parameters from SYSTEM's (system or generation) \"parameters\"
The object has its kernel-arguments extended in order to make it bootable."
(let* ((file (string-append system "/parameters"))
(params (call-with-input-file file read-boot-parameters))
- (root (boot-parameters-root-device params)))
+ (root (boot-parameters-root-device params))
+ (version (boot-parameters-version params)))
(boot-parameters
(inherit params)
- (kernel-arguments (append (bootable-kernel-arguments system root)
+ (kernel-arguments (append (bootable-kernel-arguments system root version)
(boot-parameters-kernel-arguments params))))))
(define (boot-parameters->menu-entry conf)
+ "Return a <menu-entry> instance given CONF, a <boot-parameters> instance."
(let* ((kernel (boot-parameters-kernel conf))
(multiboot-modules (boot-parameters-multiboot-modules conf))
(multiboot? (pair? multiboot-modules)))
(service file-system-service-type
(map add-dependencies file-systems)))
+(define (boot-file-system-service os)
+ "Return a service which adds, to the system profile, packages providing the
+utilites for the file systems marked as 'needed-for-boot' in OS."
+ (let ((file-systems (filter file-system-needed-for-boot?
+ (operating-system-file-systems os))))
+ (simple-service 'boot-file-system-utilities profile-service-type
+ (file-system-utilities file-systems))))
+
(define (mapped-device-users device file-systems)
"Return the subset of FILE-SYSTEMS that use DEVICE."
(let ((targets (map (cut string-append "/dev/mapper/" <>)
(any file-system-needed-for-boot? users)))
devices)))
-(define (operating-system-bootloader-crypto-devices os)
- "Return the subset of mapped devices that the bootloader must open.
-Only devices specified by uuid are supported."
- (define (valid-crypto-device? dev)
- (or (uuid? dev)
- (begin
- (warning (G_ "\
-mapped-device '~a' may not be mounted by the bootloader.~%")
- dev)
- #f)))
- (filter-map (match-lambda
- ((and (= mapped-device-type type)
- (= mapped-device-source source))
- (and (eq? luks-device-mapping type)
- (valid-crypto-device? source)
- source))
- (_ #f))
- ;; XXX: Ordering is important, we trust the returned one.
- (operating-system-boot-mapped-devices os)))
+(define operating-system-bootloader-crypto-devices
+ (mlambdaq (os) ;to avoid duplicated output
+ "Return the sources of the LUKS mapped devices specified by UUID."
+ ;; XXX: Device ordering is important, we trust the returned one.
+ (let* ((luks-devices (filter (lambda (m)
+ (eq? luks-device-mapping
+ (mapped-device-type m)))
+ (operating-system-boot-mapped-devices os)))
+ (uuid-crypto-devices non-uuid-crypto-devices
+ (partition (compose uuid? mapped-device-source)
+ luks-devices)))
+ (when (not (null? non-uuid-crypto-devices))
+ (for-each (lambda (dev)
+ (warning
+ (source-properties->location (mapped-device-location dev))
+ (G_ "mapped device '~a' may be ignored by bootloader~%")
+ (mapped-device-source dev)))
+ non-uuid-crypto-devices)
+ (display-hint "Specify mapped device sources via their LUKS UUID."))
+ (map mapped-device-source uuid-crypto-devices))))
(define (device-mapping-services os)
"Return the list of device-mapping services for OS as a list."
((string-prefix? "arm" target) "zImage")
((string-prefix? "mips" target) "vmlinuz")
((string-prefix? "aarch64" target) "Image")
+ ((string-prefix? "riscv64" target) "Image")
(else "bzImage")))
(define (operating-system-kernel-file os)
(define known-fs
(map file-system-mount-point (operating-system-file-systems os)))
- (let* ((mappings (device-mapping-services os))
- (root-fs (root-file-system-service))
- (other-fs (non-boot-file-system-service os))
- (swaps (swap-services os))
- (procs (service user-processes-service-type))
- (host-name (host-name-service (operating-system-host-name os)))
- (entries (operating-system-directory-base-entries os)))
+ (let* ((mappings (device-mapping-services os))
+ (root-fs (root-file-system-service))
+ (boot-fs (boot-file-system-service os))
+ (non-boot-fs (non-boot-file-system-service os))
+ (swaps (swap-services os))
+ (procs (service user-processes-service-type))
+ (host-name (host-name-service (operating-system-host-name os)))
+ (entries (operating-system-directory-base-entries os)))
(cons* (service system-service-type entries)
(service linux-builder-service-type
(linux-builder-configuration
(operating-system-setuid-programs os))
(service profile-service-type
(operating-system-packages os))
- other-fs
+ boot-fs non-boot-fs
(append mappings swaps
;; Add the firmware service.
%boot-service
%hurd-startup-service
%activation-service
- %shepherd-root-service
+ (service shepherd-root-service-type
+ (shepherd-configuration
+ (shepherd shepherd-0.8))) ;no Fibers
+
(service user-processes-service-type)
(account-service (append (operating-system-accounts os)
(operating-system-groups os))
(define %base-packages-utils
;; Default set of utilities packages.
(cons* procps psmisc which
- (@ (gnu packages admin) shadow) ;for 'passwd'
+ (@ (gnu packages admin) shadow-with-man-pages) ;for 'passwd'
guile-3.0-latest
iw wireless-tools))
(define %base-packages-disk-utilities
- ;; A well-rounded set of packages for interacting with disks, partitions
- ;; and filesystems.
+ ;; A well-rounded set of packages for interacting with disks,
+ ;; partitions and filesystems, included with the Guix installation
+ ;; image.
(list parted gptfdisk ddrescue
;; We used to provide fdisk from GNU fdisk, but as of version 2.0.0a
;; it pulls Guile 1.8, which takes unreasonable space; furthermore
(define %base-packages
;; Default set of packages globally visible. It should include anything
;; required for basic administrator tasks.
- (append (list e2fsprogs)
- %base-packages-artwork
+ (append %base-packages-artwork
%base-packages-interactive
%base-packages-linux
%base-packages-networking
(file-append sudo "/bin/sudo")
(file-append sudo "/bin/sudoedit")
(file-append fuse "/bin/fusermount")
+ (file-append fuse-3 "/bin/fusermount3")
;; To allow mounts with the "user" option, "mount" and "umount" must
;; be setuid-root.
(define* (operating-system-boot-parameters os root-device
#:key system-kernel-arguments?)
"Return a monadic <boot-parameters> record that describes the boot
-parameters of OS. When SYSTEM-KERNEL-ARGUMENTS? is true, add kernel arguments
-such as '--root' and '--load' to <boot-parameters>."
+parameters of OS. When SYSTEM-KERNEL-ARGUMENTS? is true, add the kernel
+arguments 'root', 'gnu.load' and 'gnu.system' to <boot-parameters>. The
+SYSTEM-KERNEL-ARGUMENTS? should only be used in necessity, as the 'gnu.load'
+and 'gnu.system' values are self-referential (they refer to the system), thus
+susceptible to introduce a cyclic dependency."
(let* ((initrd (and (not (operating-system-hurd os))
(operating-system-initrd-file os)))
(store (operating-system-store-file-system os))
(_
device)))
-(define* (operating-system-boot-parameters-file os
- #:key system-kernel-arguments?)
- "Return a file that describes the boot parameters of OS. The primary use of
-this file is the reconstruction of GRUB menu entries for old configurations.
-
-When SYSTEM-KERNEL-ARGUMENTS? is true, add kernel arguments such as '--root'
-and '--load' to the returned file (since the returned file is then usually
-stored into the content-addressed \"system\" directory, it's usually not a
-good idea to give it because the content hash would change by the content hash
-being stored into the \"parameters\" file)."
+(define* (operating-system-boot-parameters-file os)
+ "Return a file that describes the boot parameters of OS. The primary use
+of this file is the reconstruction of GRUB menu entries for old
+configurations."
(let* ((root (operating-system-root-file-system os))
(device (file-system-device root))
- (params (operating-system-boot-parameters
- os device
- #:system-kernel-arguments?
- system-kernel-arguments?)))
+ (params (operating-system-boot-parameters os device)))
(scheme-file "parameters"
#~(boot-parameters
- (version 0)
+ (version #$(boot-parameters-version params))
(label #$(boot-parameters-label params))
(root-device
#$(device->sexp
(lambda (store)
;; XXX: This is not super elegant but we can't pass SYSTEM and TARGET to
;; 'operating-system-derivation'.
- (run-with-store store (operating-system-derivation os)
- #:system system
- #:target target)))))
+ (parameterize ((%current-system system)
+ (%current-target-system target))
+ (run-with-store store
+ (mbegin %store-monad
+ (set-guile-for-build (default-guile))
+ (operating-system-derivation os))
+ #:system system
+ #:target target))))))
;;; system.scm ends here