Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn boot.kernelParams into an attribute set #28593

Closed
wants to merge 1 commit into from

Conversation

aszlig
Copy link
Member

@aszlig aszlig commented Aug 26, 2017

Note that this pull request is only a suggestion, currently untested and requires discussion, please do not merge it!

This fixes #28277 and also its subsequent pull request #28392.

The problem with #28392 was that it has simply sorted the list of boot.kernelParams within its apply function by converting it into an attrset and back to a list. This had the disadvantage, that it's no longer possible to include store paths in parameter values and it also didn't allow items to be ordered, which breaks passing arguments to init by separating them with --.

In order to address #28277 properly, we turn boot.kernelParams into an attribute set in addition with a coercedTo type for backwards-compatibility with the list of strings that we had so far.

Being an attrset this allows us to deduplicate and sort the kernel parameters in a more meaningful way and gives us an error whenever a value is defined twice as well as an option to use priorities to override existing values.

For example if we want to set console=tty0 while already defined in another module, we can simply do so like this:

{ lib, ... }: {
  boot.kernelParams.console = lib.mkForce "tty0";
}

To support passing arguments to init we now have another option called boot.initArgs, which will be unordered to support custom init systems and also added to the kernel parameters separated by --.

Cc: @volth, @edolstra
Fixes: #28277

This fixes NixOS#28277 and also its subsequent pull request NixOS#28392.

The problem with the latter was that it has simply sorted the list of
kernelParams within its apply function by converting it into an attrset
and back to a list. This had the disadvantage, that it's no longer
possible to include store paths in parameter values and it also didn't
allow items to be ordered, which breaks passing arguments to init by
separating them with "--".

In order to address NixOS#28277 properly, we turn boot.kernelParams into an
attribute set in addition with a coercedTo type for backwards-
compatibility with the list of strings that we had so far.

Being an attrset this allows us to deduplicate and sort the kernel
parameters in a more meaningful way and gives us an error whenever a
value is defined twice as well as an option to use priorities to
override existing values.

For example if we want to set console=tty0 while already defined in
another module, we can simply do so like this:

{ lib, ... }: {
  boot.kernelParams.console = lib.mkForce "tty0";
}

To support passing arguments to init we now have another option called
boot.initArgs, which will be unordered to support custom init systems
and also added to the kernel parameters separated by "--".

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Cc: @volth, @edolstra
Fixes: NixOS#28277
@mention-bot
Copy link

@aszlig, thanks for your PR! By analyzing the history of the files in this pull request, we identified @edolstra, @viric and @puffnfresh to be potential reviewers.

@bjornfor
Copy link
Contributor

For example if we want to set console=tty0 while already defined in another module, we can simply do so like this:

 boot.kernelParams.console = lib.mkForce "tty0";

And if you actually want to have two (or more) console= args? Will that be possible? Ref. kernel documentation: https://www.kernel.org/doc/html/latest/admin-guide/serial-console.html, which shows an example with two console= args where order matters. (The last console= will be used when you open /dev/console.)

'';
};

boot.kernelParamList = mkOption {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This option can be avoided by having an apply attribute on boot.kernelParams that converts it to a list. I'm not convinced apply is a good idea in general, though...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using this option in order to make sure the resulting config attribute has the same type as the input and also to avoid to introduce another function inlib.

<manvolnum>1</manvolnum>
</citerefentry> via kernel parameters.

You could directly use <option>boot.kernelParams</option> to do the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs <para> if you want the paragraph breaks to show up in the docs.

default = let
enabled = filterAttrs (const (v: v != false)) config.boot.kernelParams;
hasSpace = val: builtins.match ".* .*" val != null;
mkStrVal = val: if hasSpace val then "\"${val}\"" else val;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just quote every value unconditionally?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply because it looks ugly in dmesg.

Furthermore, passing init arguments via
<option>boot.kernelParams</option> will cause the arguments to be
sorted, so it's unsuitable if you use an init that depends on the order
of arguments.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any init arguments that depend on the order? systemd(1) suggests the order shouldn't matter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There aren't, but init could also be a shell script and/or basically anything, if you want to pass $1 to such a shell script it will be difficult if the value is sorted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, in NixOS init is always systemd.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default it is, but for example to build for embedded systems, it might make sense to change it. An example of this is in the VirtualBox tests which changes init to avoid running a full system during software virtualization (which already is slow as hell).

@aszlig
Copy link
Member Author

aszlig commented Aug 27, 2017

@bjornfor: You're absolutely right and this might be somewhat of a dead end here. One solution for this would be to also accept lists for the attribute values (and merge multiple definitions accordingly), to provide multiple values but I fear this would make it way too complicated.

Example:

{ boot.kernelParams.console = [ "ttyS1,9600" "tty0" ]; }

@aszlig
Copy link
Member Author

aszlig commented Aug 27, 2017

So in summary: If #28277 is a real issue that we want to have fixed, I'd pursue this further, but I wouldn't mind closing this PR altogether.

@fpletz fpletz added this to the 18.03 milestone Aug 30, 2017
@aszlig aszlig closed this Apr 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants