summaryrefslogtreecommitdiff
path: root/gnu/build
diff options
context:
space:
mode:
authorMathieu Othacehe <othacehe@gnu.org>2020-07-05 12:23:21 +0200
committerMathieu Othacehe <othacehe@gnu.org>2020-08-25 11:53:20 +0200
commit755f365b02b42a5d1e8ef3000dadef069553a478 (patch)
tree57ce759104439219c2c6076aa3c1af875487c5c1 /gnu/build
parent46ef674b34fd63f6bcd5bd07348d5c66eb8bdf29 (diff)
linux-libre: Support module compression.
This commit adds support for GZIP compression for linux-libre kernel modules. The initrd modules are kept uncompressed as the initrd is already compressed as a whole. The linux-libre kernel also supports XZ compression, but as Guix does not have any available bindings for now, and the compression time is far more significant, GZIP seems to be a better option. * gnu/build/linux-modules.scm (modinfo-section-contents): Use 'call-with-gzip-input-port' to read from a module file using '.gz' extension, (strip-extension): new procedure, (dot-ko): adapt to support compression, (ensure-dot-ko): ditto, (file-name->module-name): ditto, (find-module-file): ditto, (load-linux-module*): ditto, (module-name->file-name/guess): ditto, (module-name-lookup): ditto, (write-module-name-database): ditto, (write-module-alias-database): ditto, (write-module-device-database): ditto. * gnu/installer.scm (installer-program): Add "guile-zlib" to the extensions. * gnu/machine/ssh.scm (machine-check-initrd-modules): Ditto. * gnu/services.scm (activation-script): Ditto. * gnu/services/base.scm (default-serial-port): Ditto, (agetty-shepherd-service): ditto, (udev-service-type): ditto. * gnu/system/image.scm (gcrypt-sqlite3&co): Ditto. * gnu/system/linux-initrd.scm (flat-linux-module-directory): Add "guile-zlib" to the extensions and make sure that the initrd only contains uncompressed module files. * gnu/system/shadow.scm (account-shepherd-service): Add "guile-zlib" to the extensions. * guix/profiles.scm (linux-module-database): Ditto.
Diffstat (limited to 'gnu/build')
-rw-r--r--gnu/build/linux-modules.scm115
1 files changed, 79 insertions, 36 deletions
diff --git a/gnu/build/linux-modules.scm b/gnu/build/linux-modules.scm
index aa1c7cfeae2..3a473220655 100644
--- a/gnu/build/linux-modules.scm
+++ b/gnu/build/linux-modules.scm
@@ -24,6 +24,7 @@
24 #:use-module (guix build syscalls) 24 #:use-module (guix build syscalls)
25 #:use-module ((guix build utils) #:select (find-files invoke)) 25 #:use-module ((guix build utils) #:select (find-files invoke))
26 #:use-module (guix build union) 26 #:use-module (guix build union)
27 #:autoload (zlib) (call-with-gzip-input-port)
27 #:use-module (rnrs io ports) 28 #:use-module (rnrs io ports)
28 #:use-module (rnrs bytevectors) 29 #:use-module (rnrs bytevectors)
29 #:use-module (srfi srfi-1) 30 #:use-module (srfi srfi-1)
@@ -94,10 +95,28 @@ string list."
94 (cons (string->symbol (string-take str =)) 95 (cons (string->symbol (string-take str =))
95 (string-drop str (+ 1 =))))) 96 (string-drop str (+ 1 =)))))
96 97
98;; Matches kernel modules, without compression, with GZIP compression or with
99;; XZ compression.
100(define module-regex "\\.ko(\\.gz|\\.xz)?$")
101
97(define (modinfo-section-contents file) 102(define (modinfo-section-contents file)
98 "Return the contents of the '.modinfo' section of FILE as a list of 103 "Return the contents of the '.modinfo' section of FILE as a list of
99key/value pairs.." 104key/value pairs.."
100 (let* ((bv (call-with-input-file file get-bytevector-all)) 105 (define (get-bytevector file)
106 (cond
107 ((string-suffix? ".ko.gz" file)
108 (let ((port (open-file file "r0")))
109 (dynamic-wind
110 (lambda ()
111 #t)
112 (lambda ()
113 (call-with-gzip-input-port port get-bytevector-all))
114 (lambda ()
115 (close-port port)))))
116 (else
117 (call-with-input-file file get-bytevector-all))))
118
119 (let* ((bv (get-bytevector file))
101 (elf (parse-elf bv)) 120 (elf (parse-elf bv))
102 (section (elf-section-by-name elf ".modinfo")) 121 (section (elf-section-by-name elf ".modinfo"))
103 (modinfo (section-contents elf section))) 122 (modinfo (section-contents elf section)))
@@ -110,7 +129,7 @@ key/value pairs.."
110(define (module-formal-name file) 129(define (module-formal-name file)
111 "Return the module name of FILE as it appears in its info section. Usually 130 "Return the module name of FILE as it appears in its info section. Usually
112the module name is the same as the base name of FILE, modulo hyphens and minus 131the module name is the same as the base name of FILE, modulo hyphens and minus
113the \".ko\" extension." 132the \".ko[.gz|.xz]\" extension."
114 (match (assq 'name (modinfo-section-contents file)) 133 (match (assq 'name (modinfo-section-contents file))
115 (('name . name) name) 134 (('name . name) name)
116 (#f #f))) 135 (#f #f)))
@@ -171,14 +190,25 @@ modules that can be postloaded, of the soft dependencies of module FILE."
171 (_ #f)) 190 (_ #f))
172 (modinfo-section-contents file)))) 191 (modinfo-section-contents file))))
173 192
174(define dot-ko 193(define (strip-extension filename)
175 (cut string-append <> ".ko")) 194 (let ((extension (string-index filename #\.)))
176 195 (if extension
177(define (ensure-dot-ko name) 196 (string-take filename extension)
178 "Return NAME with a '.ko' prefix appended, unless it already has it." 197 filename)))
179 (if (string-suffix? ".ko" name) 198
199(define (dot-ko name compression)
200 (let ((suffix (match compression
201 ('xz ".ko.xz")
202 ('gzip ".ko.gz")
203 (else ".ko"))))
204 (string-append name suffix)))
205
206(define (ensure-dot-ko name compression)
207 "Return NAME with a '.ko[.gz|.xz]' suffix appended, unless it already has
208it."
209 (if (string-contains name ".ko")
180 name 210 name
181 (dot-ko name))) 211 (dot-ko name compression)))
182 212
183(define (normalize-module-name module) 213(define (normalize-module-name module)
184 "Return the \"canonical\" name for MODULE, replacing hyphens with 214 "Return the \"canonical\" name for MODULE, replacing hyphens with
@@ -191,9 +221,9 @@ underscores."
191 module)) 221 module))
192 222
193(define (file-name->module-name file) 223(define (file-name->module-name file)
194 "Return the module name corresponding to FILE, stripping the trailing '.ko' 224 "Return the module name corresponding to FILE, stripping the trailing
195and normalizing it." 225'.ko[.gz|.xz]' and normalizing it."
196 (normalize-module-name (basename file ".ko"))) 226 (normalize-module-name (strip-extension (basename file))))
197 227
198(define (find-module-file directory module) 228(define (find-module-file directory module)
199 "Lookup module NAME under DIRECTORY, and return its absolute file name. 229 "Lookup module NAME under DIRECTORY, and return its absolute file name.
@@ -208,19 +238,19 @@ whereas file names often, but not always, use hyphens. Examples:
208 ;; List of possible file names. XXX: It would of course be cleaner to 238 ;; List of possible file names. XXX: It would of course be cleaner to
209 ;; have a database that maps module names to file names and vice versa, 239 ;; have a database that maps module names to file names and vice versa,
210 ;; but everyone seems to be doing hacks like this one. Oh well! 240 ;; but everyone seems to be doing hacks like this one. Oh well!
211 (map ensure-dot-ko 241 (delete-duplicates
212 (delete-duplicates 242 (list module
213 (list module 243 (normalize-module-name module)
214 (normalize-module-name module) 244 (string-map (lambda (chr) ;converse of 'normalize-module-name'
215 (string-map (lambda (chr) ;converse of 'normalize-module-name' 245 (case chr
216 (case chr 246 ((#\_) #\-)
217 ((#\_) #\-) 247 (else chr)))
218 (else chr))) 248 module))))
219 module)))))
220 249
221 (match (find-files directory 250 (match (find-files directory
222 (lambda (file stat) 251 (lambda (file stat)
223 (member (basename file) names))) 252 (member (strip-extension
253 (basename file)) names)))
224 ((file) 254 ((file)
225 file) 255 file)
226 (() 256 (()
@@ -290,8 +320,8 @@ not a file name."
290 (recursive? #t) 320 (recursive? #t)
291 (lookup-module dot-ko) 321 (lookup-module dot-ko)
292 (black-list (module-black-list))) 322 (black-list (module-black-list)))
293 "Load Linux module from FILE, the name of a '.ko' file; return true on 323 "Load Linux module from FILE, the name of a '.ko[.gz|.xz]' file; return true
294success, false otherwise. When RECURSIVE? is true, load its dependencies 324on success, false otherwise. When RECURSIVE? is true, load its dependencies
295first (à la 'modprobe'.) The actual files containing modules depended on are 325first (à la 'modprobe'.) The actual files containing modules depended on are
296obtained by calling LOOKUP-MODULE with the module name. Modules whose name 326obtained by calling LOOKUP-MODULE with the module name. Modules whose name
297appears in BLACK-LIST are not loaded." 327appears in BLACK-LIST are not loaded."
@@ -523,16 +553,29 @@ are required to access DEVICE."
523;;; Module databases. 553;;; Module databases.
524;;; 554;;;
525 555
526(define (module-name->file-name/guess directory name) 556(define* (module-name->file-name/guess directory name
557 #:key compression)
527 "Guess the file name corresponding to NAME, a module name. That doesn't 558 "Guess the file name corresponding to NAME, a module name. That doesn't
528always work because sometimes underscores in NAME map to hyphens (e.g., 559always work because sometimes underscores in NAME map to hyphens (e.g.,
529\"input-leds.ko\"), sometimes not (e.g., \"mac_hid.ko\")." 560\"input-leds.ko\"), sometimes not (e.g., \"mac_hid.ko\"). If the module is
530 (string-append directory "/" (ensure-dot-ko name))) 561compressed then COMPRESSED can be set to 'xz or 'gzip, depending on the
562compression type."
563 (string-append directory "/" (ensure-dot-ko name compression)))
531 564
532(define (module-name-lookup directory) 565(define (module-name-lookup directory)
533 "Return a one argument procedure that takes a module name (e.g., 566 "Return a one argument procedure that takes a module name (e.g.,
534\"input_leds\") and returns its absolute file name (e.g., 567\"input_leds\") and returns its absolute file name (e.g.,
535\"/.../input-leds.ko\")." 568\"/.../input-leds.ko\")."
569 (define (guess-file-name name)
570 (let ((names (list
571 (module-name->file-name/guess directory name)
572 (module-name->file-name/guess directory name
573 #:compression 'xz)
574 (module-name->file-name/guess directory name
575 #:compression 'gzip))))
576 (or (find file-exists? names)
577 (first names))))
578
536 (catch 'system-error 579 (catch 'system-error
537 (lambda () 580 (lambda ()
538 (define mapping 581 (define mapping
@@ -541,23 +584,23 @@ always work because sometimes underscores in NAME map to hyphens (e.g.,
541 584
542 (lambda (name) 585 (lambda (name)
543 (or (assoc-ref mapping name) 586 (or (assoc-ref mapping name)
544 (module-name->file-name/guess directory name)))) 587 (guess-file-name name))))
545 (lambda args 588 (lambda args
546 (if (= ENOENT (system-error-errno args)) 589 (if (= ENOENT (system-error-errno args))
547 (cut module-name->file-name/guess directory <>) 590 (cut guess-file-name <>)
548 (apply throw args))))) 591 (apply throw args)))))
549 592
550(define (write-module-name-database directory) 593(define (write-module-name-database directory)
551 "Write a database that maps \"module names\" as they appear in the relevant 594 "Write a database that maps \"module names\" as they appear in the relevant
552ELF section of '.ko' files, to actual file names. This format is 595ELF section of '.ko[.gz|.xz]' files, to actual file names. This format is
553Guix-specific. It aims to deal with inconsistent naming, in particular 596Guix-specific. It aims to deal with inconsistent naming, in particular
554hyphens vs. underscores." 597hyphens vs. underscores."
555 (define mapping 598 (define mapping
556 (map (lambda (file) 599 (map (lambda (file)
557 (match (module-formal-name file) 600 (match (module-formal-name file)
558 (#f (cons (basename file ".ko") file)) 601 (#f (cons (strip-extension (basename file)) file))
559 (name (cons name file)))) 602 (name (cons name file))))
560 (find-files directory "\\.ko$"))) 603 (find-files directory module-regex)))
561 604
562 (call-with-output-file (string-append directory "/modules.name") 605 (call-with-output-file (string-append directory "/modules.name")
563 (lambda (port) 606 (lambda (port)
@@ -569,12 +612,12 @@ hyphens vs. underscores."
569 (pretty-print mapping port)))) 612 (pretty-print mapping port))))
570 613
571(define (write-module-alias-database directory) 614(define (write-module-alias-database directory)
572 "Traverse the '.ko' files in DIRECTORY and create the corresponding 615 "Traverse the '.ko[.gz|.xz]' files in DIRECTORY and create the corresponding
573'modules.alias' file." 616'modules.alias' file."
574 (define aliases 617 (define aliases
575 (map (lambda (file) 618 (map (lambda (file)
576 (cons (file-name->module-name file) (module-aliases file))) 619 (cons (file-name->module-name file) (module-aliases file)))
577 (find-files directory "\\.ko$"))) 620 (find-files directory module-regex)))
578 621
579 (call-with-output-file (string-append directory "/modules.alias") 622 (call-with-output-file (string-append directory "/modules.alias")
580 (lambda (port) 623 (lambda (port)
@@ -616,7 +659,7 @@ are found, return a tuple (DEVNAME TYPE MAJOR MINOR), otherwise return #f."
616 (char-set-complement (char-set #\-))) 659 (char-set-complement (char-set #\-)))
617 660
618(define (write-module-device-database directory) 661(define (write-module-device-database directory)
619 "Traverse the '.ko' files in DIRECTORY and create the corresponding 662 "Traverse the '.ko[.gz|.xz]' files in DIRECTORY and create the corresponding
620'modules.devname' file. This file contains information about modules that can 663'modules.devname' file. This file contains information about modules that can
621be loaded on-demand, such as file system modules." 664be loaded on-demand, such as file system modules."
622 (define aliases 665 (define aliases
@@ -624,7 +667,7 @@ be loaded on-demand, such as file system modules."
624 (match (aliases->device-tuple (module-aliases file)) 667 (match (aliases->device-tuple (module-aliases file))
625 (#f #f) 668 (#f #f)
626 (tuple (cons (file-name->module-name file) tuple)))) 669 (tuple (cons (file-name->module-name file) tuple))))
627 (find-files directory "\\.ko$"))) 670 (find-files directory module-regex)))
628 671
629 (call-with-output-file (string-append directory "/modules.devname") 672 (call-with-output-file (string-append directory "/modules.devname")
630 (lambda (port) 673 (lambda (port)