linux-initrd.scm 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2013, 2014, 2015, 2016, 2017 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. (define-module (gnu system linux-initrd)
  22. #:use-module (guix monads)
  23. #:use-module (guix store)
  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 guile)
  35. #:use-module ((gnu packages make-bootstrap)
  36. #:select (%guile-static-stripped))
  37. #:use-module (gnu system file-systems)
  38. #:use-module (gnu system mapped-devices)
  39. #:use-module (ice-9 match)
  40. #:use-module (ice-9 regex)
  41. #:use-module (srfi srfi-1)
  42. #:use-module (srfi srfi-26)
  43. #:export (expression->initrd
  44. raw-initrd
  45. file-system-packages
  46. base-initrd))
  47. ;;; Commentary:
  48. ;;;
  49. ;;; Tools to build initial RAM disks (initrd's) for Linux-Libre, and in
  50. ;;; particular initrd's that run Guile.
  51. ;;;
  52. ;;; Code:
  53. (define* (expression->initrd exp
  54. #:key
  55. (guile %guile-static-stripped)
  56. (gzip gzip)
  57. (name "guile-initrd")
  58. (system (%current-system)))
  59. "Return a derivation that builds a Linux initrd (a gzipped cpio archive)
  60. containing GUILE and that evaluates EXP, a G-expression, upon booting. All
  61. the derivations referenced by EXP are automatically copied to the initrd."
  62. ;; General Linux overview in `Documentation/early-userspace/README' and
  63. ;; `Documentation/filesystems/ramfs-rootfs-initramfs.txt'.
  64. (define init
  65. (program-file "init" exp #:guile guile))
  66. (define builder
  67. (with-imported-modules (source-module-closure
  68. '((gnu build linux-initrd)))
  69. #~(begin
  70. (use-modules (gnu build linux-initrd))
  71. (mkdir #$output)
  72. ;; The guile used in the initrd must be present in the store, so
  73. ;; that module loading works once the root is switched.
  74. ;;
  75. ;; To ensure that is the case, add an explicit reference to the
  76. ;; guile package used in the initrd to the output.
  77. ;;
  78. ;; This fixes guix-patches bug #28399, "Fix mysql activation, and
  79. ;; add a basic test".
  80. (call-with-output-file (string-append #$ output "/references")
  81. (lambda (port)
  82. (simple-format port "~A\n" #$guile)))
  83. (build-initrd (string-append #$output "/initrd")
  84. #:guile #$guile
  85. #:init #$init
  86. ;; Copy everything INIT refers to into the initrd.
  87. #:references-graphs '("closure")
  88. #:gzip (string-append #$gzip "/bin/gzip")))))
  89. (gexp->derivation name builder
  90. #:references-graphs `(("closure" ,init))))
  91. (define (flat-linux-module-directory linux modules)
  92. "Return a flat directory containing the Linux kernel modules listed in
  93. MODULES and taken from LINUX."
  94. (define build-exp
  95. (with-imported-modules (source-module-closure
  96. '((guix build utils)
  97. (gnu build linux-modules)))
  98. #~(begin
  99. (use-modules (ice-9 match) (ice-9 regex)
  100. (srfi srfi-1)
  101. (guix build utils)
  102. (gnu build linux-modules))
  103. (define (string->regexp str)
  104. ;; Return a regexp that matches STR exactly.
  105. (string-append "^" (regexp-quote str) "$"))
  106. (define module-dir
  107. (string-append #$linux "/lib/modules"))
  108. (define (lookup module)
  109. (let ((name (ensure-dot-ko module)))
  110. (match (find-files module-dir (string->regexp name))
  111. ((file)
  112. file)
  113. (()
  114. (error "module not found" name module-dir))
  115. ((_ ...)
  116. (error "several modules by that name"
  117. name module-dir)))))
  118. (define modules
  119. (let ((modules (map lookup '#$modules)))
  120. (append modules
  121. (recursive-module-dependencies modules
  122. #:lookup-module lookup))))
  123. (mkdir #$output)
  124. (for-each (lambda (module)
  125. (format #t "copying '~a'...~%" module)
  126. (copy-file module
  127. (string-append #$output "/"
  128. (basename module))))
  129. (delete-duplicates modules)))))
  130. (computed-file "linux-modules" build-exp))
  131. (define* (raw-initrd file-systems
  132. #:key
  133. (linux linux-libre)
  134. (linux-modules '())
  135. (mapped-devices '())
  136. (helper-packages '())
  137. qemu-networking?
  138. volatile-root?)
  139. "Return a monadic derivation that builds a raw initrd, with kernel
  140. modules taken from LINUX. FILE-SYSTEMS is a list of file-systems to be
  141. mounted by the initrd, possibly in addition to the root file system specified
  142. on the kernel command line via '--root'. LINUX-MODULES is a list of kernel
  143. modules to be loaded at boot time. MAPPED-DEVICES is a list of device
  144. mappings to realize before FILE-SYSTEMS are mounted.
  145. HELPER-PACKAGES is a list of packages to be copied in the initrd. It may include
  146. e2fsck/static or other packages needed by the initrd to check root partition.
  147. When QEMU-NETWORKING? is true, set up networking with the standard QEMU
  148. parameters.
  149. When VOLATILE-ROOT? is true, the root file system is writable but any changes
  150. to it are lost."
  151. (define device-mapping-commands
  152. ;; List of gexps to open the mapped devices.
  153. (map (lambda (md)
  154. (let* ((source (mapped-device-source md))
  155. (target (mapped-device-target md))
  156. (type (mapped-device-type md))
  157. (open (mapped-device-kind-open type)))
  158. (open source target)))
  159. mapped-devices))
  160. (define kodir
  161. (flat-linux-module-directory linux linux-modules))
  162. (expression->initrd
  163. (with-imported-modules (source-module-closure
  164. '((gnu build linux-boot)
  165. (guix build utils)
  166. (guix build bournish)
  167. (gnu system file-systems)
  168. (gnu build file-systems)))
  169. #~(begin
  170. (use-modules (gnu build linux-boot)
  171. (gnu system file-systems)
  172. (guix build utils)
  173. (guix build bournish) ;add the 'bournish' meta-command
  174. (srfi srfi-26)
  175. ;; FIXME: The following modules are for
  176. ;; LUKS-DEVICE-MAPPING. We should instead propagate
  177. ;; this info via gexps.
  178. ((gnu build file-systems)
  179. #:select (find-partition-by-luks-uuid))
  180. (rnrs bytevectors))
  181. (with-output-to-port (%make-void-port "w")
  182. (lambda ()
  183. (set-path-environment-variable "PATH" '("bin" "sbin")
  184. '#$helper-packages)))
  185. (boot-system #:mounts
  186. (map spec->file-system
  187. '#$(map file-system->spec file-systems))
  188. #:pre-mount (lambda ()
  189. (and #$@device-mapping-commands))
  190. #:linux-modules '#$linux-modules
  191. #:linux-module-directory '#$kodir
  192. #:qemu-guest-networking? #$qemu-networking?
  193. #:volatile-root? '#$volatile-root?)))
  194. #:name "raw-initrd"))
  195. (define* (file-system-packages file-systems #:key (volatile-root? #f))
  196. "Return the list of statically-linked, stripped packages to check
  197. FILE-SYSTEMS."
  198. `(,@(if (find (lambda (fs)
  199. (string-prefix? "ext" (file-system-type fs)))
  200. file-systems)
  201. (list e2fsck/static)
  202. '())
  203. ,@(if (find (lambda (fs)
  204. (string-suffix? "fat" (file-system-type fs)))
  205. file-systems)
  206. (list fatfsck/static)
  207. '())
  208. ,@(if (find (file-system-type-predicate "btrfs") file-systems)
  209. (list btrfs-progs/static)
  210. '())))
  211. (define* (base-initrd file-systems
  212. #:key
  213. (linux linux-libre)
  214. (mapped-devices '())
  215. qemu-networking?
  216. volatile-root?
  217. (virtio? #t)
  218. (extra-modules '()))
  219. "Return a monadic derivation that builds a generic initrd, with kernel
  220. modules taken from LINUX. FILE-SYSTEMS is a list of file-systems to be
  221. mounted by the initrd, possibly in addition to the root file system specified
  222. on the kernel command line via '--root'. MAPPED-DEVICES is a list of device
  223. mappings to realize before FILE-SYSTEMS are mounted.
  224. QEMU-NETWORKING? and VOLATILE-ROOT? behaves as in raw-initrd.
  225. When VIRTIO? is true, load additional modules so the initrd can
  226. be used as a QEMU guest with the root file system on a para-virtualized block
  227. device.
  228. The initrd is automatically populated with all the kernel modules necessary
  229. for FILE-SYSTEMS and for the given options. However, additional kernel
  230. modules can be listed in EXTRA-MODULES. They will be added to the initrd, and
  231. loaded at boot time in the order in which they appear."
  232. (define virtio-modules
  233. ;; Modules for Linux para-virtualized devices, for use in QEMU guests.
  234. '("virtio_pci" "virtio_balloon" "virtio_blk" "virtio_net"
  235. "virtio_console"))
  236. (define cifs-modules
  237. ;; Modules needed to mount CIFS file systems.
  238. '("md4" "ecb" "cifs"))
  239. (define virtio-9p-modules
  240. ;; Modules for the 9p paravirtualized file system.
  241. '("9p" "9pnet_virtio"))
  242. (define (file-system-type-predicate type)
  243. (lambda (fs)
  244. (string=? (file-system-type fs) type)))
  245. (define linux-modules
  246. ;; Modules added to the initrd and loaded from the initrd.
  247. `("ahci" ;for SATA controllers
  248. "usb-storage" "uas" ;for the installation image etc.
  249. "usbhid" "hid-generic" "hid-apple" ;keyboards during early boot
  250. "dm-crypt" "xts" "serpent_generic" "wp512" ;for encrypted root partitions
  251. "nvme" ;for new SSD NVMe devices
  252. "nls_iso8859-1" ;for `mkfs.fat`, et.al
  253. ,@(if (string-match "^(x86_64|i[3-6]86)-" (%current-system))
  254. '("pata_acpi" "pata_atiixp" ;for ATA controllers
  255. "isci") ;for SAS controllers like Intel C602
  256. '())
  257. ,@(if (or virtio? qemu-networking?)
  258. virtio-modules
  259. '())
  260. ,@(if (find (file-system-type-predicate "cifs") file-systems)
  261. cifs-modules
  262. '())
  263. ,@(if (find (file-system-type-predicate "9p") file-systems)
  264. virtio-9p-modules
  265. '())
  266. ,@(if (find (file-system-type-predicate "btrfs") file-systems)
  267. '("btrfs")
  268. '())
  269. ,@(if (find (file-system-type-predicate "iso9660") file-systems)
  270. '("isofs")
  271. '())
  272. ,@(if volatile-root?
  273. '("overlay")
  274. '())
  275. ,@extra-modules))
  276. (define helper-packages
  277. (file-system-packages file-systems #:volatile-root? volatile-root?))
  278. (raw-initrd file-systems
  279. #:linux linux
  280. #:linux-modules linux-modules
  281. #:mapped-devices mapped-devices
  282. #:helper-packages helper-packages
  283. #:qemu-networking? qemu-networking?
  284. #:volatile-root? volatile-root?))
  285. ;;; linux-initrd.scm ends here