>From 903b2d5bcb1fa28121ffd46e70f6503559c0ec95 Mon Sep 17 00:00:00 2001 Message-ID: <903b2d5bcb1fa28121ffd46e70f6503559c0ec95.1703992381.git.nathan_mail@nborghese.com> In-Reply-To: <626930cbad11e7f5546589fc290b2c95fee97b80.1703992381.git.nathan_mail@nborghese.com> References: <626930cbad11e7f5546589fc290b2c95fee97b80.1703992381.git.nathan_mail@nborghese.com> From: nathan Date: Sat, 30 Dec 2023 22:11:35 -0500 Subject: [PATCH 2/3] linux-modules: Parse kernel command line and pass module arguments * gnu/build/linux-modules.scm (parse-kernel-cmdline): New procedure. (load-linux-modules-from-directory): Use parse-kernel-cmdline to parse command line and supply options to load-linux-module*. Change-Id: I11a181670d0da5ea08965a80c396358e50bf5048 --- gnu/build/linux-modules.scm | 98 ++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/gnu/build/linux-modules.scm b/gnu/build/linux-modules.scm index c4950ea6d2..a54616b2d4 100644 --- a/gnu/build/linux-modules.scm +++ b/gnu/build/linux-modules.scm @@ -305,6 +305,93 @@ (define (modules-loaded) (((modules . _) ...) modules)))) +(define (parse-kernel-cmdline base) + "Input is the entire kernel command line, which is a space-delimited list of +modulename.parameter=value parts. The exact allowed syntax for the string is +based on the kmod_config_parse_kcmdline function from modprobe. Output is a +vhash where the key is the module name as a string and the value is a list of +strings in the form param=val (maybe with quotes in val). +`normalize-module-name' is applied to the module names. + +Duplicate parameters are not removed. The hyphen and underscore normalization +in parameter names is not applied. Empty module names are allowed." + (define (get-quoted start) + "It's similar to string-tokenize, but quoting is supported. Two values +are returned. First is the chunk of characters, second is the unused remainder +of the string. returns (values \"\" \"\") if the input string is just +whitespace or there's an unterminated quote" + ;; strip whitespace at the start + (let ((start (substring + start + (or + (string-skip start char-set:whitespace) + (string-length start))))) + (let lp ((s start) (quoted? #f)) + (if quoted? + (if (string-null? s) + (values "" "") + (lp (substring s 1) (not (eqv? (string-ref s 0) #\")))) + (if (or (string-null? s) (char-whitespace? (string-ref s 0))) + (values + (substring start 0 (- (string-length start) (string-length s))) + s) + (lp (substring s 1) (eqv? (string-ref s 0) #\"))))))) + (let lp ((s base) (table vlist-null)) + (call-with-values (lambda () (get-quoted s)) + (lambda (strblock rest) + (if (string-null? strblock) + table + ;; get parameter name. it is mandatory. + (let ((dotpos (string-index strblock #\.))) + (if dotpos + (let* ((equalpos (string-index strblock #\= dotpos)) + ;; modprobe allows a string like: + ;; "modulename.param=val" + ;; and then it converts it to + ;; modulename.param="val" + ;; This is the only case where a quote is + ;; allowed outside of the value part. + (is-bad-quoting (eqv? (string-ref strblock 0) #\")) + (modulename + (substring strblock (if is-bad-quoting 1 0) dotpos)) + (parampart + (substring + strblock + (1+ dotpos) + (or equalpos (string-length strblock))))) + ;; whitespace is only allowed in value + ;; no quotes allows in param segment + ;; param cant have dot + ;; module cant have equals + (if (or + (string-any (char-set-union + char-set:whitespace + (char-set #\" #\.)) + parampart) + (string-any (char-set-union + char-set:whitespace + (char-set #\=)) + modulename)) + (lp rest table) ;; ignore and recur + ;; add it to the table + (let ((modulename (normalize-module-name modulename))) + (lp rest + (let ((oldval (vhash-assoc modulename table))) + (vhash-cons + modulename + (cons + (if is-bad-quoting + (string-append + (substring strblock + (1+ dotpos) + (1+ equalpos)) + "\"" (substring strblock (1+ equalpos))) + (substring strblock (1+ dotpos))) + (if oldval (cdr oldval) '())) + (vhash-delete modulename table))))))) + (lp rest table))) ;; ignore and recur + ))))) + (define (module-black-list) "Return the black list of modules that must not be loaded. This black list is specified using 'modprobe.blacklist=MODULE1,MODULE2,...' on the kernel @@ -387,10 +474,19 @@ (define (load-linux-modules-from-directory modules directory) needed." (define module-name->file-name (module-name-lookup directory)) + (define options-list + (parse-kernel-cmdline + (call-with-input-file "/proc/cmdline" get-string-all))) + (define (get-options modulename) + (let ((pair (vhash-assoc modulename options-list))) + (if pair + (string-join (cdr pair) " ") + ""))) (for-each (lambda (module) (load-linux-module* (module-name->file-name module) - #:lookup-module module-name->file-name)) + #:lookup-module module-name->file-name + #:get-options get-options)) modules)) -- 2.41.0