raspberry-pi: add config.txt generation module
Two new files in raspberry-pi/common/: config-txt.nix lets you declare config.txt contents through hardware.raspberry-pi.configtxt.settings (RFC 42 style — plain values, null to remove, no enable/value wrappers). config-txt-defaults.nix has the same defaults as Raspberry Pi OS: vc4-kms-v3d, audio on, arm_boost, CM4 otg_mode, CM5 dwc2, etc. All mkDefault so they are easy to override. Not wired into board profiles yet — that comes with the RPi 5 sub-module work. Based on nvmd/nixos-raspberrypi.
This commit is contained in:
parent
3966ce987e
commit
a688dfcbb5
2 changed files with 159 additions and 0 deletions
29
raspberry-pi/common/config-txt-defaults.nix
Normal file
29
raspberry-pi/common/config-txt-defaults.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Default config.txt settings matching the official Raspberry Pi OS defaults.
|
||||
#
|
||||
# Source: https://github.com/RPi-Distro/pi-gen/blob/master/stage1/00-boot-files/files/config.txt
|
||||
# All values use mkDefault so they can be easily overridden.
|
||||
#
|
||||
# Reference: https://www.raspberrypi.com/documentation/computers/config_txt.html
|
||||
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
hardware.raspberry-pi.configtxt.settings = {
|
||||
all = {
|
||||
camera_auto_detect = lib.mkDefault true;
|
||||
display_auto_detect = lib.mkDefault true;
|
||||
max_framebuffers = lib.mkDefault 2;
|
||||
disable_fw_kms_setup = lib.mkDefault true;
|
||||
disable_overscan = lib.mkDefault true;
|
||||
arm_boost = lib.mkDefault true;
|
||||
dtparam = lib.mkDefault [ "audio=on" ];
|
||||
dtoverlay = lib.mkDefault [ "vc4-kms-v3d" ];
|
||||
};
|
||||
cm4 = {
|
||||
otg_mode = lib.mkDefault true;
|
||||
};
|
||||
cm5 = {
|
||||
dtoverlay = lib.mkDefault [ "dwc2,dr_mode=host" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
130
raspberry-pi/common/config-txt.nix
Normal file
130
raspberry-pi/common/config-txt.nix
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# config.txt generation module for Raspberry Pi
|
||||
#
|
||||
# Generates config.txt from structured Nix options. The type system models
|
||||
# config.txt as nested attrs: each nesting level adds a conditional filter,
|
||||
# and leaves are config values. Repeated keys (dtparam, dtoverlay, gpio)
|
||||
# are supported via lists.
|
||||
#
|
||||
# Based on work from nvmd/nixos-raspberrypi (MIT License) and rendering
|
||||
# approach suggested by @quentinmit. Follows RFC 42.
|
||||
#
|
||||
# Reference: https://www.raspberrypi.com/documentation/computers/config_txt.html
|
||||
|
||||
{ lib, config, ... }:
|
||||
|
||||
let
|
||||
cfg = config.hardware.raspberry-pi.configtxt;
|
||||
|
||||
mkValueString =
|
||||
v:
|
||||
if builtins.isInt v then
|
||||
toString v
|
||||
else if builtins.isString v then
|
||||
v
|
||||
else if true == v then
|
||||
"1"
|
||||
else if false == v then
|
||||
"0"
|
||||
else
|
||||
builtins.abort "config.txt: unsupported value type: ${builtins.typeOf v}";
|
||||
|
||||
mkKeyValue = lib.generators.mkKeyValueDefault { inherit mkValueString; } "=";
|
||||
|
||||
# Recursively flatten nested attrs into a list of { conditionals, name, value } records.
|
||||
# Each nesting level (except the leaf) is a conditional filter.
|
||||
# "all" filters are omitted from the conditionals list since they reset state.
|
||||
recurse =
|
||||
path: value:
|
||||
if builtins.isAttrs value && !(builtins.isList value) && !(value ? _type) then
|
||||
lib.flatten (lib.mapAttrsToList (name: recurse ([ name ] ++ path)) value)
|
||||
else
|
||||
{
|
||||
conditionals = lib.sort builtins.lessThan (lib.filter (k: k != "all") (lib.tail path));
|
||||
name = lib.head path;
|
||||
inherit value;
|
||||
};
|
||||
|
||||
# Group flattened items by their conditional filter set, then render.
|
||||
groupItems =
|
||||
items:
|
||||
lib.mapAttrsToList (groupJSON: groupItems: {
|
||||
conditionals = builtins.fromJSON groupJSON;
|
||||
items = builtins.listToAttrs groupItems;
|
||||
}) (builtins.groupBy (x: builtins.toJSON x.conditionals) items);
|
||||
|
||||
mkGroup =
|
||||
group:
|
||||
lib.concatMapStrings (k: "[${k}]\n") group.conditionals
|
||||
+ lib.generators.toKeyValue {
|
||||
inherit mkKeyValue;
|
||||
listsAsDuplicateKeys = true;
|
||||
} group.items;
|
||||
|
||||
toConfigTxt =
|
||||
attrs:
|
||||
let
|
||||
groups = lib.sort (a: b: a.conditionals < b.conditionals) (
|
||||
groupItems (lib.flatten (recurse [ ] attrs))
|
||||
);
|
||||
in
|
||||
lib.concatMapStringsSep "\n[all]\n" mkGroup groups;
|
||||
|
||||
in
|
||||
{
|
||||
options.hardware.raspberry-pi.configtxt = {
|
||||
settings = lib.mkOption {
|
||||
type =
|
||||
with lib.types;
|
||||
let
|
||||
atom = oneOf [
|
||||
str
|
||||
int
|
||||
bool
|
||||
];
|
||||
molecule = oneOf [
|
||||
atom
|
||||
(listOf atom)
|
||||
(attrsOf molecule)
|
||||
];
|
||||
in
|
||||
attrsOf molecule;
|
||||
default = { };
|
||||
description = ''
|
||||
Structured configuration for the Raspberry Pi `config.txt` file.
|
||||
|
||||
Top-level keys are conditional filter sections (`all`, `pi4`, `pi5`,
|
||||
`cm4`, etc.). Nesting adds stacked conditional filters. Leaves are
|
||||
config values rendered as `key=value`. Lists produce repeated keys.
|
||||
|
||||
Booleans render as `0`/`1`. Use `null` with `mkForce` to remove a
|
||||
default.
|
||||
|
||||
See <https://www.raspberrypi.com/documentation/computers/config_txt.html>
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
all = {
|
||||
arm_boost = true;
|
||||
disable_overscan = true;
|
||||
dtparam = [ "audio=on" ];
|
||||
dtoverlay = [ "vc4-kms-v3d" ];
|
||||
};
|
||||
pi5.arm_freq = 2400;
|
||||
cm4.otg_mode = true;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
file = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The generated config.txt content. Defaults to the rendered output of
|
||||
`settings`, but can be overridden to supply a custom config.txt.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
hardware.raspberry-pi.configtxt.file = lib.mkDefault (toConfigTxt cfg.settings);
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue