Merge branch 'master' into core-updates
[jackhill/guix/guix.git] / gnu / system / linux-initrd.scm
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 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 Mathieu Othacehe <m.othacehe@gmail.com>
6 ;;;
7 ;;; This file is part of GNU Guix.
8 ;;;
9 ;;; GNU Guix is free software; you can redistribute it and/or modify it
10 ;;; under the terms of the GNU General Public License as published by
11 ;;; the Free Software Foundation; either version 3 of the License, or (at
12 ;;; your option) any later version.
13 ;;;
14 ;;; GNU Guix is distributed in the hope that it will be useful, but
15 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;;; GNU General Public License for more details.
18 ;;;
19 ;;; You should have received a copy of the GNU General Public License
20 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21
22 (define-module (gnu system linux-initrd)
23 #:use-module (guix gexp)
24 #:use-module (guix utils)
25 #:use-module ((guix store)
26 #:select (%store-prefix))
27 #:use-module ((guix derivations)
28 #:select (derivation->output-path))
29 #:use-module (guix modules)
30 #:use-module (gnu packages compression)
31 #:use-module (gnu packages disk)
32 #:use-module (gnu packages linux)
33 #:use-module (gnu packages guile)
34 #:use-module ((gnu packages make-bootstrap)
35 #:select (%guile-static-stripped))
36 #:use-module (gnu system file-systems)
37 #:use-module (gnu system mapped-devices)
38 #:use-module (ice-9 match)
39 #:use-module (ice-9 regex)
40 #:use-module (ice-9 vlist)
41 #:use-module (srfi srfi-1)
42 #:use-module (srfi srfi-26)
43 #:export (expression->initrd
44 %base-initrd-modules
45 raw-initrd
46 file-system-packages
47 base-initrd))
48
49 \f
50 ;;; Commentary:
51 ;;;
52 ;;; Tools to build initial RAM disks (initrd's) for Linux-Libre, and in
53 ;;; particular initrd's that run Guile.
54 ;;;
55 ;;; Code:
56
57
58 (define* (expression->initrd exp
59 #:key
60 (guile %guile-static-stripped)
61 (gzip gzip)
62 (name "guile-initrd")
63 (system (%current-system)))
64 "Return as a file-like object a Linux initrd (a gzipped cpio archive)
65 containing GUILE and that evaluates EXP, a G-expression, upon booting. All
66 the derivations referenced by EXP are automatically copied to the initrd."
67
68 ;; General Linux overview in `Documentation/early-userspace/README' and
69 ;; `Documentation/filesystems/ramfs-rootfs-initramfs.txt'.
70
71 (define init
72 (program-file "init" exp #:guile guile))
73
74 (define builder
75 (with-imported-modules (source-module-closure
76 '((gnu build linux-initrd)))
77 #~(begin
78 (use-modules (gnu build linux-initrd))
79
80 (mkdir #$output)
81
82 ;; The guile used in the initrd must be present in the store, so
83 ;; that module loading works once the root is switched.
84 ;;
85 ;; To ensure that is the case, add an explicit reference to the
86 ;; guile package used in the initrd to the output.
87 ;;
88 ;; This fixes guix-patches bug #28399, "Fix mysql activation, and
89 ;; add a basic test".
90 (call-with-output-file (string-append #$ output "/references")
91 (lambda (port)
92 (simple-format port "~A\n" #$guile)))
93
94 (build-initrd (string-append #$output "/initrd")
95 #:guile #$guile
96 #:init #$init
97 ;; Copy everything INIT refers to into the initrd.
98 #:references-graphs '("closure")
99 #:gzip (string-append #$gzip "/bin/gzip")))))
100
101 (computed-file name builder
102 #:options
103 `(#:references-graphs (("closure" ,init)))))
104
105 (define (flat-linux-module-directory linux modules)
106 "Return a flat directory containing the Linux kernel modules listed in
107 MODULES and taken from LINUX."
108 (define build-exp
109 (with-imported-modules (source-module-closure
110 '((gnu build linux-modules)))
111 #~(begin
112 (use-modules (gnu build linux-modules)
113 (srfi srfi-1)
114 (srfi srfi-26))
115
116 (define module-dir
117 (string-append #$linux "/lib/modules"))
118
119 (define modules
120 (let* ((lookup (cut find-module-file module-dir <>))
121 (modules (map lookup '#$modules)))
122 (append modules
123 (recursive-module-dependencies modules
124 #:lookup-module lookup))))
125
126 (mkdir #$output)
127 (for-each (lambda (module)
128 (format #t "copying '~a'...~%" module)
129 (copy-file module
130 (string-append #$output "/"
131 (basename module))))
132 (delete-duplicates modules)))))
133
134 (computed-file "linux-modules" build-exp))
135
136 (define* (raw-initrd file-systems
137 #:key
138 (linux linux-libre)
139 (linux-modules '())
140 (mapped-devices '())
141 (helper-packages '())
142 qemu-networking?
143 volatile-root?
144 (on-error 'debug))
145 "Return as a file-like object a raw initrd, with kernel
146 modules taken from LINUX. FILE-SYSTEMS is a list of file-systems to be
147 mounted by the initrd, possibly in addition to the root file system specified
148 on the kernel command line via '--root'. LINUX-MODULES is a list of kernel
149 modules to be loaded at boot time. MAPPED-DEVICES is a list of device
150 mappings to realize before FILE-SYSTEMS are mounted.
151 HELPER-PACKAGES is a list of packages to be copied in the initrd. It may include
152 e2fsck/static or other packages needed by the initrd to check root partition.
153
154 When QEMU-NETWORKING? is true, set up networking with the standard QEMU
155 parameters.
156
157 When VOLATILE-ROOT? is true, the root file system is writable but any changes
158 to it are lost.
159
160 ON-ERROR is passed to 'call-with-error-handling'; it determines what happens
161 upon error."
162 (define device-mapping-commands
163 ;; List of gexps to open the mapped devices.
164 (map (lambda (md)
165 (let* ((source (mapped-device-source md))
166 (target (mapped-device-target md))
167 (type (mapped-device-type md))
168 (open (mapped-device-kind-open type)))
169 (open source target)))
170 mapped-devices))
171
172 (define kodir
173 (flat-linux-module-directory linux linux-modules))
174
175 (expression->initrd
176 (with-imported-modules (source-module-closure
177 '((gnu build linux-boot)
178 (guix build utils)
179 (guix build bournish)
180 (gnu system file-systems)
181 (gnu build file-systems)))
182 #~(begin
183 (use-modules (gnu build linux-boot)
184 (gnu system file-systems)
185 (guix build utils)
186 (guix build bournish) ;add the 'bournish' meta-command
187 (srfi srfi-26)
188
189 ;; FIXME: The following modules are for
190 ;; LUKS-DEVICE-MAPPING. We should instead propagate
191 ;; this info via gexps.
192 ((gnu build file-systems)
193 #:select (find-partition-by-luks-uuid))
194 (rnrs bytevectors))
195
196 (with-output-to-port (%make-void-port "w")
197 (lambda ()
198 (set-path-environment-variable "PATH" '("bin" "sbin")
199 '#$helper-packages)))
200
201 (boot-system #:mounts
202 (map spec->file-system
203 '#$(map file-system->spec file-systems))
204 #:pre-mount (lambda ()
205 (and #$@device-mapping-commands))
206 #:linux-modules '#$linux-modules
207 #:linux-module-directory '#$kodir
208 #:qemu-guest-networking? #$qemu-networking?
209 #:volatile-root? '#$volatile-root?
210 #:on-error '#$on-error)))
211 #:name "raw-initrd"))
212
213 (define* (file-system-packages file-systems #:key (volatile-root? #f))
214 "Return the list of statically-linked, stripped packages to check
215 FILE-SYSTEMS."
216 `(,@(if (find (lambda (fs)
217 (string-prefix? "ext" (file-system-type fs)))
218 file-systems)
219 (list e2fsck/static)
220 '())
221 ,@(if (find (lambda (fs)
222 (string-suffix? "fat" (file-system-type fs)))
223 file-systems)
224 (list fatfsck/static)
225 '())
226 ,@(if (find (file-system-type-predicate "btrfs") file-systems)
227 (list btrfs-progs/static)
228 '())))
229
230 (define-syntax vhash ;TODO: factorize
231 (syntax-rules (=>)
232 "Build a vhash with the given key/value mappings."
233 ((_)
234 vlist-null)
235 ((_ (key others ... => value) rest ...)
236 (vhash-cons key value
237 (vhash (others ... => value) rest ...)))
238 ((_ (=> value) rest ...)
239 (vhash rest ...))))
240
241 (define-syntax lookup-procedure
242 (syntax-rules (else)
243 "Return a procedure that lookups keys in the given dictionary."
244 ((_ mapping ... (else default))
245 (let ((table (vhash mapping ...)))
246 (lambda (key)
247 (match (vhash-assoc key table)
248 (#f default)
249 ((key . value) value)))))))
250
251 (define file-system-type-modules
252 ;; Given a file system type, return the list of modules it needs.
253 (lookup-procedure ("cifs" => '("md4" "ecb" "cifs"))
254 ("9p" => '("9p" "9pnet_virtio"))
255 ("btrfs" => '("btrfs"))
256 ("iso9660" => '("isofs"))
257 (else '())))
258
259 (define (file-system-modules file-systems)
260 "Return the list of Linux modules needed to mount FILE-SYSTEMS."
261 (append-map (compose file-system-type-modules file-system-type)
262 file-systems))
263
264 (define* (default-initrd-modules #:optional (system (%current-system)))
265 "Return the list of modules included in the initrd by default."
266 (define virtio-modules
267 ;; Modules for Linux para-virtualized devices, for use in QEMU guests.
268 '("virtio_pci" "virtio_balloon" "virtio_blk" "virtio_net"
269 "virtio_console" "virtio-rng"))
270
271 `("ahci" ;for SATA controllers
272 "usb-storage" "uas" ;for the installation image etc.
273 "usbhid" "hid-generic" "hid-apple" ;keyboards during early boot
274 "dm-crypt" "xts" "serpent_generic" "wp512" ;for encrypted root partitions
275 "nls_iso8859-1" ;for `mkfs.fat`, et.al
276 ,@(if (string-match "^(x86_64|i[3-6]86)-" system)
277 '("pata_acpi" "pata_atiixp" ;for ATA controllers
278 "isci") ;for SAS controllers like Intel C602
279 '())
280
281 ,@virtio-modules))
282
283 (define-syntax %base-initrd-modules
284 ;; This more closely matches our naming convention.
285 (identifier-syntax (default-initrd-modules)))
286
287 (define* (base-initrd file-systems
288 #:key
289 (linux linux-libre)
290 (linux-modules '())
291 (mapped-devices '())
292 qemu-networking?
293 volatile-root?
294 (extra-modules '()) ;deprecated
295 (on-error 'debug))
296 "Return as a file-like object a generic initrd, with kernel
297 modules taken from LINUX. FILE-SYSTEMS is a list of file-systems to be
298 mounted by the initrd, possibly in addition to the root file system specified
299 on the kernel command line via '--root'. MAPPED-DEVICES is a list of device
300 mappings to realize before FILE-SYSTEMS are mounted.
301
302 QEMU-NETWORKING? and VOLATILE-ROOT? behaves as in raw-initrd.
303
304 The initrd is automatically populated with all the kernel modules necessary
305 for FILE-SYSTEMS and for the given options. Additional kernel
306 modules can be listed in LINUX-MODULES. They will be added to the initrd, and
307 loaded at boot time in the order in which they appear."
308 (define linux-modules*
309 ;; Modules added to the initrd and loaded from the initrd.
310 `(,@linux-modules
311 ,@(file-system-modules file-systems)
312 ,@(if volatile-root?
313 '("overlay")
314 '())
315 ,@extra-modules))
316
317 (define helper-packages
318 (file-system-packages file-systems #:volatile-root? volatile-root?))
319
320 (raw-initrd file-systems
321 #:linux linux
322 #:linux-modules linux-modules*
323 #:mapped-devices mapped-devices
324 #:helper-packages helper-packages
325 #:qemu-networking? qemu-networking?
326 #:volatile-root? volatile-root?
327 #:on-error on-error))
328
329 ;;; linux-initrd.scm ends here