diff --git a/nixos/lib/systemd-types.nix b/nixos/lib/systemd-types.nix index f3bc8e06d9cb..7b5e3b69dda7 100644 --- a/nixos/lib/systemd-types.nix +++ b/nixos/lib/systemd-types.nix @@ -45,12 +45,35 @@ let inherit (lib.types) attrsOf + coercedTo lines listOf nullOr + oneOf + package path submodule ; + + initrdStorePathModule = { config, ... }: { + options = { + enable = (mkEnableOption "copying of this file and symlinking it") // { default = true; }; + + target = mkOption { + type = nullOr path; + description = '' + Path of the symlink. + ''; + default = null; + }; + + source = mkOption { + type = path; + description = "Path of the source file."; + }; + }; + }; + in { @@ -86,31 +109,23 @@ in automounts = listOf (submodule [ stage2AutomountOptions unitConfig automountConfig ]); initrdAutomounts = attrsOf (submodule [ stage1AutomountOptions unitConfig automountConfig ]); + initrdStorePath = listOf (coercedTo + (oneOf [ singleLineStr package ]) + (source: { inherit source; }) + (submodule initrdStorePathModule)); + initrdContents = attrsOf (submodule ({ config, options, name, ... }: { + imports = [ initrdStorePathModule ]; options = { - enable = (mkEnableOption "copying of this file and symlinking it") // { default = true; }; - - target = mkOption { - type = path; - description = '' - Path of the symlink. - ''; - default = name; - }; - text = mkOption { default = null; type = nullOr lines; description = "Text of the file."; }; - - source = mkOption { - type = path; - description = "Path of the source file."; - }; }; config = { + target = mkDefault name; source = mkIf (config.text != null) ( let name' = "initrd-" + baseNameOf name; in mkDerivedConfig options.text (pkgs.writeText name') diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix index 24b4ba5ecc22..9f813eab2e2d 100644 --- a/nixos/modules/system/boot/systemd/initrd.nix +++ b/nixos/modules/system/boot/systemd/initrd.nix @@ -112,8 +112,7 @@ let inherit (config.boot.initrd) compressor compressorArgs prepend; inherit (cfg) strip; - contents = map (path: { object = path; symlink = ""; }) (subtractLists cfg.suppressedStorePaths cfg.storePaths) - ++ mapAttrsToList (_: v: { object = v.source; symlink = v.target; }) (filterAttrs (_: v: v.enable) cfg.contents); + contents = lib.filter ({ source, ... }: !lib.elem source cfg.suppressedStorePaths) cfg.storePaths; }; in { @@ -172,7 +171,7 @@ in { description = '' Store paths to copy into the initrd as well. ''; - type = with types; listOf (oneOf [ singleLineStr package ]); + type = utils.systemdUtils.types.initrdStorePath; default = []; }; @@ -491,7 +490,8 @@ in { "${pkgs.libfido2}/lib/libfido2.so.1" ] ++ optionals cfg.package.withKmod [ "${pkgs.kmod.lib}/lib/libkmod.so.2" - ] ++ jobScripts; + ] ++ jobScripts + ++ map (c: builtins.removeAttrs c ["text"]) (builtins.attrValues cfg.contents); targets.initrd.aliases = ["default.target"]; units = diff --git a/nixos/modules/system/boot/systemd/shutdown.nix b/nixos/modules/system/boot/systemd/shutdown.nix index 5c2525a57b4b..48477954e20c 100644 --- a/nixos/modules/system/boot/systemd/shutdown.nix +++ b/nixos/modules/system/boot/systemd/shutdown.nix @@ -2,10 +2,7 @@ cfg = config.systemd.shutdownRamfs; - ramfsContents = let - storePaths = map (p: "${p}\n") cfg.storePaths; - contents = lib.mapAttrsToList (_: v: "${v.source}\n${v.target}") (lib.filterAttrs (_: v: v.enable) cfg.contents); - in pkgs.writeText "shutdown-ramfs-contents" (lib.concatStringsSep "\n" (storePaths ++ contents)); + ramfsContents = pkgs.writeText "shutdown-ramfs-contents.json" (builtins.toJSON cfg.storePaths); in { options.systemd.shutdownRamfs = { @@ -24,7 +21,7 @@ in { description = '' Store paths to copy into the shutdown ramfs as well. ''; - type = lib.types.listOf lib.types.singleLineStr; + type = utils.systemdUtils.types.initrdStorePath; default = []; }; }; @@ -35,7 +32,8 @@ in { "/etc/initrd-release".source = config.environment.etc.os-release.source; "/etc/os-release".source = config.environment.etc.os-release.source; }; - systemd.shutdownRamfs.storePaths = [pkgs.runtimeShell "${pkgs.coreutils}/bin"]; + systemd.shutdownRamfs.storePaths = [pkgs.runtimeShell "${pkgs.coreutils}/bin"] + ++ map (c: builtins.removeAttrs c ["text"]) (builtins.attrValues cfg.contents); systemd.mounts = [{ what = "tmpfs"; diff --git a/pkgs/build-support/kernel/make-initrd-ng.nix b/pkgs/build-support/kernel/make-initrd-ng.nix index 65e143cb7349..c70e9cc6dc2e 100644 --- a/pkgs/build-support/kernel/make-initrd-ng.nix +++ b/pkgs/build-support/kernel/make-initrd-ng.nix @@ -72,7 +72,7 @@ in ${if makeUInitrd then "uInitrdCompression" else null} = uInitrdCompression; passAsFile = ["contents"]; - contents = lib.concatMapStringsSep "\n" ({ object, symlink, ... }: "${object}\n${lib.optionalString (symlink != null) symlink}") contents + "\n"; + contents = builtins.toJSON contents; nativeBuildInputs = [makeInitrdNGTool libarchive] ++ lib.optional makeUInitrd ubootTools ++ lib.optional strip binutils; diff --git a/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock b/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock index 61f71f642777..ce5f5ef00971 100644 --- a/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock +++ b/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock @@ -30,10 +30,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] -name = "log" -version = "0.4.20" +name = "itoa" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "make-initrd-ng" @@ -41,6 +47,8 @@ version = "0.1.0" dependencies = [ "eyre", "goblin", + "serde", + "serde_json", ] [[package]] @@ -57,22 +65,28 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "scroll" version = "0.11.0" @@ -94,10 +108,41 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.48" +name = "serde" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", diff --git a/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml b/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml index 028833c12bb5..69081b94d892 100644 --- a/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml +++ b/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml @@ -9,3 +9,5 @@ edition = "2018" [dependencies] eyre = "0.6.8" goblin = "0.5.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/pkgs/build-support/kernel/make-initrd-ng/src/main.rs b/pkgs/build-support/kernel/make-initrd-ng/src/main.rs index daa688976c6c..cb4200214684 100644 --- a/pkgs/build-support/kernel/make-initrd-ng/src/main.rs +++ b/pkgs/build-support/kernel/make-initrd-ng/src/main.rs @@ -3,7 +3,6 @@ use std::env; use std::ffi::{OsStr, OsString}; use std::fs; use std::hash::Hash; -use std::io::{BufRead, BufReader}; use std::iter::FromIterator; use std::os::unix; use std::path::{Component, Path, PathBuf}; @@ -11,6 +10,13 @@ use std::process::Command; use eyre::Context; use goblin::{elf::Elf, Object}; +use serde::Deserialize; + +#[derive(Deserialize, Debug)] +struct StoreInput { + source: String, + target: Option, +} struct NonRepeatingQueue { queue: VecDeque, @@ -231,26 +237,23 @@ fn handle_path( fn main() -> eyre::Result<()> { let args: Vec = env::args().collect(); - let input = - fs::File::open(&args[1]).wrap_err_with(|| format!("failed to open file {:?}", &args[1]))?; + let contents = + fs::read(&args[1]).wrap_err_with(|| format!("failed to open file {:?}", &args[1]))?; + let input = serde_json::from_slice::>(&contents) + .wrap_err_with(|| format!("failed to parse JSON in {:?}", &args[1]))?; let output = &args[2]; let out_path = Path::new(output); let mut queue = NonRepeatingQueue::>::new(); - let mut lines = BufReader::new(input).lines(); - while let Some(obj) = lines.next() { - // Lines should always come in pairs - let obj = obj?; - let sym = lines.next().unwrap()?; - - let obj_path = Path::new(&obj); + for sp in input { + let obj_path = Path::new(&sp.source); queue.push_back(Box::from(obj_path)); - if !sym.is_empty() { - println!("{} -> {}", &sym, &obj); + if let Some(target) = sp.target { + println!("{} -> {}", &target, &sp.source); // We don't care about preserving symlink structure here // nearly as much as for the actual objects. - let link_string = format!("{}/{}", output, sym); + let link_string = format!("{}/{}", output, target); let link_path = Path::new(&link_string); let mut link_parent = link_path.to_path_buf(); link_parent.pop();