mirror of
https://github.com/NixOS/mobile-nixos.git
synced 2025-01-07 12:11:28 +03:00
Merge pull request #488 from samueldr-wip/feature/drop-in-stage-1-integration
Drop-in stage-1 integration [and better support for modular kernels]
This commit is contained in:
commit
271b9106ae
@ -80,6 +80,17 @@ module Mounting
|
||||
Tasks::Luks.new(info["device"], mapper)
|
||||
end
|
||||
end
|
||||
|
||||
def self.mountpoint?(path)
|
||||
begin
|
||||
parent_path = File.dirname(path)
|
||||
mp_stat = File.lstat(path)
|
||||
pa_stat = File.lstat(parent_path)
|
||||
mp_stat.dev == pa_stat.dev && mp_stat.ino == pa_stat.ino || mp_stat.dev != pa_stat.dev
|
||||
rescue Errno::ENOENT
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -77,10 +77,13 @@ module System
|
||||
|
||||
# Discovers the location of given program name.
|
||||
def self.which(program_name)
|
||||
ENV["PATH"].split(":").each do |path|
|
||||
(ENV["PATH"] or "").split(":").each do |path|
|
||||
full = File.join(path, program_name)
|
||||
return full if File.stat(full).executable? && !File.directory?(full)
|
||||
if File.exists?(full) && !File.directory?(full) && File.stat(full).executable? then
|
||||
return full
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def self.write(file, contents)
|
||||
@ -178,6 +181,13 @@ module System
|
||||
args << source
|
||||
args << dest
|
||||
|
||||
# The kernel module for the filesystem may need to be probed.
|
||||
begin
|
||||
System.run("modprobe", type)
|
||||
rescue System::CommandError
|
||||
$logger.warn("Kernel filesystem module “#{type}” failed to load.")
|
||||
end
|
||||
|
||||
# We may have some mountpoints already mounted from, e.g. early logging in
|
||||
# /run/log... If we're not careful we will mount over the existing mount
|
||||
# point and hide the resulting files.
|
||||
|
@ -72,7 +72,7 @@ module Tasks
|
||||
# to be ran.
|
||||
# Serves nothing to point to tasks depending on other tasks.
|
||||
failed_tasks = todo.reject(&:depends_on_any_unfulfilled_task?)
|
||||
failed_dependencies = failed_tasks.map(&:dependencies).inject(:+).uniq
|
||||
failed_dependencies = failed_tasks.map(&:dependencies).inject(:+).uniq.reject(&:fulfilled?)
|
||||
|
||||
if elapsed > HUNG_BOOT_NOTIFICATION
|
||||
label = "#{failed_tasks.length} tasks are waiting on #{failed_dependencies.length} unique dependencies.\n\n" +
|
||||
@ -82,15 +82,22 @@ module Tasks
|
||||
end
|
||||
|
||||
if elapsed > HUNG_BOOT_TIMEOUT
|
||||
# Building this message is not pretty!
|
||||
msg =
|
||||
msg = [
|
||||
"",
|
||||
"#{failed_tasks.length} #{if failed_tasks.length == 1 then "task" else "tasks" end} " +
|
||||
"did not run within #{HUNG_BOOT_TIMEOUT} seconds.\n" +
|
||||
"\n" +
|
||||
"did not run within #{HUNG_BOOT_TIMEOUT} seconds.\n",
|
||||
"#{failed_dependencies.length} #{if failed_dependencies.length == 1 then "dependency" else "dependencies" end} " +
|
||||
"could not resolve:\n" +
|
||||
failed_dependencies.map(&:pretty_name).join("\n") +
|
||||
"\n"
|
||||
"could not resolve:\n",
|
||||
failed_tasks.map do |task|
|
||||
[
|
||||
" - #{task.name}",
|
||||
task.dependencies.map do |dep|
|
||||
" - #{dep.pretty_name} [#{if dep.fulfilled? then "ok" else " " end}]"
|
||||
end.join("\n")
|
||||
].join("\n")
|
||||
end.join("\n"),
|
||||
""
|
||||
].join("\n")
|
||||
|
||||
# Fail with a black backdrop, and force the message to stay up 60s
|
||||
System.failure("TASKS_HANG_TIMEOUT", "Hung Tasks", msg, color: "000000", delay: 60)
|
||||
|
@ -31,6 +31,12 @@ class Tasks::Luks < Task
|
||||
add_dependency(:Devices, source)
|
||||
add_dependency(:Mount, "/run")
|
||||
add_dependency(:Target, :Environment)
|
||||
# Or else we can't get the passphrase!!
|
||||
# TODO: instead of depending on the Splash Task, depend on a new type of
|
||||
# dependency describing a "user input", which would be provided on
|
||||
# the "message bus"
|
||||
# e.g. `add_dependency(:Ask, :passphrase, "Passphrase for #{mapper}")`
|
||||
add_dependency(:Task, Tasks::Splash.instance)
|
||||
self.class.register(@mapper, self)
|
||||
end
|
||||
|
||||
|
@ -3,10 +3,14 @@ class Tasks::Modules < Task
|
||||
def initialize(*modules)
|
||||
add_dependency(:Files, MODULES_PATH)
|
||||
add_dependency(:Target, :Environment)
|
||||
add_dependency(:Mount, "/proc")
|
||||
# May be required for input or display modules
|
||||
Targets[:Graphics].add_dependency(:Task, self)
|
||||
@modules = modules
|
||||
end
|
||||
|
||||
def run()
|
||||
System.write("/proc/sys/kernel/modprobe", System.which("modprobe"))
|
||||
@modules.each do |mod|
|
||||
begin
|
||||
System.run("modprobe", mod)
|
||||
|
@ -52,6 +52,19 @@ class Tasks::Mount < Task
|
||||
@named[:type]
|
||||
end
|
||||
|
||||
def refresh_lvm()
|
||||
unless System.which("lvm").nil? then
|
||||
begin
|
||||
ENV["LVM_SUPPRESS_FD_WARNINGS"] = "1"
|
||||
System.run("lvm", "vgchange", "--activate=y")
|
||||
ENV["LVM_SUPPRESS_FD_WARNINGS"] = nil
|
||||
System.run("udevadm", "trigger", "--action=add")
|
||||
rescue System::CommandError => e
|
||||
$logger.info(e.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def name()
|
||||
"#{super}(#{source}, #{mount_point}, #{@named.inspect})"
|
||||
end
|
||||
@ -67,7 +80,15 @@ module Dependencies
|
||||
unless task
|
||||
$logger.warn("Missing Mount task for mount point #{@mount_point}")
|
||||
end
|
||||
task && task.ran
|
||||
|
||||
# Already mounted?
|
||||
# (Could be e.g. mounted beforehand or mounted by the kernel implicitly)
|
||||
return true if Mounting.mountpoint?(@mount_point)
|
||||
|
||||
if task
|
||||
task.refresh_lvm
|
||||
task.ran
|
||||
end
|
||||
end
|
||||
|
||||
def depends_on?(other)
|
||||
|
@ -28,6 +28,9 @@ class Tasks::Splash < SingletonTask
|
||||
|
||||
# Implementation details-y; ask for the splash applet to be exited.
|
||||
def quit(reason, sticky: nil)
|
||||
return if @pid.nil?
|
||||
|
||||
count = 0
|
||||
# Ensures the progress is shown
|
||||
Progress.update({progress: 100, label: reason})
|
||||
|
||||
@ -44,6 +47,12 @@ class Tasks::Splash < SingletonTask
|
||||
|
||||
# Leave some breathing room to the CPU!
|
||||
sleep(0.1)
|
||||
count += 1
|
||||
if count > 60 # 10 seconds~ish
|
||||
$logger.fatal("Splash applet would not quit by itself...")
|
||||
kill
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
@pid = nil
|
||||
|
@ -6,6 +6,7 @@ class Tasks::SwitchRoot < SingletonTask
|
||||
SYSTEM_MOUNT_POINT = "/mnt"
|
||||
|
||||
def initialize()
|
||||
add_dependency(:Task, Tasks::Splash.instance)
|
||||
add_dependency(:Target, :SwitchRoot)
|
||||
@target = SYSTEM_MOUNT_POINT
|
||||
end
|
||||
@ -92,6 +93,13 @@ class Tasks::SwitchRoot < SingletonTask
|
||||
return generation_parameter.split("=", 2).last
|
||||
end
|
||||
|
||||
# Given as a command-line option, from the bootloader (replacement for NixOS's stage-1)
|
||||
init_parameter = System.cmdline().grep(/^init=/).first
|
||||
unless init_parameter.nil?
|
||||
init_parameter = init_parameter.split("=", 2).last
|
||||
return init_parameter.rpartition("/").first
|
||||
end
|
||||
|
||||
# The default generation
|
||||
if File.symlink?(File.join(@target, DEFAULT_SYSTEM_LINK))
|
||||
return DEFAULT_SYSTEM_LINK
|
||||
|
@ -11,6 +11,9 @@ class Tasks::UDev < SingletonTask
|
||||
# It is preferred to depend on the specific device rather than this target.
|
||||
Targets[:Devices].add_dependency(:Task, self)
|
||||
Targets[:SwitchRoot].add_dependency(:Task, self)
|
||||
|
||||
# May be required for input
|
||||
Targets[:Graphics].add_dependency(:Task, self)
|
||||
end
|
||||
|
||||
def udevadm(*args)
|
||||
|
@ -17,27 +17,21 @@
|
||||
};
|
||||
|
||||
boot.kernelParams = [
|
||||
"vt.global_cursor_default=0"
|
||||
"fbcon=vc:2-6"
|
||||
"console=tty0"
|
||||
];
|
||||
|
||||
mobile.system.type = "uefi";
|
||||
|
||||
mobile.boot.stage-1 = {
|
||||
kernel = {
|
||||
package = let inherit (pkgs.linuxPackages_5_4) kernel; in
|
||||
kernel.overrideAttrs({passthru ? {}, ...}: {
|
||||
# Using `kernel.passthru` as overrideAttrs on kernel derivations
|
||||
# does not work as expected.
|
||||
# See https://github.com/NixOS/nixpkgs/issues/111504
|
||||
passthru = kernel.passthru // {
|
||||
file = "bzImage";
|
||||
};
|
||||
})
|
||||
;
|
||||
modular = true;
|
||||
# Rely on upstream NixOS modules by default for generic UEFI systems.
|
||||
useNixOSKernel = lib.mkDefault true;
|
||||
|
||||
# Sync with <nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-base.nix>
|
||||
# and with <nixpkgs/nixos/modules/system/boot/kernel.nix>
|
||||
modules = [
|
||||
# FIXME: enable only when building generic images (e.g. USB images)
|
||||
additionalModules = [
|
||||
# Some SATA/PATA stuff.
|
||||
"ahci"
|
||||
"sata_nv"
|
||||
@ -119,5 +113,5 @@
|
||||
};
|
||||
};
|
||||
|
||||
mobile.quirks.supportsStage-0 = true;
|
||||
mobile.quirks.supportsStage-0 = lib.mkDefault true;
|
||||
}
|
||||
|
@ -129,4 +129,7 @@ in
|
||||
# It's only noise, and the current stage-0 is not able to boot anything else
|
||||
# than a system it was built for anyway.
|
||||
mobile.quirks.supportsStage-0 = lib.mkForce false;
|
||||
|
||||
# Skip a long-running build for the documentation HTML.
|
||||
documentation.enable = false;
|
||||
}
|
||||
|
22
examples/testing/nixos-integration/configuration.nix
Normal file
22
examples/testing/nixos-integration/configuration.nix
Normal file
@ -0,0 +1,22 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
# This system is not expected to be bootable.
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "tmpfs";
|
||||
fsType = "tmpfs";
|
||||
};
|
||||
};
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = false;
|
||||
|
||||
# Documentation build will be different, so comparing `toplevel` would fail.
|
||||
# Different why? New options!
|
||||
documentation.enable = lib.mkOverride 10 false;
|
||||
|
||||
# Unimportant, but keeps the eval log cleaner.
|
||||
system.stateVersion = "22.05";
|
||||
|
||||
# ¯\_(ツ)_/¯
|
||||
services.getty.autologinUser = "root";
|
||||
}
|
52
examples/testing/nixos-integration/default.nix
Normal file
52
examples/testing/nixos-integration/default.nix
Normal file
@ -0,0 +1,52 @@
|
||||
{ pkgs ? (import ../../../pkgs.nix {})
|
||||
}@args':
|
||||
let args = args' // { inherit pkgs; }; in
|
||||
|
||||
let
|
||||
eval = configuration: import (pkgs.path + "/nixos") {
|
||||
configuration = {
|
||||
imports = [ configuration ];
|
||||
};
|
||||
};
|
||||
|
||||
# A "clean" NixOS eval
|
||||
nixos-eval = eval {
|
||||
imports = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
# A Mobile NixOS eval that should be a no-op
|
||||
mobile-nixos-eval = eval {
|
||||
imports = [
|
||||
./configuration.nix
|
||||
(import ../../../lib/configuration.nix { })
|
||||
];
|
||||
mobile.enable = false;
|
||||
};
|
||||
# A Mobile NixOS eval that should be a no-op
|
||||
mobile-nixos-stage-1-eval = eval {
|
||||
imports = [
|
||||
./configuration.nix
|
||||
(import ../../../lib/configuration.nix { })
|
||||
];
|
||||
mobile.enable = false;
|
||||
mobile.boot.stage-1.enable = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit
|
||||
nixos-eval
|
||||
mobile-nixos-eval
|
||||
mobile-nixos-stage-1-eval
|
||||
;
|
||||
|
||||
# Use this output to check that the product works as expected.
|
||||
# (The bogus rootfs will be overriden by the VM config.)
|
||||
default =
|
||||
assert nixos-eval.config.system.build.toplevel == mobile-nixos-eval.config.system.build.toplevel;
|
||||
assert nixos-eval.config.system.build.vm == mobile-nixos-eval.config.system.build.vm;
|
||||
mobile-nixos-eval.config.system.build.vm
|
||||
;
|
||||
|
||||
mobile-nixos-stage-1 = mobile-nixos-stage-1-eval.config.system.build.vm;
|
||||
}
|
8
examples/testing/nixos-integration/diff.sh
Executable file
8
examples/testing/nixos-integration/diff.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -p nix-diff -i bash
|
||||
|
||||
this_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"
|
||||
|
||||
nix-diff \
|
||||
"$(nix-instantiate "$this_dir"/default.nix -A nixos-eval.config.system.build.toplevel)" \
|
||||
"$(nix-instantiate "$this_dir"/default.nix -A mobile-nixos-eval.config.system.build.toplevel)"
|
@ -12,11 +12,15 @@
|
||||
# }
|
||||
# ```
|
||||
|
||||
{ device }:
|
||||
{ device ? null }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(import (../devices + "/${device}"))
|
||||
]
|
||||
++ import ../modules/module-list.nix;
|
||||
imports =
|
||||
(
|
||||
if device == null
|
||||
then []
|
||||
else [ (import (../devices + "/${device}")) ]
|
||||
)
|
||||
++ import ../modules/module-list.nix
|
||||
;
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
# This module, while seemingly having a funny name, has a truthful name.
|
||||
# It dis(assembles) the integration within the NixOS module system that is
|
||||
# causing issues for mobile-nixos.
|
||||
#
|
||||
# In reality, all fixups made here is a call for a better isolation of the
|
||||
# modules they target. Let's wait until this is more stable, and add required
|
||||
# fixes to the NixOS modules system as needed ☺.
|
||||
|
||||
{lib, config, ...}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./initrd.nix
|
||||
];
|
||||
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
# I don't know why, but the documentation has issues with the
|
||||
# soc options when building other than qemu_x86_64
|
||||
# And here the installation-device profile is a bit annoying.
|
||||
# Let's ultra-diable the documentation and nixos manual.
|
||||
documentation.enable = lib.mkOverride 10 false;
|
||||
}
|
||||
];
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
{ pkgs, lib, config, ... }:
|
||||
|
||||
let
|
||||
dummy = pkgs.runCommandNoCC "dummy" {} "touch $out";
|
||||
in
|
||||
{
|
||||
disabledModules = [
|
||||
"tasks/encrypted-devices.nix"
|
||||
"tasks/filesystems/zfs.nix"
|
||||
];
|
||||
|
||||
config = {
|
||||
# This isn't even used in our initrd...
|
||||
boot.supportedFilesystems = lib.mkOverride 10 [ ];
|
||||
boot.initrd.supportedFilesystems = lib.mkOverride 10 [];
|
||||
|
||||
# And disable the initrd outright!
|
||||
boot.initrd.enable = false;
|
||||
system.build.initialRamdiskSecretAppender = dummy;
|
||||
};
|
||||
}
|
35
modules/bootloader.nix
Normal file
35
modules/bootloader.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (config.boot) growPartition;
|
||||
inherit (lib) mkIf mkOption optionalString types;
|
||||
inherit (config.mobile._internal) compressLargeArtifacts;
|
||||
inherit (pkgs) buildPackages;
|
||||
rootfsLabel = config.mobile.generatedFilesystems.rootfs.label;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
mobile = {
|
||||
bootloader = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = config.mobile.enable;
|
||||
description = ''
|
||||
Whether the bootloader **configuration** for Mobile NixOS
|
||||
is enabled.
|
||||
|
||||
Installation and management of the Mobile NixOS bootloading
|
||||
components is not implemented at this point in time.
|
||||
(e.g. flashing boot.img on android, boot partition on other systems.)
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (config.mobile.bootloader.enable) {
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = false;
|
||||
};
|
||||
}
|
||||
|
@ -14,4 +14,7 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
documentation.nixos.options.splitBuild = false;
|
||||
};
|
||||
}
|
||||
|
@ -9,9 +9,15 @@ in
|
||||
options.mobile.hardware.screen = {
|
||||
width = mkOption {
|
||||
type = types.int;
|
||||
description = ''
|
||||
Width of the device's display.
|
||||
'';
|
||||
};
|
||||
height = mkOption {
|
||||
type = types.int;
|
||||
description = ''
|
||||
Height of the device's display.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
inherit (lib) mkIf mkOption mkOptionDefault types;
|
||||
cfg = config.mobile.hardware;
|
||||
in
|
||||
{
|
||||
@ -20,5 +20,14 @@ in
|
||||
{ assertion = cfg.socs ? ${cfg.soc}; message = "Cannot enable SOC ${cfg.soc}; it is unknown.";}
|
||||
];
|
||||
mobile.hardware.socs."${cfg.soc}".enable = true;
|
||||
|
||||
# When evaluating with the Mobile NixOS defaults disabled, we want
|
||||
# to use the a generic type so evaluation can continue.
|
||||
# Otherwise we want to error on an unset value if not set.
|
||||
mobile.hardware.soc = mkIf (!config.mobile.enable) (
|
||||
mkOptionDefault (
|
||||
"generic-${config.nixpkgs.localSystem.parsed.cpu.name}"
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@ -3,10 +3,13 @@
|
||||
let
|
||||
|
||||
inherit (lib)
|
||||
literalExpression
|
||||
mergeEqualOption
|
||||
mkDefault
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
mkOverride
|
||||
types
|
||||
;
|
||||
cfg = config.mobile.boot.stage-1.kernel;
|
||||
@ -14,9 +17,9 @@ let
|
||||
|
||||
modulesClosure = pkgs.makeModulesClosure {
|
||||
kernel = cfg.package;
|
||||
allowMissing = true;
|
||||
allowMissing = cfg.allowMissingModules;
|
||||
rootModules = cfg.modules ++ cfg.additionalModules;
|
||||
firmware = cfg.firmwares;
|
||||
firmware = config.hardware.firmware;
|
||||
};
|
||||
|
||||
inherit (config.mobile.quirks) supportsStage-0;
|
||||
@ -25,6 +28,16 @@ in
|
||||
# Note: These options are provided *instead* of `boot.initrd.*`, as we are
|
||||
# not re-using the `initrd` options.
|
||||
options.mobile.boot.stage-1.kernel = {
|
||||
useNixOSKernel = mkOption {
|
||||
type = types.bool;
|
||||
default = !config.mobile.enable;
|
||||
defaultText = literalExpression "!config.mobile.enable";
|
||||
description = ''
|
||||
Whether Mobile NixOS relies on upstream NixOS settings for kernel config.
|
||||
|
||||
Enable this when using the NixOS machinery for kernels.
|
||||
'';
|
||||
};
|
||||
modular = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@ -52,11 +65,11 @@ in
|
||||
They will not be modprobed.
|
||||
'';
|
||||
};
|
||||
firmwares = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
allowMissingModules = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Firmwares to add to the closure.
|
||||
Chooses whether the modules closure build fails if a module is missing.
|
||||
'';
|
||||
};
|
||||
# We cannot use `linuxPackagesFor` as older kernels cause eval-time assertions...
|
||||
@ -73,50 +86,94 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config.mobile.boot.stage-1 = (mkIf cfg.modular {
|
||||
firmware = [ modulesClosure ];
|
||||
contents = [
|
||||
{ object = "${modulesClosure}/lib/modules"; symlink = "/lib/modules"; }
|
||||
];
|
||||
kernel.modules = [
|
||||
# Basic always-needed kernel modules.
|
||||
"loop"
|
||||
config = mkMerge [
|
||||
# This can always be configured, as it does not affect the NixOS configuration.
|
||||
{
|
||||
mobile.boot.stage-1 = (mkIf cfg.modular {
|
||||
firmware = [ modulesClosure ];
|
||||
contents = [
|
||||
{ object = "${modulesClosure}/lib/modules"; symlink = "/lib/modules"; }
|
||||
];
|
||||
kernel.modules = [
|
||||
# Basic always-needed kernel modules.
|
||||
"loop"
|
||||
"uinput"
|
||||
"evdev"
|
||||
];
|
||||
kernel.additionalModules = [
|
||||
# Filesystems
|
||||
"nls_cp437"
|
||||
"nls_iso8859-1"
|
||||
"fat"
|
||||
"vfat"
|
||||
|
||||
# Filesystems
|
||||
"nls_cp437"
|
||||
"nls_iso8859-1"
|
||||
"fat"
|
||||
"vfat"
|
||||
"ext4"
|
||||
"crc32c"
|
||||
];
|
||||
});
|
||||
}
|
||||
{
|
||||
mobile.boot.stage-1 = (mkIf (!cfg.modular) {
|
||||
contents = [
|
||||
# Link an empty `/lib/modules` for the Modules task.
|
||||
# This is better than implementing conditional loading of the task
|
||||
# as the task is now always exercised.
|
||||
{
|
||||
object =
|
||||
let
|
||||
nullModules = pkgs.callPackage (
|
||||
{ runCommandNoCC, ... }:
|
||||
runCommandNoCC "null-modules" { } ''
|
||||
mkdir -p $out/lib/modules
|
||||
''
|
||||
) {};
|
||||
in
|
||||
"${nullModules}/lib/modules"
|
||||
;
|
||||
symlink = "/lib/modules";
|
||||
}
|
||||
];
|
||||
});
|
||||
}
|
||||
# Options affecting the NixOS configuration
|
||||
(mkIf (!cfg.useNixOSKernel) {
|
||||
boot.kernelPackages = mkDefault (
|
||||
if (supportsStage-0 && config.mobile.rootfs.shared.enabled) || cfg.package == null
|
||||
then let
|
||||
self = {
|
||||
# This must look legit enough so that NixOS thinks it's a kernel attrset.
|
||||
stdenv = pkgs.stdenv;
|
||||
# callPackage so that override / overrideAttrs exist.
|
||||
kernel = pkgs.callPackage (
|
||||
{ runCommandNoCC, ... }: runCommandNoCC "null-kernel" { version = "99"; } "mkdir $out; touch $out/'<no-kernel>'"
|
||||
) {};
|
||||
# Fake having `extend` available... probably dumb... but is it more
|
||||
# dumb than faking a kernelPackages package set for eval??
|
||||
extend = _: self;
|
||||
};
|
||||
in self
|
||||
else (pkgs.recurseIntoAttrs (pkgs.linuxPackagesFor cfg.package))
|
||||
);
|
||||
|
||||
"ext4"
|
||||
"crc32c"
|
||||
];
|
||||
});
|
||||
system.boot.loader.kernelFile = mkIf (cfg.package != null && cfg.package ? file) (
|
||||
mkDefault cfg.package.file
|
||||
);
|
||||
|
||||
config.boot.kernelPackages = mkDefault (
|
||||
if (supportsStage-0 && config.mobile.rootfs.shared.enabled) || cfg.package == null
|
||||
then let
|
||||
self = {
|
||||
# This must look legit enough so that NixOS thinks it's a kernel attrset.
|
||||
stdenv = pkgs.stdenv;
|
||||
# callPackage so that override / overrideAttrs exist.
|
||||
kernel = pkgs.callPackage (
|
||||
{ runCommandNoCC, ... }: runCommandNoCC "dummy" { version = "99"; } "mkdir $out; touch $out/dummy"
|
||||
) {};
|
||||
# Fake having `extend` available... probably dumb... but is it more
|
||||
# dumb than faking a kernelPackages package set for eval??
|
||||
extend = _: self;
|
||||
# Disable kernel config checks as it's EXTREMELY nixpkgs-kernel centric.
|
||||
# We're duplicating that good work for the time being.
|
||||
system.requiredKernelConfig = lib.mkForce [];
|
||||
})
|
||||
(mkIf (cfg.useNixOSKernel) {
|
||||
mobile.boot.stage-1 = {
|
||||
kernel = {
|
||||
package = config.boot.kernelPackages.kernel;
|
||||
modular = true;
|
||||
# Use the modules described by the NixOS config.
|
||||
modules = config.boot.initrd.kernelModules ++ [ "uinput" "evdev" ];
|
||||
additionalModules = config.boot.initrd.availableKernelModules;
|
||||
};
|
||||
};
|
||||
in self
|
||||
else (pkgs.recurseIntoAttrs (pkgs.linuxPackagesFor cfg.package))
|
||||
);
|
||||
|
||||
config.system.boot.loader.kernelFile = mkIf (cfg.package != null && cfg.package ? file) (
|
||||
mkDefault cfg.package.file
|
||||
);
|
||||
|
||||
# Disable kernel config checks as it's EXTREMELY nixpkgs-kernel centric.
|
||||
# We're duplicating that good work for the time being.
|
||||
config.system.requiredKernelConfig = lib.mkForce [];
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ in
|
||||
options.mobile.boot.stage-1.bootlog = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
default = config.mobile.boot.stage-1.enable;
|
||||
description = ''
|
||||
Enables bootlogd logging multiplexer.
|
||||
'';
|
||||
|
@ -46,8 +46,8 @@ let
|
||||
# TODO: define as an option
|
||||
withStrace = false;
|
||||
|
||||
device_config = config.mobile.device;
|
||||
device_name = device_config.name;
|
||||
inherit (config.mobile) device;
|
||||
device_name = device.name;
|
||||
|
||||
stage-1 = config.mobile.boot.stage-1;
|
||||
|
||||
@ -193,7 +193,7 @@ let
|
||||
};
|
||||
|
||||
initrd = makeInitrd {
|
||||
name = "initrd-${device_config.name}";
|
||||
name = "mobile-nixos-initrd-${device_name}";
|
||||
inherit contents;
|
||||
|
||||
compressor = {
|
||||
@ -207,7 +207,7 @@ let
|
||||
};
|
||||
|
||||
# ncdu -f result/initrd.ncdu
|
||||
initrd-meta = pkgs.runCommandNoCC "initrd-${device_config.name}-meta" {
|
||||
initrd-meta = pkgs.runCommandNoCC "initrd-${device_name}-meta" {
|
||||
nativeBuildInputs = with pkgs.buildPackages; [
|
||||
ncdu
|
||||
cpio
|
||||
@ -230,6 +230,16 @@ let
|
||||
in
|
||||
{
|
||||
options = {
|
||||
mobile.boot.stage-1.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = config.mobile.enable;
|
||||
description = ''
|
||||
Whether to use the Mobile NixOS stage-1 implementation or not.
|
||||
|
||||
This will forcible override the NixOS stage-1 when enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
mobile.boot.stage-1.stage = mkOption {
|
||||
type = types.enum [ 0 1 ];
|
||||
default = 1;
|
||||
@ -337,7 +347,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
config = mkIf config.mobile.boot.stage-1.enable {
|
||||
boot.initrd.enable = false;
|
||||
|
||||
# This isn't even used in our initrd...
|
||||
boot.supportedFilesystems = lib.mkOverride 10 [ ];
|
||||
boot.initrd.supportedFilesystems = lib.mkOverride 10 [];
|
||||
|
||||
system.build.initialRamdiskSecretAppender =
|
||||
pkgs.runCommandNoCC "noopRamdiskSecretAppender" {} "touch $out"
|
||||
;
|
||||
|
||||
mobile.outputs = {
|
||||
inherit
|
||||
extraUtils
|
||||
@ -350,14 +370,14 @@ in
|
||||
# default NixOS outputs. Do not refer to this in Mobile NixOS.
|
||||
system.build.initialRamdisk =
|
||||
if config.mobile.rootfs.shared.enabled
|
||||
then pkgs.runCommandNoCC "dummy" {} "touch $out"
|
||||
then pkgs.runCommandNoCC "nullInitialRamdisk" {} "touch $out"
|
||||
else initrd
|
||||
;
|
||||
|
||||
mobile.boot.stage-1.bootConfig = {
|
||||
inherit (config.mobile.boot.stage-1) stage;
|
||||
device = {
|
||||
inherit (device_config) name;
|
||||
name = device_name;
|
||||
};
|
||||
kernel = {
|
||||
inherit (config.mobile.boot.stage-1.kernel) modules;
|
||||
|
@ -36,4 +36,10 @@ with lib;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (!config.mobile.enable) {
|
||||
mobile.device.name = mkOptionDefault "generic";
|
||||
mobile.device.identity.name = mkOptionDefault "generic";
|
||||
mobile.device.identity.manufacturer = mkOptionDefault "generic";
|
||||
};
|
||||
}
|
||||
|
22
modules/mobile.nix
Normal file
22
modules/mobile.nix
Normal file
@ -0,0 +1,22 @@
|
||||
{ lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
mobile = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
When this setting is set to false, including Mobile
|
||||
NixOS in your NixOS configuration should be a no-op.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
# Then add our additional modules.
|
||||
# Keep this list `:sort`ed.
|
||||
[
|
||||
./_nixos-disintegration
|
||||
./adb.nix
|
||||
./boot-initrd.nix
|
||||
./bootloader.nix
|
||||
./cross-workarounds.nix
|
||||
./devices-metadata.nix
|
||||
./documentation.nix
|
||||
@ -35,6 +35,7 @@
|
||||
./kernel-config.nix
|
||||
./lib.nix
|
||||
./luks.nix
|
||||
./mobile.nix
|
||||
./mobile-device.nix
|
||||
./nixpkgs.nix
|
||||
./outputs.nix
|
||||
|
@ -4,90 +4,103 @@
|
||||
|
||||
let
|
||||
inherit (config.boot) growPartition;
|
||||
inherit (lib) optionalString types;
|
||||
inherit (lib) mkIf mkOption optionalString types;
|
||||
inherit (config.mobile._internal) compressLargeArtifacts;
|
||||
inherit (pkgs) buildPackages;
|
||||
rootfsLabel = config.mobile.generatedFilesystems.rootfs.label;
|
||||
in
|
||||
{
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = false;
|
||||
|
||||
boot.growPartition = lib.mkDefault true;
|
||||
|
||||
mobile.generatedFilesystems.rootfs = lib.mkDefault {
|
||||
type = "ext4";
|
||||
label = "NIXOS_SYSTEM";
|
||||
id = "44444444-4444-4444-8888-888888888888";
|
||||
|
||||
populateCommands =
|
||||
let
|
||||
closureInfo = pkgs.buildPackages.closureInfo { rootPaths = config.system.build.toplevel; };
|
||||
in
|
||||
''
|
||||
mkdir -p ./nix/store
|
||||
echo "Copying system closure..."
|
||||
while IFS= read -r path; do
|
||||
echo " Copying $path"
|
||||
cp -prf "$path" ./nix/store
|
||||
done < "${closureInfo}/store-paths"
|
||||
echo "Done copying system closure..."
|
||||
cp -v ${closureInfo}/registration ./nix-path-registration
|
||||
'';
|
||||
|
||||
# Give some headroom for initial mounting.
|
||||
extraPadding = pkgs.imageBuilder.size.MiB 20;
|
||||
|
||||
# FIXME: See #117, move compression into the image builder.
|
||||
# Zstd can take a long time to complete successfully at high compression
|
||||
# levels. Increasing the compression level could lead to timeouts.
|
||||
postProcess = optionalString compressLargeArtifacts ''
|
||||
(PS4=" $ "; set -x
|
||||
PATH="$PATH:${buildPackages.zstd}/bin"
|
||||
cd $out
|
||||
ls -lh
|
||||
time zstd -10 --rm "$filename"
|
||||
ls -lh
|
||||
)
|
||||
'' + ''
|
||||
(PS4=" $ "; set -x
|
||||
mkdir $out/nix-support
|
||||
cat <<EOF > $out/nix-support/hydra-build-products
|
||||
file rootfs${optionalString compressLargeArtifacts "-zstd"} $out/$filename${optionalString compressLargeArtifacts ".zst"}
|
||||
EOF
|
||||
)
|
||||
'';
|
||||
|
||||
zstd = compressLargeArtifacts;
|
||||
};
|
||||
|
||||
boot.postBootCommands = ''
|
||||
# On the first boot do some maintenance tasks
|
||||
if [ -f /nix-path-registration ]; then
|
||||
# Register the contents of the initial Nix store
|
||||
${config.nix.package.out}/bin/nix-store --load-db < /nix-path-registration
|
||||
|
||||
# nixos-rebuild also requires a "system" profile and an /etc/NIXOS tag.
|
||||
touch /etc/NIXOS
|
||||
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
||||
|
||||
# Prevents this from running on later boots.
|
||||
rm -f /nix-path-registration
|
||||
fi
|
||||
'';
|
||||
|
||||
fileSystems = {
|
||||
"/" = lib.mkDefault {
|
||||
device = "/dev/disk/by-label/${rootfsLabel}";
|
||||
fsType = "ext4";
|
||||
autoResize = true;
|
||||
options = {
|
||||
mobile = {
|
||||
rootfs = {
|
||||
enableDefaultConfiguration = mkOption {
|
||||
type = types.bool;
|
||||
default = config.mobile.enable;
|
||||
description = ''
|
||||
Whether some of the rootfs configuration is managed by Mobile NixOS or not.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# FIXME: Move this in a proper module + task for the filesystem.
|
||||
# This is a "wrong" assumption, that only holds through since we are setting
|
||||
# fileSystems."/".autoResize to true here.
|
||||
mobile.boot.stage-1.extraUtils = with pkgs; [
|
||||
{ package = e2fsprogs; }
|
||||
];
|
||||
config = mkIf (config.mobile.rootfs.enableDefaultConfiguration) {
|
||||
boot.growPartition = lib.mkDefault true;
|
||||
|
||||
mobile.generatedFilesystems.rootfs = lib.mkDefault {
|
||||
type = "ext4";
|
||||
label = "NIXOS_SYSTEM";
|
||||
id = "44444444-4444-4444-8888-888888888888";
|
||||
|
||||
populateCommands =
|
||||
let
|
||||
closureInfo = pkgs.buildPackages.closureInfo { rootPaths = config.system.build.toplevel; };
|
||||
in
|
||||
''
|
||||
mkdir -p ./nix/store
|
||||
echo "Copying system closure..."
|
||||
while IFS= read -r path; do
|
||||
echo " Copying $path"
|
||||
cp -prf "$path" ./nix/store
|
||||
done < "${closureInfo}/store-paths"
|
||||
echo "Done copying system closure..."
|
||||
cp -v ${closureInfo}/registration ./nix-path-registration
|
||||
'';
|
||||
|
||||
# Give some headroom for initial mounting.
|
||||
extraPadding = pkgs.imageBuilder.size.MiB 20;
|
||||
|
||||
# FIXME: See #117, move compression into the image builder.
|
||||
# Zstd can take a long time to complete successfully at high compression
|
||||
# levels. Increasing the compression level could lead to timeouts.
|
||||
postProcess = optionalString compressLargeArtifacts ''
|
||||
(PS4=" $ "; set -x
|
||||
PATH="$PATH:${buildPackages.zstd}/bin"
|
||||
cd $out
|
||||
ls -lh
|
||||
time zstd -10 --rm "$filename"
|
||||
ls -lh
|
||||
)
|
||||
'' + ''
|
||||
(PS4=" $ "; set -x
|
||||
mkdir $out/nix-support
|
||||
cat <<EOF > $out/nix-support/hydra-build-products
|
||||
file rootfs${optionalString compressLargeArtifacts "-zstd"} $out/$filename${optionalString compressLargeArtifacts ".zst"}
|
||||
EOF
|
||||
)
|
||||
'';
|
||||
|
||||
zstd = compressLargeArtifacts;
|
||||
};
|
||||
|
||||
boot.postBootCommands = ''
|
||||
# On the first boot do some maintenance tasks
|
||||
if [ -f /nix-path-registration ]; then
|
||||
# Register the contents of the initial Nix store
|
||||
${config.nix.package.out}/bin/nix-store --load-db < /nix-path-registration
|
||||
|
||||
# nixos-rebuild also requires a "system" profile and an /etc/NIXOS tag.
|
||||
touch /etc/NIXOS
|
||||
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
||||
|
||||
# Prevents this from running on later boots.
|
||||
rm -f /nix-path-registration
|
||||
fi
|
||||
'';
|
||||
|
||||
fileSystems = {
|
||||
"/" = lib.mkDefault {
|
||||
device = "/dev/disk/by-label/${rootfsLabel}";
|
||||
fsType = "ext4";
|
||||
autoResize = true;
|
||||
};
|
||||
};
|
||||
|
||||
# FIXME: Move this in a proper module + task for the filesystem.
|
||||
# This is a "wrong" assumption, that only holds through since we are setting
|
||||
# fileSystems."/".autoResize to true here.
|
||||
mobile.boot.stage-1.extraUtils = with pkgs; [
|
||||
{ package = e2fsprogs; }
|
||||
];
|
||||
};
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ in
|
||||
|
||||
config = mkIf enabled {
|
||||
# Ensure we don't bring a kernel or initrd into the system.
|
||||
system.boot.loader.kernelFile = "dummy";
|
||||
system.boot.loader.initrdFile = "dummy";
|
||||
system.boot.loader.kernelFile = "<no-kernel>";
|
||||
system.boot.loader.initrdFile = "<no-initrd>";
|
||||
|
||||
# And totally obliterate device-specific files from stage-2.
|
||||
system.extraSystemBuilderCmds = ''
|
||||
|
@ -13,7 +13,7 @@ let
|
||||
'';
|
||||
in
|
||||
{
|
||||
config = mkIf (!config.mobile.rootfs.shared.enabled) {
|
||||
config = mkIf (config.mobile.enable && !config.mobile.rootfs.shared.enabled) {
|
||||
system.extraSystemBuilderCmds = ''
|
||||
echo ":: Adding Mobile NixOS information to the build..."
|
||||
(
|
||||
|
@ -7,6 +7,8 @@ let
|
||||
|
||||
# The platform selected by the configuration
|
||||
selectedPlatform = lib.systems.elaborate cfg.system;
|
||||
|
||||
isCross = selectedPlatform.system != localSystem.system;
|
||||
in
|
||||
{
|
||||
options.mobile = {
|
||||
@ -33,20 +35,11 @@ in
|
||||
}
|
||||
];
|
||||
|
||||
nixpkgs.crossSystem = lib.mkIf
|
||||
(
|
||||
let
|
||||
result = selectedPlatform.system != localSystem.system;
|
||||
in
|
||||
builtins.trace
|
||||
"Building with crossSystem?: ${selectedPlatform.system} != ${localSystem.system} → ${if result then "we are" else "we're not"}."
|
||||
result
|
||||
)
|
||||
(
|
||||
builtins.trace
|
||||
" crossSystem: config: ${selectedPlatform.config}"
|
||||
selectedPlatform
|
||||
)
|
||||
;
|
||||
nixpkgs.crossSystem = lib.mkIf isCross (
|
||||
builtins.trace ''
|
||||
Building with crossSystem?: ${selectedPlatform.system} != ${localSystem.system} → ${if isCross then "we are" else "we're not"}.
|
||||
crossSystem: config: ${selectedPlatform.config}''
|
||||
selectedPlatform
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@ -49,5 +49,12 @@ in
|
||||
message = "Cannot build unexpected system type: ${system_type}.\n Known types: ${lib.concatStringsSep ", " known_system_types}";
|
||||
}
|
||||
];
|
||||
|
||||
# When evaluating with the Mobile NixOS defaults disabled, we want
|
||||
# to use the `none` type so evaluation can continue.
|
||||
# Otherwise we want to error on an unset value if not set.
|
||||
mobile.system.type = mkIf (!config.mobile.enable) (
|
||||
lib.mkOptionDefault "none"
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, fetchurl
|
||||
, runCommandNoCC
|
||||
, initrd
|
||||
@ -36,7 +37,7 @@ let
|
||||
};
|
||||
|
||||
# Kernel used in kpart.
|
||||
kernel_file = "${kernel}/${kernel.file}";
|
||||
kernel_file = "${kernel}/${if kernel ? file then kernel.file else stdenv.hostPlatform.linux-kernel.target}";
|
||||
|
||||
# Kernel command line for vbutil_kernel.
|
||||
kpart_config = writeTextFile {
|
||||
|
@ -10,7 +10,7 @@ let
|
||||
inherit (cfg) soc;
|
||||
deviceName = config.mobile.device.name;
|
||||
kernel = stage-0.mobile.boot.stage-1.kernel.package;
|
||||
kernel_file = "${kernel}/${kernel.file}";
|
||||
kernel_file = "${kernel}/${if kernel ? file then kernel.file else pkgs.stdenv.hostPlatform.linux-kernel.target}";
|
||||
|
||||
# Look-up table to translate from targetPlatform to U-Boot names.
|
||||
ubootPlatforms = {
|
||||
|
@ -10,7 +10,7 @@ let
|
||||
cfg = config.mobile.quirks.uefi;
|
||||
deviceName = config.mobile.device.name;
|
||||
kernel = stage-0.mobile.boot.stage-1.kernel.package;
|
||||
kernelFile = "${kernel}/${kernel.file}";
|
||||
kernelFile = "${kernel}/${if kernel ? file then kernel.file else pkgs.stdenv.hostPlatform.linux-kernel.target}";
|
||||
|
||||
# Look-up table to translate from targetPlatform to U-Boot names.
|
||||
uefiPlatforms = {
|
||||
|
@ -4,7 +4,7 @@ let
|
||||
# This particular VM module is only enabled for the uefi system type.
|
||||
enabled = config.mobile.system.type == "uefi";
|
||||
|
||||
inherit (lib) mkAfter mkIf mkOption types;
|
||||
inherit (lib) mkAfter mkIf mkMerge mkOption types;
|
||||
inherit (config.mobile) device hardware;
|
||||
inherit (config.mobile.boot) stage-1;
|
||||
inherit (config.mobile.outputs.uefi) disk-image;
|
||||
@ -16,6 +16,15 @@ in
|
||||
{
|
||||
options = {
|
||||
mobile = {
|
||||
quirks.uefi.enableVM = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
internal = true;
|
||||
description = ''
|
||||
Internal switch to select whether the `outputs.uefi.vm` value points
|
||||
to the composeConfig usage, or to the actual output.
|
||||
'';
|
||||
};
|
||||
outputs = {
|
||||
uefi = {
|
||||
vm = mkOption {
|
||||
@ -29,44 +38,53 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
config = mkIf enabled {
|
||||
boot.kernelParams = mkAfter [
|
||||
"console=ttyS0"
|
||||
];
|
||||
config = mkMerge [
|
||||
(mkIf config.mobile.quirks.uefi.enableVM {
|
||||
boot.kernelParams = mkAfter [
|
||||
"console=ttyS0"
|
||||
];
|
||||
|
||||
mobile.boot.stage-1.kernel.modules = [
|
||||
# Networking
|
||||
"e1000"
|
||||
mobile.boot.stage-1.kernel.modules = [
|
||||
# Networking
|
||||
"e1000"
|
||||
|
||||
# Input within X11
|
||||
"uinput" "evdev"
|
||||
# Input within X11
|
||||
"uinput" "evdev"
|
||||
|
||||
# Video
|
||||
"bochs_drm"
|
||||
];
|
||||
mobile.outputs.uefi = {
|
||||
vm = pkgs.writeShellScript "run-vm-${device.name}" ''
|
||||
ARGS=(
|
||||
-enable-kvm
|
||||
-bios "${pkgs.OVMF.fd}/FV/OVMF.fd"
|
||||
-m "${ram}M"
|
||||
-serial "mon:stdio"
|
||||
-drive "file=${disk-image}/${disk-image.filename},format=raw,snapshot=on"
|
||||
# Video
|
||||
"bochs_drm"
|
||||
];
|
||||
mobile.outputs.uefi = {
|
||||
vm = pkgs.writeShellScript "run-vm-${device.name}" ''
|
||||
ARGS=(
|
||||
-enable-kvm
|
||||
-bios "${pkgs.OVMF.fd}/FV/OVMF.fd"
|
||||
-m "${ram}M"
|
||||
-serial "mon:stdio"
|
||||
-drive "file=${disk-image}/${disk-image.filename},format=raw,snapshot=on"
|
||||
|
||||
-device "VGA,edid=on,xres=${xres},yres=${yres}"
|
||||
-device "usb-ehci"
|
||||
-device "usb-kbd"
|
||||
-device "usb-tablet"
|
||||
-device "VGA,edid=on,xres=${xres},yres=${yres}"
|
||||
-device "usb-ehci"
|
||||
-device "usb-kbd"
|
||||
-device "usb-tablet"
|
||||
|
||||
-device "e1000,netdev=net0"
|
||||
-netdev "user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::2323-:23,net=172.16.42.0/24,dhcpstart=172.16.42.1"
|
||||
-device "e1000,netdev=net0"
|
||||
-netdev "user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::2323-:23,net=172.16.42.0/24,dhcpstart=172.16.42.1"
|
||||
|
||||
-device "e1000,netdev=user.0"
|
||||
-netdev "user,id=user.0"
|
||||
)
|
||||
-device "e1000,netdev=user.0"
|
||||
-netdev "user,id=user.0"
|
||||
)
|
||||
|
||||
${pkgs.qemu}/bin/qemu-system-${pkgs.stdenv.targetPlatform.qemuArch} "''${ARGS[@]}" "''${@}"
|
||||
'';
|
||||
};
|
||||
};
|
||||
${pkgs.qemu}/bin/qemu-system-${pkgs.stdenv.targetPlatform.qemuArch} "''${ARGS[@]}" "''${@}"
|
||||
'';
|
||||
};
|
||||
})
|
||||
(mkIf (!config.mobile.quirks.uefi.enableVM) {
|
||||
mobile.outputs.uefi.vm = (config.lib.mobile-nixos.composeConfig {
|
||||
config = {
|
||||
mobile.quirks.uefi.enableVM = true;
|
||||
};
|
||||
}).config.mobile.outputs.uefi.vm;
|
||||
})
|
||||
];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user