1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2016 Mark H Weaver <mhw@netris.org>
4 ;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
5 ;;; Copyright © 2017, 2019 Mathieu Othacehe <m.othacehe@gmail.com>
6 ;;; Copyright © 2019 Tobias Geerinckx-Rice <me@tobias.gr>
8 ;;; This file is part of GNU Guix.
10 ;;; GNU Guix is free software; you can redistribute it and/or modify it
11 ;;; under the terms of the GNU General Public License as published by
12 ;;; the Free Software Foundation; either version 3 of the License, or (at
13 ;;; your option) any later version.
15 ;;; GNU Guix is distributed in the hope that it will be useful, but
16 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;;; GNU General Public License for more details.
20 ;;; You should have received a copy of the GNU General Public License
21 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
23 (define-module (gnu system linux-initrd)
24 #:use-module (guix gexp)
25 #:use-module (guix utils)
26 #:use-module ((guix store)
27 #:select (%store-prefix))
28 #:use-module ((guix derivations)
29 #:select (derivation->output-path))
30 #:use-module (guix modules)
31 #:use-module (gnu packages compression)
32 #:use-module (gnu packages disk)
33 #:use-module (gnu packages linux)
34 #:use-module (gnu packages file-systems)
35 #:use-module (gnu packages guile)
36 #:use-module ((gnu packages xorg)
37 #:select (console-setup xkeyboard-config))
38 #:use-module ((gnu packages make-bootstrap)
39 #:select (%guile-3.0-static-stripped))
40 #:use-module (gnu system file-systems)
41 #:use-module (gnu system mapped-devices)
42 #:use-module (gnu system keyboard)
43 #:use-module (ice-9 match)
44 #:use-module (ice-9 regex)
45 #:use-module (ice-9 vlist)
46 #:use-module (srfi srfi-1)
47 #:use-module (srfi srfi-26)
48 #:export (expression->initrd
57 ;;; Tools to build initial RAM disks (initrd's) for Linux-Libre, and in
58 ;;; particular initrd's that run Guile.
63 (define* (expression->initrd exp
65 (guile %guile-3.0-static-stripped)
68 (system (%current-system)))
69 "Return as a file-like object a Linux initrd (a gzipped cpio archive)
70 containing GUILE and that evaluates EXP, a G-expression, upon booting. All
71 the derivations referenced by EXP are automatically copied to the initrd."
73 ;; General Linux overview in `Documentation/early-userspace/README' and
74 ;; `Documentation/filesystems/ramfs-rootfs-initramfs.txt'.
77 (program-file "init" exp #:guile guile))
80 (with-imported-modules (source-module-closure
81 '((gnu build linux-initrd)))
83 (use-modules (gnu build linux-initrd))
87 ;; The guile used in the initrd must be present in the store, so
88 ;; that module loading works once the root is switched.
90 ;; To ensure that is the case, add an explicit reference to the
91 ;; guile package used in the initrd to the output.
93 ;; This fixes guix-patches bug #28399, "Fix mysql activation, and
95 (call-with-output-file (string-append #$ output "/references")
97 (simple-format port "~A\n" #$guile)))
99 (build-initrd (string-append #$output "/initrd.cpio.gz")
102 ;; Copy everything INIT refers to into the initrd.
103 #:references-graphs '("closure")
104 #:gzip (string-append #+gzip "/bin/gzip")))))
106 (file-append (computed-file name builder
108 `(#:references-graphs (("closure" ,init))))
111 (define (flat-linux-module-directory linux modules)
112 "Return a flat directory containing the Linux kernel modules listed in
113 MODULES and taken from LINUX."
115 (with-imported-modules (source-module-closure
116 '((gnu build linux-modules)))
118 (use-modules (gnu build linux-modules)
123 (string-append #$linux "/lib/modules"))
126 (let* ((lookup (cut find-module-file module-dir <>))
127 (modules (map lookup '#$modules)))
129 (recursive-module-dependencies modules
130 #:lookup-module lookup))))
133 (for-each (lambda (module)
134 (format #t "copying '~a'...~%" module)
136 (string-append #$output "/"
138 (delete-duplicates modules))
140 ;; Hyphen or underscore? This database tells us.
141 (write-module-name-database #$output))))
143 (computed-file "linux-modules" build-exp))
145 (define* (raw-initrd file-systems
151 (helper-packages '())
155 "Return as a file-like object a raw initrd, with kernel
156 modules taken from LINUX. FILE-SYSTEMS is a list of file-systems to be
157 mounted by the initrd, possibly in addition to the root file system specified
158 on the kernel command line via '--root'. LINUX-MODULES is a list of kernel
159 modules to be loaded at boot time. MAPPED-DEVICES is a list of device
160 mappings to realize before FILE-SYSTEMS are mounted.
161 HELPER-PACKAGES is a list of packages to be copied in the initrd. It may include
162 e2fsck/static or other packages needed by the initrd to check root partition.
164 When true, KEYBOARD-LAYOUT is a <keyboard-layout> record denoting the desired
165 console keyboard layout. This is done before MAPPED-DEVICES are set up and
166 before FILE-SYSTEMS are mounted such that, should the user need to enter a
167 passphrase or use the REPL, this happens using the intended keyboard layout.
169 When QEMU-NETWORKING? is true, set up networking with the standard QEMU
172 When VOLATILE-ROOT? is true, the root file system is writable but any changes
175 ON-ERROR is passed to 'call-with-error-handling'; it determines what happens
177 (define device-mapping-commands
178 ;; List of gexps to open the mapped devices.
180 (let* ((source (mapped-device-source md))
181 (target (mapped-device-target md))
182 (type (mapped-device-type md))
183 (open (mapped-device-kind-open type)))
184 (open source target)))
188 (flat-linux-module-directory linux linux-modules))
191 (with-imported-modules (source-module-closure
192 '((gnu build linux-boot)
194 (guix build bournish)
195 (gnu system file-systems)
196 (gnu build file-systems)))
198 (use-modules (gnu build linux-boot)
199 (gnu system file-systems)
200 ((guix build utils) #:hide (delete))
201 (guix build bournish) ;add the 'bournish' meta-command
204 ;; FIXME: The following modules are for
205 ;; LUKS-DEVICE-MAPPING. We should instead propagate
206 ;; this info via gexps.
207 ((gnu build file-systems)
208 #:select (find-partition-by-luks-uuid))
211 (with-output-to-port (%make-void-port "w")
213 (set-path-environment-variable "PATH" '("bin" "sbin")
214 '#$helper-packages)))
216 (parameterize ((current-warning-port (%make-void-port "w")))
217 (boot-system #:mounts
218 (map spec->file-system
219 '#$(map file-system->spec file-systems))
220 #:pre-mount (lambda ()
221 (and #$@device-mapping-commands))
222 #:linux-modules '#$linux-modules
223 #:linux-module-directory '#$kodir
224 #:keymap-file #+(and=> keyboard-layout
225 keyboard-layout->console-keymap)
226 #:qemu-guest-networking? #$qemu-networking?
227 #:volatile-root? '#$volatile-root?
228 #:on-error '#$on-error))))
229 #:name "raw-initrd"))
231 (define* (file-system-packages file-systems #:key (volatile-root? #f))
232 "Return the list of statically-linked, stripped packages to check
234 `(,@(if (find (lambda (fs)
235 (string-prefix? "ext" (file-system-type fs)))
239 ,@(if (find (lambda (fs)
240 (string-suffix? "fat" (file-system-type fs)))
242 (list fatfsck/static)
244 ,@(if (find (file-system-type-predicate "btrfs") file-systems)
245 (list btrfs-progs/static)
247 ,@(if (find (file-system-type-predicate "jfs") file-systems)
248 (list jfs_fsck/static)
250 ,@(if (find (file-system-type-predicate "f2fs") file-systems)
251 (list f2fs-fsck/static)
254 (define-syntax vhash ;TODO: factorize
256 "Build a vhash with the given key/value mappings."
259 ((_ (key others ... => value) rest ...)
260 (vhash-cons key value
261 (vhash (others ... => value) rest ...)))
262 ((_ (=> value) rest ...)
265 (define-syntax lookup-procedure
267 "Return a procedure that lookups keys in the given dictionary."
268 ((_ mapping ... (else default))
269 (let ((table (vhash mapping ...)))
271 (match (vhash-assoc key table)
273 ((key . value) value)))))))
275 (define file-system-type-modules
276 ;; Given a file system type, return the list of modules it needs.
277 (lookup-procedure ("cifs" => '("md4" "ecb" "cifs"))
278 ("9p" => '("9p" "9pnet_virtio"))
279 ("btrfs" => '("btrfs"))
280 ("iso9660" => '("isofs"))
282 ("f2fs" => '("f2fs" "crc32_generic"))
285 (define (file-system-modules file-systems)
286 "Return the list of Linux modules needed to mount FILE-SYSTEMS."
287 (append-map (compose file-system-type-modules file-system-type)
290 (define* (default-initrd-modules
292 (system (or (%current-target-system)
294 "Return the list of modules included in the initrd by default."
295 (define virtio-modules
296 ;; Modules for Linux para-virtualized devices, for use in QEMU guests.
297 '("virtio_pci" "virtio_balloon" "virtio_blk" "virtio_net"
298 "virtio_console" "virtio-rng"))
300 `("ahci" ;for SATA controllers
301 "usb-storage" "uas" ;for the installation image etc.
302 "usbhid" "hid-generic" "hid-apple" ;keyboards during early boot
303 "dm-crypt" "xts" "serpent_generic" "wp512" ;for encrypted root partitions
304 "nls_iso8859-1" ;for `mkfs.fat`, et.al
305 ,@(if (string-match "^(x86_64|i[3-6]86)-" system)
306 '("pata_acpi" "pata_atiixp" ;for ATA controllers
307 "isci") ;for SAS controllers like Intel C602
312 (define-syntax %base-initrd-modules
313 ;; This more closely matches our naming convention.
314 (identifier-syntax (default-initrd-modules)))
316 (define* (base-initrd file-systems
324 (extra-modules '()) ;deprecated
326 "Return as a file-like object a generic initrd, with kernel
327 modules taken from LINUX. FILE-SYSTEMS is a list of file-systems to be
328 mounted by the initrd, possibly in addition to the root file system specified
329 on the kernel command line via '--root'. MAPPED-DEVICES is a list of device
330 mappings to realize before FILE-SYSTEMS are mounted.
332 When true, KEYBOARD-LAYOUT is a <keyboard-layout> record denoting the desired
333 console keyboard layout. This is done before MAPPED-DEVICES are set up and
334 before FILE-SYSTEMS are mounted such that, should the user need to enter a
335 passphrase or use the REPL, this happens using the intended keyboard layout.
337 QEMU-NETWORKING? and VOLATILE-ROOT? behaves as in raw-initrd.
339 The initrd is automatically populated with all the kernel modules necessary
340 for FILE-SYSTEMS and for the given options. Additional kernel
341 modules can be listed in LINUX-MODULES. They will be added to the initrd, and
342 loaded at boot time in the order in which they appear."
343 (define linux-modules*
344 ;; Modules added to the initrd and loaded from the initrd.
346 ,@(file-system-modules file-systems)
352 (define helper-packages
353 (append (file-system-packages file-systems
354 #:volatile-root? volatile-root?)
356 (list loadkeys-static)
359 (raw-initrd file-systems
361 #:linux-modules linux-modules*
362 #:mapped-devices mapped-devices
363 #:helper-packages helper-packages
364 #:keyboard-layout keyboard-layout
365 #:qemu-networking? qemu-networking?
366 #:volatile-root? volatile-root?
367 #:on-error on-error))
369 ;;; linux-initrd.scm ends here